Wikipedia
piwiki
https://pi.wikipedia.org/wiki/%E0%A4%AA%E0%A4%AE%E0%A5%81%E0%A4%96_%E0%A4%AA%E0%A4%A4%E0%A5%8D%E0%A4%A4_Pamukha_patta
MediaWiki 1.47.0-wmf.24
first-letter
मीडिया
विसेस
सम्भासित
अवयव
अवयव सम्भासित
Wikipedia
Wikipedia सम्भासित
पटिमा
पटिमा सम्भासित
मीडियाविकि
मीडियाविकि सम्भासित
पटिरूप
पटिरूप सम्भासित
अवस्सय
अवस्सय सम्भासित
विभाग
विभाग सम्भासित
TimedText
TimedText talk
Module
Module talk
Event
Event talk
पाळिभासा
0
7571
110852
104502
2026-10-23T18:57:50Z
InternetArchiveBot
5946
Rescuing 1 sources and tagging 0 as dead.) #IABot (v2.0.9.6
110852
wikitext
text/x-wiki
{{Infobox language
|name=पाळि
|pronunciation= {{IPA-all|paːli|}}
|states=जम्बुदीप
|era=बीसी पञ्चसतपुब्ब तो एकसतपुब्ब
|ref=<ref>Nagrajji (2003) "Pali language and the Buddhist Canonical Literature". ''Agama and Tripitaka'', vol. 2: Language and Literature.</ref>
|speakers2=
|familycolor=Indo-European
| fam2 = [[इंडो-ईरानी भाषा|इंडो-ईरानी]]
| fam3 = [[इंडो-आर्यन भाषा|इंडो-आर्यन]]
| fam4 = [[मज्झिमइंडो-आर्यन भाषा|मज्झिमइंडो-आर्यन भाषा]]
| iso1 = pi
| iso2 = pli
| iso3 = pli
| linglist = pli
| notice = Indic
| glotto = pali1273
| glottorefname = Pali
| notice2 = IPA
}}
[[File:Sanskrit-Pali Faulmann Gesch T10.jpg|thumb|350px|उपरिभागे देवनागरी अक्खरेहि सक्कटभासाय लिखितं विस्सणुनो पत्थनावचनं अत्थि। हेट्ठाभागे मरम्मरट्ठतो लद्धं कम्मवाचापाळि अत्थि॥]]
'''पाळिभासा''' जम्बुदीपस्स अन्तोदेसे जातानं मनुस्सानं मातुभासा अहोसि॥ इमस्स भासास्स महन्तेन पमाणेन अज्झयनकरणस्स हेतु सब्बञ्ञुबुद्धस्स अनग्घानि सासनिकगन्थानि तिपिटके पाळिभासाय सङ्गहेत्वा ठपितत्ता होति॥
[[पटिमा:Distinctions in Pali.webm|thumb|सब्बजातियानं पाळिभासाय विसेसं विभावेन्तो पाळिभासाकुसलो [[रामञ्ञमनुस्सा|रामञ्ञ]]पण्डितो॥]]
==मूलसन्तकिञ्च भासाय उपचियमानअक्कम==
===वोहारयोनि===
पाळि इति सद्दं थेरवादबुद्धमामकेहि उपयुत्तं अहोसि॥ सुतेसिनो पाळि सद्दस्स अत्थं धातुञ्च नानाविधं विवरन्ति। लिखनरूपम्पि न समं होति॥ R. C. Childers पाळि इति "आवलि" अत्थो होतीति आह॥<ref>Hazra, Kanai Lal. ''Pāli Language and Literature; a systematic survey and historical study.'' D.K. Printworld Lrd., New Delhi, 1994, page 19.</ref>
पाळिभासाय अन्तिकतरं दिस्समानं सासनिक इहानि अधिप्पायं पच्छिम जम्बुदीपे गुज्जररट्ठे धम्मासोकमहाराजस्स सिलालेखा भवन्ति॥<ref name="Hirakawa, Akira 2007. p. 119">Hirakawa, Akira. Groner, Paul. ''A History of Indian Buddhism: From Śākyamuni to Early Mahāyāna.'' 2007. p. 119</ref>
==== मरम्मरट्ठे विभावना====
पाळिभासाय मूलट्ठानं सक्कतभासाया विय जम्बुदीपोयेव होति॥ जम्बुदीपेपि मगधरट्ठे भासितत्ता इमं मागधभासा ति वुच्चति॥ लोके पठमं उप्पन्नभासा ताव होति। तस्मा मूलभासा तिपि वुच्चति॥ तं मागधमूलभासां कप्पादिका मनुस्सा च। ब्रह्मानो च। अञ्ञेसं सद्दं अस्सुतपुब्बा दहरा कुमारा च। सम्मासम्बुद्धा च भासन्ती ति गन्थेसु आगतं॥ एवं कप्पादितो पट्ठाय आगता एसा पाळिभासा दोसकलङ्केहि विमुत्ता सुद्धा निज्जटा मूलभासायेव होति॥ अञ्ञासु अञ्ञतरासु भासासु अक्खरानं बहुत्ता अत्थानं संकिण्णता। दुब्बुज्झनता। परिपुण्णवोहारानं अभावो। विसज्जनीयस्स बहुत्ता। नासिकासद्दलक्खणं। अब्यत्ताक्खरता। फरुसस्सरो। अक्खरब्यञ्जनानं अतिबहुत्तं वा अत्यप्पत्तं वा ति अनेकविधा दोसा सन्ति॥ पाळिभासा पन एतेहि दोसेहि सब्बथा विमुत्ता सद्दतो च अत्थतो च परिपुण्णा सात्थसब्यञ्जनगुणेहि समन्नागता महाभासा होति॥
एवं सात्थसब्यञ्जनगुण समन्नागतत्ता बुद्धमुखपाठं परियत्तिं रक्खितुं समत्था भासा होति। तस्मा "पाति रक्खतीति पाळि" इिति वचनत्थानुरूपं पाळि त्येव वुच्चति॥ इमिस्सा पाळिभासाया आवस्सिकत्तं विनयपिटके अधिप्पायतो अतिविय पाकटं होति॥ तं चिरट्ठितं चन॥ पब्बज्जा। उपसम्पदा कम्मवाचादिनि अञ्ञाय भासाय धारेत्वा निप्फादेतुं न सक्कोन्ति। पाळिभासायेव सुविहितं रुळ्हिय वाचेत्वा निप्फादेतब्बानि होन्ति॥ पि च। इमस्मिं कप्पे पुब्बे उप्पन्ना ककुसन्धादिनो बुद्धा च। पुब्बे कप्पेसु उप्पन्नपुब्बा बुद्धा च इमाय पाळिभासायेव वेनेय्यसत्तानं सधम्मं देसेन्ति॥ अम्हेहि सरणं गतो गोतमसम्मासम्बुद्धोपि वेनेय्यानं धम्मामतं पायेत्वा अनुसासन्तो इमाय पाळिभासायेव देसेसि॥ अनागते उप्पज्जिस्सन्ता बुद्धापि पाळिभासायेव धम्मं देसेस्सन्ति॥ तिपिटकसङ्खातं परियत्तिधम्मं संगायन्ता आयस्मा महाकस्सपादयो महाथेरापि पाळिभासायेव संगायिंसू॥ पाळिभासा नाम वित्थारताय अतिगम्भीरा महाभासा होति। तस्मा पद। पाठ। कम्म। कत्तादि-नयानं परिवत्तन निम्मित मग्गे धारेन्ता अनेकेसु सद्दसत्थेसु पुराणाचरियेहि गन्था रचिता होन्ति॥
एसा पाळिभासा मरम्मरट्ठं अनुरुद्धदेवमहाराजस्स कालतो पुब्बेपि पत्ता। अनुरुद्धराजस्स काले महाथेरस्स अरहन्तस्स आनुभावेन अतिविय विरूळ्हा आसि॥ ततो पट्ठाय बुद्धमामका मरम्मराजानो पाळिभासां अतिविय उपत्थम्भेसुं॥ तस्मा पुकं समये मरम्मरट्ठे जना सब्बेसम्पि पाळिभासां परिसीलेन्ति॥ इत्थियोपि ओदनं पचन्तियो उदकं आहरन्तियो पाळिभासां लिखन्ति ति आमणना सन्ति॥ तस्मिं काले अञ्ञतरा इत्थियो पाळिचापे परं वाचेतुं सक्कोन्ति। सत्थगन्थे रचयितुं सक्कोन्ति तिपि अनुस्सति सन्ति॥ विभत्यत्थ नाम सद्दन्तरगन्थो जयसीह राजस्स धीताय रचितो सद्दगन्थो होति॥ अपि च जयसीहराजस्स धीता थान प्यिनराजकुमारी चापं वाचेन्तिं भिक्खुपि उपसंकमित्वा उग्गण्हन्ति ति। अञ्ञतरो तिस्सा सिस्सभिक्खु थान प्यिनराजकुमारिया सम्बन्धं आकङ्खित्वा राजिनो सन्तिके याचिते "एकं गन्थं रचयितुं सक्कोन्तोयेव मामकीं धीतरं लभिस्सति" ति राजा आणापेसि॥ तदा थेरो न्यासगन्थस्स अत्थसंवण्णनायी तीकागन्थं पाळिभासाय रचयित्वा राजिनो उपहरति। राजा पसन्नमानसो धीतरं तस्सा पादमूलिकं अदासि ति राजवंसेसु सुय्यति॥ अज्जतने पन पाळिभासां भिक्खुविहारेसु च विज्जालयेसु चेव अभियुञ्जित्वा परिसीलेन्ति॥ पुब्बे विय जना सब्बे न उस्सहन्ति॥ अत्थतो पन बुद्धवादिनो सब्बेसम्पि परिसीलितब्बा होति॥ हेतु पन: सम्मासम्बुद्धस्स अनुसासनि। मग्ग फल निब्बान पत्ति मग्गो तिपिटकभासांसुयेव तिट्ठति॥ तिपिटकचापं पाळिभासायेव सण्ठितं॥ मरम्मभासाय परिवत्तिता पिटकगन्था सन्ति। निज्जटं पाळिभासां सयं जानन्तो पुग्गलो यावता सब्बं जानाति। तावता मरम्मभासामत्तेन ञातुं न सक्कोति॥ अपि च मरम्मभासाय अन्तो सील। समाधि। पञ्ञा आदीनि पाळिवोहारानि यावता सक्कोन्ति इध पाविसिंसू। तस्मा अज्जपि पाळिभासा मरम्मभासायेव ति आसंकितुं वट्टति॥ मरम्मभासाय रचितेसु गन्थेसु तानि पाळिवोहारानि पाविसेत्वा लिखितत्ता पाळिं अकुसलो पुग्गलो मरम्मभासां सम्मा तिरच्छातुं दुक्करं होति॥
==भासाबेद==
===अक्खरानि===
पाळिभासायं अुपयुत्तानि अक्खरानि एकचत्तालीस (४१) होन्ति॥ तानि एकचत्तालीस अक्खरानि अट्ठ (८) सरा च। तेत्तिंस (३३) ब्यञ्जनानि च ति द्विधा विभत्तानि होन्ति॥
=== सरा (८)===
सरा (८) नाम: "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}। इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}। उ (u){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥ.wav|listen}}। उू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥူ.wav|listen}}। ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}। ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}" ति होन्ति॥
{| class="wikitable"
|+
!
! colspan="2" |मूलसरा
!गुणसर
!वुद्धिसरा
(पाळिभासायं न यूज्यते। सक्कते यूज्यते। पाळिरूपसिद्धियं उपकारकं होति॥)
|-
!सरयुगळानि
!रस्ससरा
(अलहुस्सरा)
!दीघसर
(लहुस्सरा)
!
!
|-
|पठमा रस्सदीघयुगळा
|style="background:gold;text-align:center"|अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}
|style="background:gold;text-align:center"|आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}
|
|
|-
|दुतिया रस्सदीघयुगळा
|style="background:gold;text-align:center"|इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}
|style="background:gold;text-align:center"|इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}
|style="background:#a57c00;text-align:center"|ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}
|style="background:#db9d00;text-align:center"|ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}
|-
|ततिया रस्सदीघयुगळा
|style="background:gold;text-align:center"|अु (u){{audio|LL-Q100271134 (mis)-咽頭べさ-အု.wav|listen}}
|style="background:gold;text-align:center"|अू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-အူ.wav|listen}}।
|style="background:#a57c00;text-align:center"|ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}
|style="background:#db9d00;text-align:center"|ओो (ou){{audio|LL-Q100271134 (mis)-咽頭べさ-အော.wav|listen}}
|}
तेसु अट्ठसु सरेसु "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}। इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}। उ (u){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥ.wav|listen}}। उू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥူ.wav|listen}}। ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}। ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}" ति एते अट्ठानुरूपा मूलसरा नाम होन्ति॥ "ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}। ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}" ति सरा पन तेहि मूलसरेहि अभिवुद्धिं पत्ता सरा होन्ति। तस्मा "गुणसरा" ति वुच्चन्ति॥ {{efn|अधिप्पायो पन: "ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}" सरो नाम "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}} + इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}" ति एतेसं संयोगेन भवितो होति॥ "ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}"}} सरो नाम "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}} + इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}" ति एतेसं संयोगेन भवितो होति॥
मूलसरेसु ६ सरेसु "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। उ (u) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဥ.wav|listen}}" ति एते रस्ससरा नाम होन्ति॥ "आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}। उू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥူ.wav|listen}}" ति एते दीघसरा नाम होन्ति॥ "अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}" ति पठमं यूयं॥ "इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}" ति दुतियं यूयं॥ "उ (u) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဥ.wav|listen}}। उू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥူ.wav|listen}}" ति ततियं यूयं॥ एवं मूलसरा (६) तयो रस्सदीघयुगळा होन्ति॥
# मूलसरा : अ (a){{audio|LL-Q100271134 (mis)-咽頭べさ-အ.wav|listen}}। आ (ā){{audio|LL-Q100271134 (mis)-咽頭べさ-အာ.wav|listen}}। इ (i){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣ.wav|listen}}। इी (ī){{audio|LL-Q100271134 (mis)-咽頭べさ-ဣဳ.wav|listen}}। उ (u) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဥ.wav|listen}}। उू (ū){{audio|LL-Q100271134 (mis)-咽頭べさ-ဥူ.wav|listen}}
# गुणसरा: ए (e){{audio|LL-Q100271134 (mis)-咽頭べさ-ဨ.wav|listen}}၊ ओ (o){{audio|LL-Q100271134 (mis)-咽頭べさ-ဩ.wav|listen}}
===ब्यञ्जनानि ३३===
ब्यञ्जनानि वग्गब्यञ्जनं च अवग्गब्यञ्जनञ्च ति द्विधा ठितानि॥ '''<nowiki/>'वग्गब्यञ्जनं'<nowiki/>''' नाम वग्ग आकारेन संगहितानि ब्यञ्जनानि होन्ति॥ '''<nowiki/>'अवग्गब्यञ्जनं'''' नाम वग्गतो मुत्तानि ब्यञ्जनानि होन्ति॥ वग्गब्यञ्जनानि पञ्चवीसति (२५)। अवग्गब्यञ्जनानि अट्ठ (८) होन्ति॥
तानि ब्यञ्जनानि अेतेनाकारेन तिट्ठन्ति॥
===वग्गब्यञ्जनानि २५===
{| class="wikitable"
|+
!ठानानि
!पथम
!दुतिय
!ततिय
!चतुत्थ
!पञ्चम
!वग्गो
|-
|१ कण्ठजं
(कण्ठे भवा अक्खरा)
|क
(ka){{audio|LL-Q100271134 (mis)-咽頭べさ-က.wav|listen}}
|ख
(kha){{audio|LL-Q100271134 (mis)-咽頭べさ-ခ.wav|listen}}
|ग
(ga){{audio|LL-Q100271134 (mis)-咽頭べさ-ဂ.wav|listen}}
|घ
(gha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဃ.wav|listen}}
|ङ
(ṅa){{audio|LL-Q100271134 (mis)-咽頭べさ-ၚ.wav|listen}}
|(क वग्गो)
|-
|२ तालुजं
(तालुस्मिं भवा अक्खरा)
|च
(ca){{audio|LL-Q100271134 (mis)-咽頭べさ-စ.wav|listen}}
|छ
(cha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဆ.wav|listen}}
|ज
(ja){{audio|LL-Q100271134 (mis)-咽頭べさ-ဇ.wav|listen}}
|झ
(jha){{audio|LL-Q100271134 (mis)-咽頭べさ-ၛ.wav|listen}}
|ञ्ञ
('''ñ'''a){{audio|LL-Q100271134 (mis)-咽頭べさ-ည.wav|listen}}
|(च वग्गो)
|-
|३ मुद्धजं
( मुद्धनि भवा अक्खरा)
|ट
(ṭa){{audio|LL-Q100271134 (mis)-咽頭べさ-ဋ.wav|listen}}
|ठ
(ṭha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဌ.wav|listen}}
|ड
(ḍa){{audio|LL-Q100271134 (mis)-咽頭べさ-ဍ.wav|listen}}
|ढ
(ḍha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဎ.wav|listen}}
|ण
(ṇa){{audio|LL-Q100271134 (mis)-咽頭べさ-ဏ.wav|listen}}
|(ट वग्गो)
|-
|४ दन्तज
(दन्तेसु भवा अक्खरा)
|त
(ta){{audio|LL-Q100271134 (mis)-咽頭べさ-တ.wav|listen}}
|थ
(tha){{audio|LL-Q100271134 (mis)-咽頭べさ-ထ.wav|listen}}
|द
(da){{audio|LL-Q100271134 (mis)-咽頭べさ-ဒ.wav|listen}}
|ध
(dha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဓ.wav|listen}}
|न
(na){{audio|LL-Q100271134 (mis)-咽頭べさ-န.wav|listen}}
|(त वग्गो)
|-
|५ ओट्ठजं
(ओट्ठे भवा अक्खरा)
|प
(pa){{audio|LL-Q100271134 (mis)-咽頭べさ-ပ.wav|listen}}
|फ
(pha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဖ.wav|listen}}
|ब
(ba){{audio|LL-Q100271134 (mis)-咽頭べさ-ဗ.wav|listen}}
|भ
(bha){{audio|LL-Q100271134 (mis)-咽頭べさ-ဘ.wav|listen}}
|म
(ma){{audio|LL-Q100271134 (mis)-咽頭べさ-မ.wav|listen}}
|(प वग्गो)
|}
===अवग्गब्यञ्जनानि ८===
य (ya) {{audio|LL-Q100271134 (mis)-咽頭べさ-ယ.wav|listen}}। र (ra) {{audio|LL-Q100271134 (mis)-咽頭べさ-ရ.wav|listen}}। ल (la) {{audio|LL-Q100271134 (mis)-咽頭べさ-လ.wav|listen}}। व (va) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဝ.wav|listen}}। स (sa) {{audio|LL-Q100271134 (mis)-咽頭べさ-သ.wav|listen}}। ह (ha) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဟ.wav|listen}}। ळ (ḷa) {{audio|LL-Q100271134 (mis)-咽頭べさ-ဠ.wav|listen}}। अं (ṃ) {{audio|LL-Q100271134 (mis)-咽頭べさ-အံ.wav|listen}}॥
==निस्सै==
{{Reflist|}}
* See entries for "Pali" (written by K. R. Norman of the Pali Text Society) and "India--Buddhism" in ''The Concise Encyclopedia of Language and Religion'', (Sawyer ed.) ISBN 0-08-043167-4
* {{cite book |last=Müller |first=Edward |year=1995 |orig-year=First published 1884 |title=Simplified Grammar of the Pali Language |publisher=Asian Educational Services |isbn=81-206-1103-9}}
* {{cite book |last=Silva |first=Lily de |year=1994 |title=Pali Primer |edition=first |publisher=Vipassana Research Institute Publications |isbn=81-7414-014-X}}
* {{cite book |last=Warder |first=A. K. |year=1991 |title=Introduction to Pali|edition= third |publisher=Pali Text Society |isbn=0-86013-197-1}}
==लिंक==
* Pali Text Society, London. [http://dsal.uchicago.edu/dictionaries/pali/ The Pali Text Society's Pali-English dictionary]. Chipstead, 1921-1925.
* [https://web.archive.org/web/20150921151757/http://www.palitext.com/ Pali Text Society] {{Webarchive|url=https://web.archive.org/web/20150921151757/http://www.palitext.com/ |date=21 September 2015 }}
* [http://dhamma.ru/paali/palisan.htm Reconstruction of Ancient Indian sound clusters on the basis of Pali sounds (according to "Grammatik des Pali" by Achim Fahs)]
* [https://web.archive.org/web/20210225203912/http://www.ahandfulofleaves.org/documents/Concise%20Pali%20English%20Dictionary_Buddhadatta.pdf Buddhadatta Mahāthera, A. P. (1958). Concise Pāli-English Dictionary.] {{Webarchive|url=https://web.archive.org/web/20210225203912/http://www.ahandfulofleaves.org/documents/Concise%20Pali%20English%20Dictionary_Buddhadatta.pdf |date=25 February 2021 }}
[[Category:पाळि| ]]
[[Category:बङ्गदेसस्स भासायो]]
[[Category:जम्बुदीपस्स भासायो]]
95qux97cazzxtsysz6c0aiktblr0xdw
अवयव सम्भासित:WikiBayer
3
13617
110853
2026-10-24T18:16:36Z
NDG
8149
/* Nuke */ new section
110853
wikitext
text/x-wiki
== Nuke ==
Hallo, kannst Du mir erklären, warum Du die Bearbeitungen von Intobesa nukest? [[User:NDG|NDG]] ([[User talk:NDG|talk]] • [[Special:Contributions/NDG|contribs]]) १८:१६, २४ अस्सयुजा २०२६ (यूतीसी)
p1b06efeudnkru1btwlhjpx2urb8jgw
110854
110853
2026-10-25T10:26:14Z
WikiBayer
5034
/* Nuke */ पटिवचनं देहि
110854
wikitext
text/x-wiki
== Nuke ==
Hallo, kannst Du mir erklären, warum Du die Bearbeitungen von Intobesa nukest? [[User:NDG|NDG]] ([[User talk:NDG|talk]] • [[Special:Contributions/NDG|contribs]]) १८:१६, २४ अस्सयुजा २०२६ (यूतीसी)
:Das war ein unabsichtlicher Bedienunsfehler stelle die wieder her [[User:WikiBayer|WikiBayer]] ([[User talk:WikiBayer|talk]] • [[Special:Contributions/WikiBayer|contribs]]) १०:२६, २५ अस्सयुजा २०२६ (यूतीसी)
eb9z1nzjgbs5was7y6dzddj43edk42u
110855
110854
2026-10-25T10:27:30Z
NDG
8149
/* Nuke */ पटिवचनं देहि
110855
wikitext
text/x-wiki
== Nuke ==
Hallo, kannst Du mir erklären, warum Du die Bearbeitungen von Intobesa nukest? [[User:NDG|NDG]] ([[User talk:NDG|talk]] • [[Special:Contributions/NDG|contribs]]) १८:१६, २४ अस्सयुजा २०२६ (यूतीसी)
:Das war ein unabsichtlicher Bedienunsfehler stelle die wieder her [[User:WikiBayer|WikiBayer]] ([[User talk:WikiBayer|talk]] • [[Special:Contributions/WikiBayer|contribs]]) १०:२६, २५ अस्सयुजा २०२६ (यूतीसी)
::Kannst Du mir erklären, wie dieser Bedienungsfehler zustandegekommen ist? Beim nuken habe ich so viele Anfragen, dass ich mir das gerade schwer vorstellen kann. [[User:NDG|NDG]] ([[User talk:NDG|talk]] • [[Special:Contributions/NDG|contribs]]) १०:२७, २५ अस्सयुजा २०२६ (यूतीसी)
oh7sfkm3mupapln3sq9perk8q1ttg6c
अवयव:WikiBayer/vector.js
2
13618
110856
2026-10-25T11:02:59Z
WikiBayer
5034
h
110856
javascript
text/javascript
//
// Skriptname: [Gadget-Massdelete.js]
// Autor: [WikiBayer]
// Datum: [2026]
// Beschreibung: [MassDelete - Massenlöeschung, -wiederherstellung und Logbuchlöschung]
// Version: [2.0.0]
// <nowiki>
(function () {
"use strict";
var CONSTANTS = {
MAX_PAGES_PER_REQUEST: 500,
DEFAULT_DELAY_PAGES: 286,
DEFAULT_DELAY_REVLOG: 67,
MIN_DELAY_PAGES: 250,
MAX_DELAY_PAGES: 2000,
MIN_DELAY_REVLOG: 50,
MAX_DELAY_REVLOG: 125,
LOG_ENTRIES_DEFAULT: 21,
LOG_ENTRIES_DISPLAY: 20,
USER_AGENT: "MassDelete/2.0.0",
PREVIEW_MAX_LENGTH: 300,
PREVIEW_SENTENCES: 3,
PREVIEW_BACKLINKS_LIMIT: 500,
TOOLTIP_DELAY_MS: 300,
GLOBAL_REASONS_PAGE: "MediaWiki:Gadget-Massdelete-reasons.json",
GLOBAL_REASONS_CROSSWIKI_PAGE: "MediaWiki:Gadget-Massdelete-crosswiki-reasons.json",
USER_REASONS_SUFFIX: "/Gadget-config/WB-Massdelete-Reasons.json"
};
var TRANSLATIONS = {
de: {
title: "Massenlöschung & Wiederherstellung",
description:
"Massenlöschung und -wiederherstellung von Seiten. Der Benutzer ist für seine Handlungen selbst verantwortlich.",
infoText:
"Laut Systemadministratoren sollte aufgrund der Datenbankauslastung maximal nur 1 Seite pro Sekunde gelöscht werden. Alternativ:",
deleteTab: "Löschen",
undeleteTab: "Wiederherstellen",
logdelTab: "Logbuchlöschung",
username: "Benutzername",
usernamePlaceholder: "Benutzername eingeben...",
namespace: "Namensraum",
namespaceAll: "Alle Namensräume",
timeFilter: "Zeitfilter",
timeFilterNone: "Kein Filter",
timeFilterWeek: "Letzte 7 Tage",
timeFilterMonth: "Letzter Monat (30 Tage)",
timeFilterYear: "Letztes Jahr",
getPages: "Seiten abrufen",
getDeletedPages: "Gelöschte Seiten abrufen",
loadingPages: "Lade Seiten...",
loadingDeletedPages: "Lade gelöschte Seiten...",
noPagesFound: "Keine Seiten gefunden",
noDeletedPagesFound: "Keine gelöschten Seiten gefunden",
pagesAdded: "Seiten hinzugefügt",
deletedPagesAdded: "Gelöschte Seiten hinzugefügt",
alreadyInList: "bereits vorhanden",
allPagesInList: "Alle Seiten bereits in der Liste",
pagesToDelete: "Zu löschende Seiten (eine pro Zeile)",
pagesToUndelete: "Zu wiederherzustellende Seiten (eine pro Zeile)",
pagesManualPlaceholder: "Optional: Seiten manuell eingeben (eine pro Zeile)",
addToList: "Zur Liste hinzufügen",
pagesList: "Seitenliste",
selectAll: "Alle auswählen",
deselectAll: "Alle abwählen",
clearList: "Liste leeren",
listCleared: "Liste geleert",
noPagesInTextbox: "Keine Seiten in der Textbox",
commonReasons: "Häufige Gründe",
insertReason: "Häufigen Grund einfügen…",
reasonLabel: "Grund",
reasonPlaceholder: "Grund eingeben...",
globalSysopAction: "GS/Steward action",
rateLimitPages: "Verzögerung zwischen Löschungen (Seiten)",
rateLimitRevLog: "Verzögerung zwischen Löschungen (Logeinträge)",
deleteButton: "Löschen",
undeleteButton: "Wiederherstellen",
logdelButton: "Logeinträge löschen",
processing: "Verarbeite",
of: "von",
pages: "Seiten",
logEntries: "Logeinträge",
completed: "Abgeschlossen",
failed: "Fehlgeschlagen",
deletions: "Löschungen",
undeletions: "Wiederherstellungen",
noPages: "Keine Seiten angegeben",
created: "Erstellt",
revisions: "Versionen",
pageLog: "Logbuch",
pageLinks: "Seitenlinks",
hide: "Ausblenden",
dismiss: "Schließen",
loadingPreview: "Lade Vorschau...",
noPreviewAvailable: "Keine Vorschau verfügbar",
previewLoadError: "Fehler beim Laden der Vorschau",
loading: "Laden...",
loadMoreEntries: "Mehr Einträge laden:",
moreAvailable: "mehr verfügbar",
logTypes: "Logbuchtypen",
logThanks: "Dankeschön",
logCreate: "Seitenerstellung",
logNewusers: "Benutzerkontenerstellung",
logBlock: "Sperrungen (eingehend)",
logAll: "Alle Logbücher",
getLogEntries: "Logbücher laden",
loadingLogEntries: "Lade Logbucheinträge...",
noLogEntriesFound: "Keine Logeinträge gefunden",
noLogEntriesSelected: "Keine Logeinträge ausgewählt",
parameters: "Parameter",
hideContent: "Inhalt verstecken",
hideComment: "Kommentar verstecken",
hideUser: "Benutzername verstecken",
hideTitle: "Sperrziel verstecken",
blockOnlyInfo: "Bei Block-Logs kann nur das Sperrziel gelöscht werden.",
thanksOnlyInfo: "Bei Thanks-Logs kann nur der Benutzername gelöscht werden.",
mixedLogsNote: "Block- und Thanks-Logs werden mit ihren speziellen Optionen separat verarbeitet.",
logID: "LogID",
jobStatsTitle: "Aufgaben-Status",
totalPages: "Seiten insgesamt",
totalLogEntries: "Logeinträge insgesamt",
successCount: "Erfolgreich",
failedCount: "Fehlgeschlagen",
selectAtLeastOne: "Bitte mindestens eine Option auswählen"
},
en: {
title: "Mass Delete & Restore",
description: "Mass deletion and restoration of pages. The user is responsible for their own actions.",
infoText:
"According to system administrators, only 1 page per second should be deleted due to database load. Alternatively:",
deleteTab: "Delete",
undeleteTab: "Restore",
logdelTab: "Log Deletion",
username: "Username",
usernamePlaceholder: "Enter username...",
namespace: "Namespace",
namespaceAll: "All namespaces",
timeFilter: "Time filter",
timeFilterNone: "No filter",
timeFilterWeek: "Last 7 days",
timeFilterMonth: "Last month (30 days)",
timeFilterYear: "Last year",
getPages: "Get pages",
getDeletedPages: "Get deleted pages",
loadingPages: "Loading pages...",
loadingDeletedPages: "Loading deleted pages...",
noPagesFound: "No pages found",
noDeletedPagesFound: "No deleted pages found",
pagesAdded: "pages added",
deletedPagesAdded: "Deleted pages added",
alreadyInList: "already in list",
allPagesInList: "All pages already in list",
pagesToDelete: "Pages to delete (one per line)",
pagesToUndelete: "Pages to restore (one per line)",
pagesManualPlaceholder: "Optional: Enter pages manually (one per line)",
addToList: "Add to list",
pagesList: "Pages list",
selectAll: "Select all",
deselectAll: "Deselect all",
clearList: "Clear list",
listCleared: "List cleared",
noPagesInTextbox: "No pages in textbox",
commonReasons: "Common reasons",
insertReason: "Insert common reason…",
reasonLabel: "Reason",
reasonPlaceholder: "Enter reason...",
globalSysopAction: "GS/Steward action",
rateLimitPages: "Delay between deletions (pages)",
rateLimitRevLog: "Delay between deletions (log entries)",
deleteButton: "Delete",
undeleteButton: "Restore",
logdelButton: "Delete log entries",
processing: "Processing",
of: "of",
pages: "pages",
logEntries: "log entries",
completed: "Completed",
failed: "Failed",
deletions: "deletions",
undeletions: "restorations",
noPages: "No pages specified",
created: "Created",
revisions: "Revisions",
pageLog: "Log",
pageLinks: "Page links",
hide: "Hide",
dismiss: "Dismiss",
loadingPreview: "Loading preview...",
noPreviewAvailable: "No preview available",
previewLoadError: "Error loading preview",
loading: "Loading...",
loadMoreEntries: "Load more entries:",
moreAvailable: "more available",
logTypes: "Log types",
logThanks: "Thanks",
logCreate: "Page creation",
logNewusers: "User account creation",
logBlock: "Blocks (incoming)",
logAll: "All logs",
getLogEntries: "Load logs",
loadingLogEntries: "Loading log entries...",
noLogEntriesFound: "No log entries found",
noLogEntriesSelected: "No log entries selected",
parameters: "Parameters",
hideContent: "Hide content",
hideComment: "Hide comment",
hideUser: "Hide username",
hideTitle: "Hide block target",
blockOnlyInfo: "For block logs, only the block target can be deleted.",
thanksOnlyInfo: "For thanks logs, only the username can be deleted.",
mixedLogsNote: "Block and thanks logs will be processed separately with their special options.",
logID: "LogID",
jobStatsTitle: "Job Statistics",
totalPages: "Total pages",
totalLogEntries: "Total log entries",
successCount: "Successful",
failedCount: "Failed",
selectAtLeastOne: "Please select at least one option"
}
};
function t(key) {
var lang = mw.config.get("wgUserLanguage") || "en";
var dict = TRANSLATIONS[lang] || TRANSLATIONS.en;
if (dict[key] !== undefined) return dict[key];
if (TRANSLATIONS.en[key] !== undefined) return TRANSLATIONS.en[key];
return key;
}
var RequestQueue = {
delayPages: CONSTANTS.DEFAULT_DELAY_PAGES,
delayRevLog: CONSTANTS.DEFAULT_DELAY_REVLOG,
queue: [],
processing: false,
lastRequestTime: 0,
getDelay: function (type) {
return type === "revlog"
? Math.max(CONSTANTS.MIN_DELAY_REVLOG, Math.min(CONSTANTS.MAX_DELAY_REVLOG, this.delayRevLog))
: Math.max(CONSTANTS.MIN_DELAY_PAGES, Math.min(CONSTANTS.MAX_DELAY_PAGES, this.delayPages));
},
addRequest: function (requestFunction, type) {
var self = this;
return new Promise(function (resolve, reject) {
self.queue.push({
requestFunction: requestFunction,
resolve: resolve,
reject: reject,
type: type || "pages"
});
if (!self.processing) self.processQueue();
});
},
processQueue: async function () {
if (this.queue.length === 0) {
this.processing = false;
return;
}
this.processing = true;
while (this.queue.length > 0) {
var type = this.queue[0].type;
var delay = this.getDelay(type);
var now = Date.now();
var timeSinceLastRequest = now - this.lastRequestTime;
if (this.lastRequestTime > 0 && timeSinceLastRequest < delay) {
await new Promise(function (r) {
setTimeout(r, delay - timeSinceLastRequest);
});
}
var job = this.queue.shift();
try {
var result = await job.requestFunction();
job.resolve(result);
} catch (error) {
job.reject(error);
}
this.lastRequestTime = Date.now();
}
this.processing = false;
},
reset: function () {
this.queue = [];
this.processing = false;
this.lastRequestTime = 0;
}
};
function getReasonLabel(reason) {
var userLang = mw.config.get("wgUserLanguage") || "en";
if (!reason) return "";
if (typeof reason.label === "string") return reason.label;
return (reason.label && (reason.label[userLang] || reason.label.en)) || reason.value || "";
}
function buildReasonMenuItems(reasonsArray) {
var items = [];
var groupCounter = 0;
(reasonsArray || []).forEach(function (entry) {
if (entry && entry.group) {
groupCounter++;
items.push({
label: getReasonLabel({ label: entry.group }),
value: "__group__" + groupCounter,
disabled: true
});
(entry.reasons || []).forEach(function (reason) {
items.push({
label: "\u00A0\u00A0" + getReasonLabel(reason),
value: reason.value
});
});
} else if (entry) {
items.push({ label: getReasonLabel(entry), value: entry.value });
}
});
return items;
}
async function loadReasons(api) {
var currentUser = mw.config.get("wgUserName");
async function tryPage(pageApi, title) {
try {
var response = await pageApi.get({
action: "query",
prop: "revisions",
titles: title,
rvprop: "content",
rvslots: "main",
formatversion: 2
});
var page = response.query && response.query.pages && response.query.pages[0];
if (page && !page.missing && page.revisions && page.revisions[0]) {
return JSON.parse(page.revisions[0].slots.main.content);
}
} catch (error) {
console.error("MassDelete: Error loading reasons from " + title, error);
}
return null;
}
if (currentUser) {
var userReasonsPage = "User:" + currentUser + CONSTANTS.USER_REASONS_SUFFIX;
var userData = await tryPage(api, userReasonsPage);
if (userData) {
console.log("MassDelete: Loaded user-specific reasons from " + userReasonsPage);
return {
delete: userData.delete || [],
undelete: userData.undelete || [],
logdel: userData.logdel || []
};
}
}
var globalData = await tryPage(api, CONSTANTS.GLOBAL_REASONS_PAGE);
if (globalData) {
console.log("MassDelete: Loaded global reasons from " + CONSTANTS.GLOBAL_REASONS_PAGE);
return {
delete: globalData.delete || [],
undelete: globalData.undelete || [],
logdel: globalData.logdel || []
};
}
try {
var wikidataApi = new mw.ForeignApi("https://www.wikidata.org/w/api.php", {
userAgent: CONSTANTS.USER_AGENT
});
var crosswikiData = await tryPage(wikidataApi, CONSTANTS.GLOBAL_REASONS_CROSSWIKI_PAGE);
if (crosswikiData) {
console.log(
"MassDelete: Loaded cross-wiki reasons from Wikidata: " + CONSTANTS.GLOBAL_REASONS_CROSSWIKI_PAGE
);
return {
delete: crosswikiData.delete || [],
undelete: crosswikiData.undelete || [],
logdel: crosswikiData.logdel || []
};
}
} catch (error) {
console.error("MassDelete: Error loading cross-wiki reasons from Wikidata:", error);
}
console.warn("MassDelete: No reasons loaded, using empty arrays");
return { delete: [], undelete: [], logdel: [] };
}
async function getUserCreatedPages(api, username, namespace, timeFilterDays) {
var articles = [];
var seenPages = new Set();
var uccontinue;
var ucend = null;
if (timeFilterDays) {
ucend = new Date(Date.now() - timeFilterDays * 24 * 60 * 60 * 1000).toISOString();
}
do {
let params = {
action: "query",
list: "usercontribs",
ucuser: username,
uclimit: "max",
ucshow: "new",
ucprop: "title|timestamp",
format: "json"
};
if (uccontinue) params.uccontinue = uccontinue;
if (namespace !== "" && namespace !== null && namespace !== undefined) params.ucnamespace = namespace;
if (ucend) params.ucend = ucend;
var response = await RequestQueue.addRequest(function () {
return api.get(params);
});
var contribs = (response.query && response.query.usercontribs) || [];
contribs.forEach(function (contrib) {
if (!seenPages.has(contrib.title)) {
seenPages.add(contrib.title);
articles.push({ title: contrib.title, timestamp: contrib.timestamp });
}
});
uccontinue = response.continue ? response.continue.uccontinue : null;
} while (uccontinue);
return articles;
}
async function filterExistingPages(api, pages) {
var filteredPages = [];
var batchSize = 59;
for (let i = 0; i < pages.length; i += batchSize) {
let batch = pages.slice(i, i + batchSize);
let titles = batch
.map(function (p) {
return p.title;
})
.join("|");
var response = await RequestQueue.addRequest(function () {
return api.get({ action: "query", titles: titles, format: "json", formatversion: 2 });
});
var existingTitles = new Set();
if (response.query && response.query.pages) {
response.query.pages.forEach(function (page) {
if (!page.missing) existingTitles.add(page.title);
});
}
batch.forEach(function (page) {
if (!existingTitles.has(page.title)) filteredPages.push(page);
});
}
return filteredPages;
}
async function getUserDeletedPages(api, username, namespace, timeFilterDays) {
var deletedPages = [];
var seenPages = new Set();
var lecontinue;
var leend = null;
if (timeFilterDays) {
leend = new Date(Date.now() - timeFilterDays * 24 * 60 * 60 * 1000).toISOString();
}
do {
let params = {
action: "query",
list: "logevents",
leuser: username,
letype: "delete",
leaction: "delete/delete",
lelimit: "max",
leprop: "title|timestamp",
format: "json"
};
if (lecontinue) params.lecontinue = lecontinue;
if (namespace !== "" && namespace !== null && namespace !== undefined) params.lenamespace = namespace;
if (leend) params.leend = leend;
var response = await RequestQueue.addRequest(function () {
return api.get(params);
});
var logs = (response.query && response.query.logevents) || [];
logs.forEach(function (log) {
if (!seenPages.has(log.title)) {
seenPages.add(log.title);
deletedPages.push({ title: log.title, timestamp: log.timestamp });
}
});
lecontinue = response.continue ? response.continue.lecontinue : null;
} while (lecontinue);
if (deletedPages.length > 0) {
deletedPages = await filterExistingPages(api, deletedPages);
}
return deletedPages;
}
async function getLogEntries(api, username, logTypes, limit, timeFilterDays) {
var entries = [];
var lecontinue;
var remaining = limit;
var leend = null;
if (timeFilterDays) {
leend = new Date(Date.now() - timeFilterDays * 24 * 60 * 60 * 1000).toISOString();
}
do {
let fetchLimit = Math.min(remaining, CONSTANTS.MAX_PAGES_PER_REQUEST);
let params = {
action: "query",
list: "logevents",
leuser: username,
lelimit: fetchLimit,
leprop: "ids|title|type|user|timestamp|comment|details",
format: "json"
};
if (lecontinue) params.lecontinue = lecontinue;
if (logTypes && logTypes.length > 0 && logTypes.indexOf("") === -1) {
params.letype = logTypes.join("|");
}
if (leend) params.leend = leend;
var response = await RequestQueue.addRequest(function () {
return api.get(params);
}, "revlog");
var newEntries = (response.query && response.query.logevents) || [];
entries = entries.concat(newEntries);
remaining -= newEntries.length;
lecontinue = response.continue ? response.continue.lecontinue : null;
if (remaining <= 0) break;
} while (lecontinue);
return entries;
}
async function safeApiCall(errorLabel, fn) {
try {
return await fn();
} catch (error) {
console.error(errorLabel, error);
return null;
}
}
async function getPageRevisions(api, page, limit, rvcontinue) {
limit = limit || 10;
return safeApiCall("Error loading revisions:", async function () {
var params = {
action: "query",
titles: page,
prop: "revisions",
rvprop: "user|timestamp|comment|size|ids",
rvlimit: limit,
format: "json",
formatversion: 2
};
if (rvcontinue) params.rvcontinue = rvcontinue;
var response = await RequestQueue.addRequest(function () {
return api.get(params);
});
var pages = (response.query && response.query.pages) || [];
if (pages.length === 0 || pages[0].missing) return null;
return {
revisions: pages[0].revisions || [],
rvcontinue: response.continue ? response.continue.rvcontinue : null,
hasMore: !!response.continue
};
});
}
async function getPageLog(api, page, limit) {
limit = limit || 10;
return safeApiCall("Error loading page log:", async function () {
var response = await RequestQueue.addRequest(function () {
return api.get({
action: "query",
list: "logevents",
letitle: page,
leprop: "user|timestamp|comment|type|action|ids",
lelimit: limit,
format: "json",
formatversion: 2
});
});
return { logs: (response.query && response.query.logevents) || [] };
});
}
async function getPageBacklinks(api, page, limit, blcontinue) {
limit = limit || 10;
return safeApiCall("Error loading backlinks:", async function () {
var params = {
action: "query",
list: "backlinks",
bltitle: page,
bllimit: limit,
format: "json",
formatversion: 2
};
if (blcontinue) params.blcontinue = blcontinue;
var response = await RequestQueue.addRequest(function () {
return api.get(params);
});
return {
backlinks: (response.query && response.query.backlinks) || [],
blcontinue: response.continue ? response.continue.blcontinue : null,
hasMore: !!response.continue
};
});
}
async function fetchPagePreview(api, page) {
var response = await RequestQueue.addRequest(function () {
return api.get({
action: "query",
prop: "extracts",
titles: page,
exintro: true,
explaintext: true,
exsentences: CONSTANTS.PREVIEW_SENTENCES,
list: "backlinks",
bltitle: page,
bllimit: CONSTANTS.PREVIEW_BACKLINKS_LIMIT,
format: "json"
});
});
var pages = (response.query && response.query.pages) || {};
var firstKey = Object.keys(pages)[0];
var pageData = firstKey !== undefined ? pages[firstKey] : null;
var preview = null;
if (pageData && pageData.extract) {
preview = pageData.extract;
if (preview.length > CONSTANTS.PREVIEW_MAX_LENGTH) {
preview = preview.substring(0, CONSTANTS.PREVIEW_MAX_LENGTH) + "...";
}
}
var backlinks = (response.query && response.query.backlinks) || [];
return {
preview: preview,
backlinksCount: backlinks.length,
backlinksTruncated: !!(response.continue && response.continue.blcontinue)
};
}
function makePageListItem(title, timestamp) {
return {
title: title,
timestamp: timestamp || null,
showRevisions: false,
showLog: false,
showBacklinks: false,
revisionsLoading: false,
logLoading: false,
backlinksLoading: false,
revisionsData: null,
logData: null,
backlinksData: null
};
}
function addPagesToList(list, selected, pagesData) {
var existing = {};
list.forEach(function (p) {
existing[p.title] = true;
});
var added = 0;
(pagesData || []).forEach(function (pageData) {
var title = typeof pageData === "string" ? pageData : pageData.title;
if (!title || existing[title]) return;
existing[title] = true;
var timestamp = typeof pageData === "object" ? pageData.timestamp : null;
list.push(makePageListItem(title, timestamp));
selected.push(title);
added++;
});
return added;
}
function namespaceMenuItems(includeFileTalk) {
var items = [
{ value: "", label: t("namespaceAll") },
{ value: "0", label: t("namespace") + " 0 (Main)" },
{ value: "1", label: t("namespace") + " 1 (Talk)" },
{ value: "2", label: t("namespace") + " 2 (User)" },
{ value: "3", label: t("namespace") + " 3 (User talk)" },
{ value: "4", label: t("namespace") + " 4 (Project)" },
{ value: "6", label: t("namespace") + " 6 (File)" }
];
if (includeFileTalk) items.push({ value: "7", label: t("namespace") + " 7 (File talk)" });
return items;
}
function timeFilterMenuItems() {
return [
{ value: "", label: t("timeFilterNone") },
{ value: "7", label: t("timeFilterWeek") },
{ value: "30", label: t("timeFilterMonth") },
{ value: "365", label: t("timeFilterYear") }
];
}
var LOG_TYPE_OPTIONS = [
{ value: "", labelKey: "logAll" },
{ value: "thanks", labelKey: "logThanks" },
{ value: "create", labelKey: "logCreate" },
{ value: "newusers", labelKey: "logNewusers" },
{ value: "block", labelKey: "logBlock" }
];
function buildApp(Vue, Codex, api, initData) {
var h = Vue.h;
var ref = Vue.ref;
var reactive = Vue.reactive;
var computed = Vue.computed;
var watch = Vue.watch;
var onUnmounted = Vue.onUnmounted;
var Teleport = Vue.Teleport;
var CdxTabs = Codex.CdxTabs;
var CdxTab = Codex.CdxTab;
var CdxField = Codex.CdxField;
var CdxTextInput = Codex.CdxTextInput;
var CdxTextArea = Codex.CdxTextArea;
var CdxSelect = Codex.CdxSelect;
var CdxCheckbox = Codex.CdxCheckbox;
var CdxButton = Codex.CdxButton;
var CdxMessage = Codex.CdxMessage;
var CdxProgressBar = Codex.CdxProgressBar;
return {
name: "MassDeleteApp",
setup: function () {
var isGlobalUser = initData.isGlobalUser;
var globalUserText = initData.globalUserText;
var deleteReasonItems = buildReasonMenuItems(initData.reasons.delete);
var undeleteReasonItems = buildReasonMenuItems(initData.reasons.undelete);
var logdelReasonItems = buildReasonMenuItems(initData.reasons.logdel);
var namespaceItemsDelete = namespaceMenuItems(false);
var namespaceItemsUndelete = namespaceMenuItems(true);
var timeFilterItems = timeFilterMenuItems();
var logTypeItems = LOG_TYPE_OPTIONS.map(function (opt) {
return { value: opt.value, labelKey: opt.labelKey, label: t(opt.labelKey) };
});
var previewCache = {};
var activeTab = ref("delete");
var delayPages = ref(CONSTANTS.DEFAULT_DELAY_PAGES);
var delayRevLog = ref(CONSTANTS.DEFAULT_DELAY_REVLOG);
watch(delayPages, function (v) {
RequestQueue.delayPages = v;
});
watch(delayRevLog, function (v) {
RequestQueue.delayRevLog = v;
});
var deleteState = reactive({
username: "",
namespace: "",
timeFilter: "",
manualText: "",
pages: [],
selected: [],
loadingPages: false,
reasonPick: null,
reasonText: "",
globalSysop: false
});
var undeleteState = reactive({
username: "",
namespace: "",
timeFilter: "",
manualText: "",
pages: [],
selected: [],
loadingPages: false,
reasonPick: null,
reasonText: "",
globalSysop: false
});
var logdelState = reactive({
username: "",
timeFilter: "",
typeFilters: [],
entries: [],
selectedIds: [],
hideOptions: [],
loadingEntries: false,
hasMore: false,
reasonPick: null,
reasonText: "",
globalSysop: false
});
var logdelSelection = computed(function () {
var types = {};
var count = 0;
logdelState.entries.forEach(function (entry) {
if (logdelState.selectedIds.indexOf(entry.logid) !== -1 && !types[entry.type]) {
types[entry.type] = true;
count++;
}
});
var onlyBlock = count === 1 && !!types.block;
var onlyThanks = count === 1 && !!types.thanks;
var mode = count === 0 ? "none" : onlyBlock ? "onlyBlock" : onlyThanks ? "onlyThanks" : "mixed";
return { types: types, mode: mode, onlyBlock: onlyBlock, onlyThanks: onlyThanks };
});
watch(
function () {
return logdelSelection.value.mode;
},
function () {
logdelState.hideOptions = [];
}
);
var job = reactive({
visible: false,
kind: "delete",
totalLabelKey: "totalPages",
total: 0,
success: 0,
failed: 0
});
var progress = reactive({ visible: false, current: 0, total: 0, typeKey: "pages" });
var results = ref([]);
var running = ref(false);
var tooltip = reactive({ visible: false, x: 0, y: 0, text: "", linksInfo: "" });
var tooltipTimer = null;
function positionTooltipFromElement(el) {
if (!el) return;
var rect = el.getBoundingClientRect();
var tooltipWidth = 400;
var x = rect.right + 10;
if (x + tooltipWidth > window.innerWidth) {
x = Math.max(5, rect.left - tooltipWidth - 10);
}
tooltip.x = x;
tooltip.y = rect.top;
}
function hideTooltip() {
if (tooltipTimer) {
clearTimeout(tooltipTimer);
tooltipTimer = null;
}
tooltip.visible = false;
}
function onWindowScroll() {
tooltip.visible = false;
}
window.addEventListener("scroll", onWindowScroll, true);
function showTooltipFor(page, evt) {
if (tooltipTimer) clearTimeout(tooltipTimer);
var targetEl = evt.currentTarget;
tooltipTimer = setTimeout(function () {
positionTooltipFromElement(targetEl);
tooltip.visible = true;
if (previewCache[page] !== undefined) {
tooltip.text = previewCache[page].text;
tooltip.linksInfo = previewCache[page].linksInfo;
return;
}
tooltip.text = t("loadingPreview");
tooltip.linksInfo = "";
fetchPagePreview(api, page)
.then(function (result) {
var text = result.preview !== null ? result.preview : t("noPreviewAvailable");
var linksInfo =
result.backlinksCount +
(result.backlinksTruncated ? "+" : "") +
" " +
t("pageLinks");
previewCache[page] = { text: text, linksInfo: linksInfo };
if (tooltip.visible) {
tooltip.text = text;
tooltip.linksInfo = linksInfo;
}
})
.catch(function () {
if (tooltip.visible) {
tooltip.text = t("previewLoadError");
tooltip.linksInfo = "";
}
});
}, CONSTANTS.TOOLTIP_DELAY_MS);
}
function moveTooltip(evt) {
if (tooltip.visible) positionTooltipFromElement(evt.currentTarget);
}
function insertReasonPick(state, value) {
if (value && String(value).indexOf("__group__") !== 0) {
var current = (state.reasonText || "").trim();
state.reasonText = current ? current + "; " + value : value;
}
state.reasonPick = null;
}
function buildReason(state) {
var reason = (state.reasonText || "").trim();
if (isGlobalUser && state.globalSysop) {
reason = reason + " " + globalUserText;
}
return reason;
}
function fetchPagesForState(state, kind) {
var username = (state.username || "").trim();
if (!username) {
mw.notify(t("usernamePlaceholder"), { type: "error" });
return;
}
state.loadingPages = true;
var timeFilterDays = state.timeFilter ? parseInt(state.timeFilter, 10) : null;
var fetchPromise =
kind === "deleted"
? getUserDeletedPages(api, username, state.namespace, timeFilterDays)
: getUserCreatedPages(api, username, state.namespace, timeFilterDays);
fetchPromise
.then(function (pages) {
if (!pages || pages.length === 0) {
mw.notify(t(kind === "deleted" ? "noDeletedPagesFound" : "noPagesFound"), {
type: "warn"
});
return;
}
var added = addPagesToList(state.pages, state.selected, pages);
if (added > 0) {
var skipped = pages.length - added;
var message = added + " " + t(kind === "deleted" ? "deletedPagesAdded" : "pagesAdded");
if (skipped > 0) message += " (" + skipped + " " + t("alreadyInList") + ")";
mw.notify(message, { type: "success" });
} else {
mw.notify(t("allPagesInList"), { type: "info" });
}
})
.catch(function (error) {
mw.notify("Error: " + error, { type: "error" });
})
.finally(function () {
state.loadingPages = false;
});
}
function addManualPages(state) {
var lines = (state.manualText || "")
.split("\n")
.map(function (s) {
return s.trim();
})
.filter(Boolean);
if (lines.length === 0) {
mw.notify(t("noPagesInTextbox"), { type: "warn" });
return;
}
var added = addPagesToList(state.pages, state.selected, lines);
state.manualText = "";
if (added > 0) {
var skipped = lines.length - added;
var message = added + " " + t("pagesAdded");
if (skipped > 0) message += " (" + skipped + " " + t("alreadyInList") + ")";
mw.notify(message, { type: "success" });
} else {
mw.notify(t("allPagesInList"), { type: "info" });
}
}
function selectAllPages(state) {
state.selected = state.pages.map(function (p) {
return p.title;
});
}
function deselectAllPages(state) {
state.selected = [];
}
function toggleSelected(state, title) {
var idx = state.selected.indexOf(title);
if (idx === -1) {
state.selected.push(title);
} else {
state.selected.splice(idx, 1);
}
}
function clearPageList(state) {
state.pages = [];
state.selected = [];
mw.notify(t("listCleared"), { type: "success" });
}
function getPagesToProcess(state) {
if (state.selected.length > 0) return state.selected.slice();
return (state.manualText || "")
.split("\n")
.map(function (s) {
return s.trim();
})
.filter(Boolean);
}
function toggleRevisions(item) {
if (item.showRevisions) {
item.showRevisions = false;
return;
}
item.showRevisions = true;
if (item.revisionsData || item.revisionsLoading) return;
item.revisionsLoading = true;
getPageRevisions(api, item.title, 10, null)
.then(function (data) {
item.revisionsData = data;
})
.finally(function () {
item.revisionsLoading = false;
});
}
function loadMoreRevisions(item) {
if (!item.revisionsData || !item.revisionsData.hasMore) return;
item.revisionsLoading = true;
getPageRevisions(api, item.title, 10, item.revisionsData.rvcontinue)
.then(function (data) {
if (data) {
item.revisionsData = {
revisions: item.revisionsData.revisions.concat(data.revisions),
rvcontinue: data.rvcontinue,
hasMore: data.hasMore
};
}
})
.finally(function () {
item.revisionsLoading = false;
});
}
function toggleLog(item) {
if (item.showLog) {
item.showLog = false;
return;
}
item.showLog = true;
if (item.logData || item.logLoading) return;
item.logLoading = true;
getPageLog(api, item.title, 10)
.then(function (data) {
item.logData = data;
})
.finally(function () {
item.logLoading = false;
});
}
function toggleBacklinks(item) {
if (item.showBacklinks) {
item.showBacklinks = false;
return;
}
item.showBacklinks = true;
if (item.backlinksData || item.backlinksLoading) return;
item.backlinksLoading = true;
getPageBacklinks(api, item.title, 10, null)
.then(function (data) {
item.backlinksData = data;
})
.finally(function () {
item.backlinksLoading = false;
});
}
function loadMoreBacklinks(item) {
if (!item.backlinksData || !item.backlinksData.hasMore) return;
item.backlinksLoading = true;
getPageBacklinks(api, item.title, 10, item.backlinksData.blcontinue)
.then(function (data) {
if (data) {
item.backlinksData = {
backlinks: item.backlinksData.backlinks.concat(data.backlinks),
blcontinue: data.blcontinue,
hasMore: data.hasMore
};
}
})
.finally(function () {
item.backlinksLoading = false;
});
}
async function executePages(state, isDelete) {
var pages = getPagesToProcess(state);
if (!pages || pages.length === 0) {
mw.notify(t("noPages"), { type: "error" });
return;
}
var reason = buildReason(state);
running.value = true;
results.value = [];
job.kind = isDelete ? "delete" : "undelete";
job.totalLabelKey = "totalPages";
job.total = pages.length;
job.success = 0;
job.failed = 0;
job.visible = true;
progress.typeKey = "pages";
progress.total = pages.length;
progress.current = 0;
progress.visible = true;
var localResults = [];
for (let i = 0; i < pages.length; i++) {
let page = pages[i];
try {
await RequestQueue.addRequest(function () {
return api.postWithToken("csrf", {
action: isDelete ? "delete" : "undelete",
title: page,
reason: reason,
format: "json"
});
});
localResults.push({ page: page, success: true });
job.success++;
} catch (error) {
localResults.push({
page: page,
success: false,
error:
(error && error.error && error.error.info) ||
(error && error.toString()) ||
"Unknown error"
});
job.failed++;
}
progress.current = i + 1;
}
progress.visible = false;
results.value = localResults;
running.value = false;
var noticeMsg =
t("completed") +
": " +
job.success +
" " +
t("pages") +
(job.failed > 0 ? ", " + job.failed + " " + t("failed") : "");
mw.notify(noticeMsg, { type: job.success > 0 ? "success" : "error" });
}
function onLogTypeFiltersUpdate(newArr) {
var hadAll = logdelState.typeFilters.indexOf("") !== -1;
var hasAllNow = newArr.indexOf("") !== -1;
if (hasAllNow && !hadAll) {
logdelState.typeFilters = [""];
} else if (hasAllNow && newArr.length > 1) {
logdelState.typeFilters = newArr.filter(function (v) {
return v !== "";
});
} else {
logdelState.typeFilters = newArr;
}
}
function fetchLogEntriesForState() {
var username = (logdelState.username || "").trim();
if (!username) {
mw.notify(t("usernamePlaceholder"), { type: "error" });
return;
}
logdelState.loadingEntries = true;
var timeFilterDays = logdelState.timeFilter ? parseInt(logdelState.timeFilter, 10) : null;
getLogEntries(api, username, logdelState.typeFilters, CONSTANTS.LOG_ENTRIES_DEFAULT, timeFilterDays)
.then(function (entries) {
var hasMore = entries.length > CONSTANTS.LOG_ENTRIES_DISPLAY;
var displayEntries = hasMore ? entries.slice(0, CONSTANTS.LOG_ENTRIES_DISPLAY) : entries;
logdelState.entries = displayEntries;
logdelState.selectedIds = [];
logdelState.hasMore = hasMore;
if (displayEntries.length > 0) {
var msg =
displayEntries.length +
" " +
t("logEntries") +
(hasMore ? " (" + t("moreAvailable") + ")" : "");
mw.notify(msg, { type: "success" });
} else {
mw.notify(t("noLogEntriesFound"), { type: "warn" });
}
})
.catch(function (error) {
mw.notify("Error: " + error, { type: "error" });
})
.finally(function () {
logdelState.loadingEntries = false;
});
}
function loadMoreLogEntries(limit) {
var username = (logdelState.username || "").trim();
if (!username) return;
var timeFilterDays = logdelState.timeFilter ? parseInt(logdelState.timeFilter, 10) : null;
logdelState.loadingEntries = true;
getLogEntries(api, username, logdelState.typeFilters, limit, timeFilterDays)
.then(function (entries) {
logdelState.entries = entries;
logdelState.selectedIds = [];
logdelState.hasMore = false;
mw.notify(entries.length + " " + t("logEntries"), { type: "success" });
})
.catch(function (error) {
mw.notify("Error: " + error, { type: "error" });
})
.finally(function () {
logdelState.loadingEntries = false;
});
}
function selectAllEntries() {
logdelState.selectedIds = logdelState.entries.map(function (e) {
return e.logid;
});
}
function deselectAllEntries() {
logdelState.selectedIds = [];
}
async function executeLogDelete() {
var selectedIds = logdelState.selectedIds;
if (selectedIds.length === 0) {
mw.notify(t("noLogEntriesSelected"), { type: "error" });
return;
}
if (logdelState.hideOptions.length === 0) {
mw.notify(t("selectAtLeastOne"), { type: "error" });
return;
}
var reason = buildReason(logdelState);
var hideParam = logdelState.hideOptions.join("|");
var entriesByType = {};
logdelState.entries.forEach(function (entry) {
if (selectedIds.indexOf(entry.logid) === -1) return;
if (!entriesByType[entry.type]) entriesByType[entry.type] = [];
entriesByType[entry.type].push(entry.logid);
});
running.value = true;
results.value = [];
job.kind = "logdel";
job.totalLabelKey = "totalLogEntries";
job.total = selectedIds.length;
job.success = 0;
job.failed = 0;
job.visible = true;
progress.typeKey = "logEntries";
progress.total = selectedIds.length;
progress.current = 0;
progress.visible = true;
var localResults = [];
var processed = 0;
var logtypes = Object.keys(entriesByType);
for (let t2 = 0; t2 < logtypes.length; t2++) {
let logtype = logtypes[t2];
let logids = entriesByType[logtype];
let effectiveHideParam = hideParam;
if (logtype === "block") {
effectiveHideParam = "content";
} else if (logtype === "thanks") {
effectiveHideParam = "user";
}
try {
await RequestQueue.addRequest(function () {
return api.postWithToken("csrf", {
action: "revisiondelete",
type: "logging",
ids: logids.join("|"),
hide: effectiveHideParam,
reason: reason,
format: "json"
});
}, "revlog");
localResults.push({ page: logtype + " logs", success: true, count: logids.length });
job.success += logids.length;
} catch (error) {
localResults.push({
page: logtype + " logs",
success: false,
error:
(error && error.error && error.error.info) ||
(error && error.toString()) ||
"Unknown error",
count: logids.length
});
job.failed += logids.length;
}
processed += logids.length;
progress.current = processed;
}
progress.visible = false;
results.value = localResults;
running.value = false;
var noticeMsg =
t("completed") +
": " +
job.success +
" " +
t("logEntries") +
(job.failed > 0 ? ", " + job.failed + " " + t("failed") : "");
mw.notify(noticeMsg, { type: job.success > 0 ? "success" : "error" });
}
onUnmounted(function () {
if (tooltipTimer) clearTimeout(tooltipTimer);
window.removeEventListener("scroll", onWindowScroll, true);
RequestQueue.reset();
});
var STYLE = {
label: "font-size:13px;font-weight:600;margin-bottom:4px;color:var(--color-base,#202122)",
hint: "font-size:12px;color:var(--color-subtle,#54595d)",
section:
"margin-bottom:16px;padding:12px;background:var(--background-color-base,#fff);" +
"border:1px solid var(--border-color-subtle,#eaecf0);border-radius:2px",
panel:
"font-size:11px;margin-top:4px;padding:6px;" +
"background:var(--background-color-neutral-subtle,#f8f9fa);border-radius:2px",
list: "margin:0;padding-left:18px;list-style:disc",
listItem: "font-size:11px;margin:3px 0",
link: "color:var(--color-progressive,#36c)",
chip:
"background:var(--background-color-progressive-subtle,#eaf3ff);padding:1px 5px;" +
"border-radius:2px;font-size:10px",
row: "padding:8px 0;border-bottom:1px solid var(--border-color-subtle,#eaecf0)",
pageTitle: "font-weight:500;font-size:14px;line-height:20px;display:inline-flex;align-items:center",
srOnly:
"position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;" +
"clip:rect(0,0,0,0);white-space:nowrap;border:0",
scrollList:
"border:1px solid var(--border-color-subtle,#eaecf0);border-radius:2px;" +
"padding:0 8px;max-height:480px;overflow-y:auto",
listHeader:
"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;flex-wrap:wrap;gap:8px",
fieldRow: "display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end",
fieldGrow: "flex:1;min-width:200px",
fieldFixed: "min-width:220px"
};
function renderLabel(text) {
return h("div", { style: STYLE.label }, text);
}
function renderListHeader(labelText, buttons) {
return h("div", { style: STYLE.listHeader }, [
renderLabel(labelText),
h(
"div",
{ style: "display:flex;gap:6px" },
buttons.map(function (b) {
return h(
CdxButton,
{ weight: "quiet", size: "small", action: b.action, onClick: b.onClick },
function () {
return t(b.labelKey);
}
);
})
)
]);
}
function renderRateSlider(isRevLog) {
var valueRef = isRevLog ? delayRevLog : delayPages;
var min = isRevLog ? CONSTANTS.MIN_DELAY_REVLOG : CONSTANTS.MIN_DELAY_PAGES;
var max = isRevLog ? CONSTANTS.MAX_DELAY_REVLOG : CONSTANTS.MAX_DELAY_PAGES;
var step = isRevLog ? 5 : 50;
var labelKey = isRevLog ? "rateLimitRevLog" : "rateLimitPages";
var mid = min + Math.floor((max - min) / (2 * step)) * step;
var midPercent = ((mid - min) / (max - min)) * 100;
return h("div", { style: STYLE.section }, [
h("label", { style: STYLE.label }, labelKey ? t(labelKey) + ": " + valueRef.value + "ms" : ""),
h("input", {
type: "range",
min: min,
max: max,
step: step,
value: valueRef.value,
style: "width:100%;cursor:pointer;accent-color:var(--color-progressive,#36c);",
onInput: function (e) {
valueRef.value = parseInt(e.target.value, 10);
}
}),
h("div", { style: "position:relative;height:14px;" + STYLE.hint + ";margin-top:4px" }, [
h("span", { style: "position:absolute;left:0" }, min + "ms"),
h(
"span",
{ style: "position:absolute;left:" + midPercent + "%;transform:translateX(-50%)" },
mid + "ms"
),
h("span", { style: "position:absolute;right:0" }, max + "ms")
])
]);
}
function renderJobStats() {
if (!job.visible) return null;
return h("div", { style: STYLE.section }, [
h("div", { style: "font-weight:600;margin-bottom:8px" }, t("jobStatsTitle")),
h("div", { style: "display:flex;gap:16px;font-size:14px;flex-wrap:wrap" }, [
h("div", {}, t(job.totalLabelKey) + ": " + job.total),
h("div", {}, [
t("successCount") + ": ",
h("strong", { style: "color:var(--color-success,#14866d)" }, String(job.success))
]),
h("div", {}, [
t("failedCount") + ": ",
h("strong", { style: "color:var(--color-error,#d33)" }, String(job.failed))
])
])
]);
}
function renderProgress() {
if (!progress.visible) return null;
var pct = progress.total > 0 ? Math.round((progress.current / progress.total) * 100) : 0;
var label =
t("processing") +
": " +
progress.current +
" " +
t("of") +
" " +
progress.total +
" " +
t(progress.typeKey);
return h("div", { style: "margin-bottom:16px" }, [
h(CdxProgressBar, { "aria-label": label, value: pct, startLabel: "0%", endLabel: "100%" }),
h("div", { style: STYLE.hint + ";text-align:center;margin-top:4px" }, label)
]);
}
function renderResults() {
if (!results.value || results.value.length === 0) return null;
var failed = results.value.filter(function (r) {
return !r.success;
});
var success = results.value.filter(function (r) {
return r.success;
});
var unitLabel = job.kind === "logdel" ? t("logEntries") : t("pages");
var deletionsWord = job.kind === "undelete" ? t("undeletions") : t("deletions");
var children = [];
if (failed.length > 0) {
children.push(
h("div", { style: "margin-bottom:8px" }, [
h(
CdxMessage,
{
type: "error",
allowUserDismiss: true,
dismissButtonLabel: t("dismiss"),
onUserDismissed: function () {
results.value = results.value.filter(function (r) {
return r.success;
});
}
},
{
default: function () {
return [
h(
"div",
{ style: "font-weight:600;margin-bottom:6px" },
t("failed") + " " + deletionsWord + " (" + failed.length + "):"
),
h(
"ul",
{ style: "margin:0;padding-left:20px" },
failed.map(function (r, idx) {
var isPageResult = r.count === undefined;
var title = isPageResult ? mw.Title.newFromText(r.page) : null;
var content = title
? [
h(
"a",
{ href: title.getUrl(), target: "_blank" },
r.page
),
": " + (r.error || "Unknown error")
]
: [r.page + (r.error ? ": " + r.error : "")];
return h(
"li",
{ style: "margin-bottom:4px", key: "fail" + idx },
content
);
})
)
];
}
}
)
])
);
}
if (success.length > 0) {
var totalSuccessCount = success.reduce(function (sum, r) {
return sum + (r.count || 1);
}, 0);
children.push(
h(
CdxMessage,
{
type: "success",
allowUserDismiss: true,
dismissButtonLabel: t("dismiss"),
onUserDismissed: function () {
results.value = results.value.filter(function (r) {
return !r.success;
});
}
},
{
default: function () {
return t("completed") + ": " + totalSuccessCount + " " + unitLabel;
}
}
)
);
}
return h("div", { style: "margin-bottom:16px" }, children);
}
function renderTooltip() {
if (!tooltip.visible) return null;
var children = [h("div", {}, tooltip.text)];
if (tooltip.linksInfo) {
children.push(
h(
"div",
{
style:
"margin-top:6px;padding-top:6px;border-top:1px solid var(--border-color-subtle,#eaecf0);" +
"font-weight:600;color:var(--color-base,#202122)"
},
tooltip.linksInfo
)
);
}
return h(
"div",
{
style:
"position:fixed;left:" +
tooltip.x +
"px;top:" +
tooltip.y +
"px;z-index:10000;" +
"background:var(--background-color-base,#fff);border:1px solid var(--border-color-base,#a2a9b1);" +
"border-radius:2px;padding:10px;max-width:400px;box-shadow:0 2px 8px rgba(0,0,0,0.15);" +
"font-size:12px;color:var(--color-subtle,#54595d);pointer-events:none;word-wrap:break-word"
},
children
);
}
function renderExpandablePanel(cfg) {
var body;
if (cfg.loading) {
body = h("div", { style: STYLE.hint }, t("loading"));
} else if (cfg.isEmpty) {
body = h("div", { style: STYLE.hint }, t(cfg.emptyKey));
} else {
body = cfg.content;
}
return h("div", { style: STYLE.panel }, body);
}
function renderLoadMoreButton(hasMore, loading, onClick) {
if (!hasMore) return null;
return h(
CdxButton,
{ weight: "quiet", size: "small", disabled: loading, onClick: onClick },
function () {
return loading ? t("loading") : t("loadMoreEntries");
}
);
}
function renderToggleButton(shown, showLabelKey, onClick) {
return h(
CdxButton,
{ weight: "quiet", action: "progressive", size: "small", onClick: onClick },
function () {
return t(shown ? "hide" : showLabelKey);
}
);
}
function renderRevisionsPanel(item) {
var loading = item.revisionsLoading && !item.revisionsData;
var isEmpty = !loading && (!item.revisionsData || item.revisionsData.revisions.length === 0);
var content = null;
if (!loading && !isEmpty) {
var list = item.revisionsData.revisions.map(function (rev, idx) {
var date = new Date(rev.timestamp).toLocaleString();
var size = rev.size ? " (" + (rev.size / 1024).toFixed(1) + " KB)" : "";
var title = mw.Title.newFromText(item.title);
var href = title ? title.getUrl({ oldid: rev.revid }) : "#";
return h("li", { style: STYLE.listItem, key: "rev" + idx }, [
h("a", { href: href, target: "_blank", style: STYLE.link }, [
h("strong", {}, rev.user),
" " + date + size
]),
rev.comment ? " \u2013 " + rev.comment : ""
]);
});
content = [
h("ul", { style: STYLE.list }, list),
renderLoadMoreButton(item.revisionsData.hasMore, item.revisionsLoading, function () {
loadMoreRevisions(item);
})
];
}
return renderExpandablePanel({
loading: loading,
isEmpty: isEmpty,
emptyKey: "noPreviewAvailable",
content: content
});
}
function renderLogPanel(item) {
var loading = item.logLoading;
var isEmpty = !loading && (!item.logData || item.logData.logs.length === 0);
var content = null;
if (!loading && !isEmpty) {
content = h(
"ul",
{ style: STYLE.list },
item.logData.logs.map(function (log, idx) {
var date = new Date(log.timestamp).toLocaleString();
var logType = (log.type + "/" + (log.action || "")).replace(/\/$/, "");
return h("li", { style: STYLE.listItem, key: "log" + idx }, [
h("span", { style: STYLE.chip + ";margin-right:5px" }, logType),
h("strong", {}, log.user),
" " + date + (log.comment ? " \u2013 " + log.comment : "")
]);
})
);
}
return renderExpandablePanel({
loading: loading,
isEmpty: isEmpty,
emptyKey: "noLogEntriesFound",
content: content
});
}
function renderBacklinksPanel(item) {
var loading = item.backlinksLoading && !item.backlinksData;
var isEmpty = !loading && (!item.backlinksData || item.backlinksData.backlinks.length === 0);
var content = null;
if (!loading && !isEmpty) {
var list = item.backlinksData.backlinks.map(function (bl, idx) {
var title = mw.Title.newFromText(bl.title);
var href = title ? title.getUrl() : "#";
return h("li", { style: STYLE.listItem, key: "bl" + idx }, [
h("a", { href: href, target: "_blank", style: STYLE.link }, bl.title)
]);
});
content = [
h("ul", { style: STYLE.list }, list),
renderLoadMoreButton(item.backlinksData.hasMore, item.backlinksLoading, function () {
loadMoreBacklinks(item);
})
];
}
return renderExpandablePanel({
loading: loading,
isEmpty: isEmpty,
emptyKey: "noPagesFound",
content: content
});
}
function renderPageRow(item, state, opts) {
var checkbox = h(
CdxCheckbox,
{
modelValue: state.selected,
"onUpdate:modelValue": function (v) {
state.selected = v;
},
inputValue: item.title
},
{
default: function () {
return h("span", { style: STYLE.srOnly }, item.title);
}
}
);
var titleEl;
if (!opts.linkable) {
titleEl = h(
"span",
{
style: STYLE.pageTitle + ";cursor:pointer",
onClick: function () {
toggleSelected(state, item.title);
}
},
item.title
);
} else {
var title = mw.Title.newFromText(item.title);
var href = title ? title.getUrl() : "#";
titleEl = h(
"a",
{
href: href,
target: "_blank",
style: STYLE.link + ";" + STYLE.pageTitle,
onMouseenter: function (e) {
showTooltipFor(item.title, e);
},
onMousemove: moveTooltip,
onMouseleave: hideTooltip
},
item.title
);
}
var buttons = [];
if (opts.showRevisionsButton) {
buttons.push(
renderToggleButton(item.showRevisions, "revisions", function () {
toggleRevisions(item);
})
);
}
buttons.push(
renderToggleButton(item.showLog, "pageLog", function () {
toggleLog(item);
})
);
buttons.push(
renderToggleButton(item.showBacklinks, "pageLinks", function () {
toggleBacklinks(item);
})
);
var metaAndPanels = [];
if (item.timestamp) {
metaAndPanels.push(
h(
"div",
{ style: STYLE.hint },
t("created") + ": " + new Date(item.timestamp).toLocaleString()
)
);
}
if (opts.showRevisionsButton && item.showRevisions) metaAndPanels.push(renderRevisionsPanel(item));
if (item.showLog) metaAndPanels.push(renderLogPanel(item));
if (item.showBacklinks) metaAndPanels.push(renderBacklinksPanel(item));
return h("div", { key: item.title, style: STYLE.row }, [
h(
"div",
{ style: "display:flex;align-items:center;gap:6px;flex-wrap:wrap" },
[checkbox, titleEl].concat(buttons)
),
metaAndPanels.length > 0
? h("div", { style: "margin-left:26px;margin-top:4px" }, metaAndPanels)
: null
]);
}
function renderPagesListSection(state, opts) {
if (state.pages.length === 0) return null;
return h("div", { style: "margin-top:16px" }, [
renderListHeader(t("pagesList") + " (" + state.pages.length + ")", [
{
labelKey: "selectAll",
onClick: function () {
selectAllPages(state);
}
},
{
labelKey: "deselectAll",
onClick: function () {
deselectAllPages(state);
}
},
{
labelKey: "clearList",
action: "destructive",
onClick: function () {
clearPageList(state);
}
}
]),
h(
"div",
{ style: STYLE.scrollList, role: "group", "aria-label": t("pagesList") },
state.pages.map(function (item) {
return renderPageRow(item, state, opts);
})
)
]);
}
function renderEntryRow(entry) {
var date = new Date(entry.timestamp).toLocaleString();
var checkbox = h(
CdxCheckbox,
{
modelValue: logdelState.selectedIds,
"onUpdate:modelValue": function (v) {
logdelState.selectedIds = v;
},
inputValue: entry.logid
},
{
default: function () {
var parts = [
h(
"span",
{ style: STYLE.chip + ";margin-right:6px" },
entry.type + "/" + (entry.action || "")
)
];
if (entry.title) {
parts.push(
h(
"a",
{ href: mw.util.getUrl(entry.title), target: "_blank", style: STYLE.link },
entry.title
)
);
}
return parts;
}
}
);
return h("div", { key: entry.logid, style: STYLE.row }, [
checkbox,
h(
"div",
{ style: STYLE.hint + ";margin-left:26px" },
t("logID") + ": " + entry.logid + " \u2022 " + date
),
entry.comment
? h("div", { style: STYLE.hint + ";margin-left:26px;font-style:italic" }, entry.comment)
: null
]);
}
function renderHideOptions() {
var selection = logdelSelection.value;
function cb(value, labelKey) {
return h(
CdxCheckbox,
{
key: value,
modelValue: logdelState.hideOptions,
"onUpdate:modelValue": function (v) {
logdelState.hideOptions = v;
},
inputValue: value
},
function () {
return t(labelKey);
}
);
}
var checkboxes;
var note = null;
if (selection.onlyBlock) {
checkboxes = [cb("content", "hideTitle")];
note = t("blockOnlyInfo");
} else if (selection.onlyThanks) {
checkboxes = [cb("user", "hideUser")];
note = t("thanksOnlyInfo");
} else {
checkboxes = [
cb("content", "hideContent"),
cb("comment", "hideComment"),
cb("user", "hideUser")
];
if (selection.types.block || selection.types.thanks) note = t("mixedLogsNote");
}
return h(
CdxField,
{ isFieldset: true },
{
label: function () {
return t("parameters");
},
default: function () {
return checkboxes.concat(
note
? [
h("div", { style: "margin-top:8px" }, [
h(CdxMessage, { type: "warning" }, function () {
return note;
})
])
]
: []
);
}
}
);
}
function renderLogTypeFilters() {
return h(
CdxField,
{ isFieldset: true },
{
label: function () {
return t("logTypes");
},
default: function () {
return logTypeItems.map(function (opt) {
return h(
CdxCheckbox,
{
key: opt.value || "all",
modelValue: logdelState.typeFilters,
"onUpdate:modelValue": onLogTypeFiltersUpdate,
inputValue: opt.value
},
function () {
return opt.label;
}
);
});
}
}
);
}
function renderReasonSection(state, reasonItems) {
return h("div", { style: STYLE.section }, [
h(
CdxField,
{},
{
label: function () {
return t("commonReasons");
},
default: function () {
return h(CdxSelect, {
selected: state.reasonPick,
"onUpdate:selected": function (v) {
insertReasonPick(state, v);
},
menuItems: reasonItems,
defaultLabel: t("insertReason"),
disabled: reasonItems.length === 0
});
}
}
),
h("div", { style: "margin-top:10px" }, [
h(
CdxField,
{},
{
label: function () {
return t("reasonLabel");
},
default: function () {
return h(CdxTextInput, {
modelValue: state.reasonText,
"onUpdate:modelValue": function (v) {
state.reasonText = v;
},
placeholder: t("reasonPlaceholder")
});
}
}
)
]),
isGlobalUser
? h("div", { style: "margin-top:10px" }, [
h(
CdxField,
{ isFieldset: true, hideLabel: true },
{
label: function () {
return t("globalSysopAction");
},
default: function () {
return h(
CdxCheckbox,
{
modelValue: state.globalSysop,
"onUpdate:modelValue": function (v) {
state.globalSysop = v;
}
},
function () {
return t("globalSysopAction");
}
);
}
}
)
])
: null
]);
}
function renderPageActionTab(cfg) {
var state = cfg.state;
return [
h("div", { style: STYLE.section }, [
h("div", { style: STYLE.fieldRow + ";margin-bottom:8px" }, [
h("div", { style: STYLE.fieldGrow }, [
h(
CdxField,
{},
{
label: function () {
return t("username");
},
default: function () {
return h(CdxTextInput, {
modelValue: state.username,
"onUpdate:modelValue": function (v) {
state.username = v;
},
placeholder: t("usernamePlaceholder")
});
}
}
)
]),
h("div", { style: STYLE.fieldFixed }, [
h(
CdxField,
{ hideLabel: true },
{
label: function () {
return t("namespace");
},
default: function () {
return h(CdxSelect, {
selected: state.namespace,
"onUpdate:selected": function (v) {
state.namespace = v;
},
menuItems: cfg.namespaceItems
});
}
}
)
])
]),
h("div", { style: STYLE.fieldRow }, [
h("div", { style: STYLE.fieldGrow }, [
h(
CdxField,
{ hideLabel: true },
{
label: function () {
return t("timeFilter");
},
default: function () {
return h(CdxSelect, {
selected: state.timeFilter,
"onUpdate:selected": function (v) {
state.timeFilter = v;
},
menuItems: timeFilterItems
});
}
}
)
]),
h(
CdxButton,
{
action: "progressive",
disabled: state.loadingPages,
onClick: function () {
fetchPagesForState(state, cfg.fetchKind);
}
},
function () {
return t(state.loadingPages ? cfg.loadingLabelKey : cfg.fetchButtonLabelKey);
}
)
])
]),
h("div", { style: STYLE.section }, [
h(
CdxField,
{},
{
label: function () {
return t(cfg.manualLabelKey);
},
default: function () {
return h(CdxTextArea, {
modelValue: state.manualText,
"onUpdate:modelValue": function (v) {
state.manualText = v;
},
placeholder: t("pagesManualPlaceholder"),
rows: 5
});
}
}
),
h(
CdxButton,
{
action: "progressive",
onClick: function () {
addManualPages(state);
}
},
function () {
return t("addToList");
}
),
renderPagesListSection(state, cfg.rowOpts)
]),
renderReasonSection(state, cfg.reasonItems),
renderRateSlider(false),
h(
CdxButton,
{
action: cfg.executeAction,
weight: "primary",
disabled: running.value,
onClick: function () {
executePages(state, cfg.isDelete);
}
},
function () {
return t(cfg.executeLabelKey);
}
)
];
}
function renderDeleteTab() {
return renderPageActionTab({
state: deleteState,
namespaceItems: namespaceItemsDelete,
fetchKind: "created",
loadingLabelKey: "loadingPages",
fetchButtonLabelKey: "getPages",
manualLabelKey: "pagesToDelete",
rowOpts: { linkable: true, showRevisionsButton: true },
reasonItems: deleteReasonItems,
executeAction: "destructive",
isDelete: true,
executeLabelKey: "deleteButton"
});
}
function renderUndeleteTab() {
return renderPageActionTab({
state: undeleteState,
namespaceItems: namespaceItemsUndelete,
fetchKind: "deleted",
loadingLabelKey: "loadingDeletedPages",
fetchButtonLabelKey: "getDeletedPages",
manualLabelKey: "pagesToUndelete",
rowOpts: { linkable: false, showRevisionsButton: false },
reasonItems: undeleteReasonItems,
executeAction: "progressive",
isDelete: false,
executeLabelKey: "undeleteButton"
});
}
function renderLogdelTab() {
return [
h("div", { style: STYLE.section }, [
h(
CdxField,
{},
{
label: function () {
return t("username");
},
default: function () {
return h(CdxTextInput, {
modelValue: logdelState.username,
"onUpdate:modelValue": function (v) {
logdelState.username = v;
},
placeholder: t("usernamePlaceholder")
});
}
}
),
h("div", { style: STYLE.fieldRow + ";margin-top:10px" }, [
h("div", { style: STYLE.fieldGrow }, [
h(
CdxField,
{ hideLabel: true },
{
label: function () {
return t("timeFilter");
},
default: function () {
return h(CdxSelect, {
selected: logdelState.timeFilter,
"onUpdate:selected": function (v) {
logdelState.timeFilter = v;
},
menuItems: timeFilterItems
});
}
}
)
]),
h(
CdxButton,
{
action: "progressive",
disabled: logdelState.loadingEntries,
onClick: fetchLogEntriesForState
},
function () {
return logdelState.loadingEntries ? t("loadingLogEntries") : t("getLogEntries");
}
)
])
]),
h("div", { style: STYLE.section }, [renderLogTypeFilters()]),
logdelState.entries.length > 0
? h("div", { style: STYLE.section }, [
renderListHeader(t("logEntries") + " (" + logdelState.entries.length + ")", [
{ labelKey: "selectAll", onClick: selectAllEntries },
{ labelKey: "deselectAll", onClick: deselectAllEntries }
]),
h(
"div",
{ style: STYLE.scrollList, role: "group", "aria-label": t("logEntries") },
logdelState.entries.map(renderEntryRow)
),
logdelState.hasMore
? h("div", { style: "padding-top:10px;text-align:center" }, [
h(
"div",
{ style: STYLE.hint + ";margin-bottom:6px" },
t("loadMoreEntries")
),
h(
"div",
{ style: "display:flex;gap:8px;justify-content:center" },
[50, 100, 200].map(function (n) {
return h(
CdxButton,
{
key: n,
action: "progressive",
disabled: logdelState.loadingEntries,
onClick: function () {
loadMoreLogEntries(n);
}
},
function () {
return String(n);
}
);
})
)
])
: null
])
: null,
h("div", { style: STYLE.section }, [renderHideOptions()]),
renderReasonSection(logdelState, logdelReasonItems),
renderRateSlider(true),
h(
CdxButton,
{
action: "destructive",
weight: "primary",
disabled: running.value,
onClick: executeLogDelete
},
function () {
return t("logdelButton");
}
)
];
}
function renderInfoBanner() {
return h("div", { style: "margin-bottom:16px" }, [
h(
CdxMessage,
{ type: "notice" },
{
default: function () {
return [
t("infoText") + " ",
h(
"a",
{ href: mw.util.getUrl("Special:Nuke"), target: "_blank" },
"Special:Nuke"
)
];
}
}
)
]);
}
return function render() {
return h("div", { class: "cdx-massdelete-app" }, [
h(
"h3",
{
style:
"margin-top:0;border-bottom:1px solid var(--border-color-base,#a2a9b1);padding-bottom:6px;" +
"color:var(--color-base,#202122)"
},
t("title")
),
h("p", { style: "color:var(--color-subtle,#54595d)" }, t("description")),
renderInfoBanner(),
h(
CdxTabs,
{
active: activeTab.value,
"onUpdate:active": function (v) {
activeTab.value = v;
}
},
{
default: function () {
return [
h(
CdxTab,
{ name: "delete", label: t("deleteTab") },
{ default: renderDeleteTab }
),
h(
CdxTab,
{ name: "undelete", label: t("undeleteTab") },
{ default: renderUndeleteTab }
),
h(
CdxTab,
{ name: "logdel", label: t("logdelTab") },
{ default: renderLogdelTab }
)
];
}
}
),
h("div", { style: "margin-top:16px" }, [renderJobStats(), renderProgress(), renderResults()]),
h(Teleport, { to: "body" }, [renderTooltip()])
]);
};
}
};
}
async function init() {
var config = mw.config.get(["wgNamespaceNumber", "wgTitle", "wgGlobalGroups", "wgUserGroups"]);
var onMassDeletePage =
config.wgNamespaceNumber === -1 && config.wgTitle && config.wgTitle.toLowerCase() === "massdelete";
var hasRights =
/global-sysop|steward/.test(config.wgGlobalGroups) ||
(config.wgUserGroups && config.wgUserGroups.indexOf("sysop") !== -1);
if (!onMassDeletePage || !hasRights) return;
console.log("MassDelete - Delays:");
console.log("Pages/Undelete: " + RequestQueue.delayPages + "ms between operations");
console.log("Log entries: " + RequestQueue.delayRevLog + "ms between operations");
var isGlobalUser = false;
var globalUserText = "";
if (/steward/.test(config.wgGlobalGroups)) {
isGlobalUser = true;
globalUserText = "(Steward action)";
} else if (/global-sysop/.test(config.wgGlobalGroups)) {
isGlobalUser = true;
globalUserText = "(global sysop action)";
}
var api = new mw.Api({ userAgent: CONSTANTS.USER_AGENT });
var reasons = await loadReasons(api);
mw.loader.using(["vue", "@wikimedia/codex"]).then(function (require) {
var Vue = require("vue");
var Codex = require("@wikimedia/codex");
var component = buildApp(Vue, Codex, api, {
reasons: reasons,
isGlobalUser: isGlobalUser,
globalUserText: globalUserText
});
var bodyContent = document.getElementById("bodyContent");
if (!bodyContent) return;
bodyContent.innerHTML = "";
var mountPoint = document.createElement("div");
bodyContent.appendChild(mountPoint);
Vue.createMwApp(component).mount(mountPoint);
mw.notify(t("title"), { type: "success" });
});
}
$(function () {
mw.loader.using(["mediawiki.api", "mediawiki.Title", "mediawiki.util"]).then(init);
});
})();
// </nowiki>
788tvv7ew1ot0tjqx6okc71egltyec3