Wikipedia sowiki https://so.wikipedia.org/wiki/Bogga_Hore MediaWiki 1.48.0-wmf.1 first-letter Media Special Talk User User talk Wikipedia Wikipedia talk File File talk MediaWiki MediaWiki talk Template Template talk Help Help talk Category Category talk Portal Portal talk TimedText TimedText talk Module Module talk Event Event talk MediaWiki:Monobook.css 8 2445 311221 310842 2026-10-28T13:44:21Z Isma4l 41797 311221 css text/css /* Don't display some stuff on the main page */ body.page-Bogga_Hore #deleteconfirm, body.page-Bogga_Hore #t-cite, body.page-Bogga_Hore #lastmod, body.action-view.page-Bogga_Hore #siteSub, body.action-view.page-Bogga_Hore #contentSub { display: none !important; } #siteNotice { margin-top: 5px; margin-bottom: -.5em; } #mw-dismissable-notice { background: transparent; } /* Make non-articles light blue * Make content area light blue in all namespaces except articles (main namespace). * This is done by setting the background color for all #content areas * to light blue, and then overriding it back to white for any #content * enclosed in a .ns-0 (main namespace). We do the same for the "tab" * backgrounds and some other objects. */ @media screen { body:not(.ns-0) #content, body:not(.ns-0) #p-cactions li a:hover, body:not(.ns-0) #p-cactions li.selected a, body:not(.ns-0) #content div.thumb { /* "Margin" for thumbs, padding for galleries */ background-color: #F8FCFF; /* Light blue */ } body:not(.ns-0) #p-cactions li a { background-color: #F7F9FB; /* Light blue-gray inactive tabs */ } } /* Talk page tab "+" / "new section". Sets the same padding as the other tabs have. */ div#p-cactions #ca-addsection a { padding-left: .8em; padding-right: .8em; } /* Make "From Wikipedia, the free encyclopedia" a bit smaller */ #siteSub { font-size: 92%; } div#footer #lastmod, div#footer #copyright { display: block; } p.error { font-weight: bold; } /* Remove default styles for [[MediaWiki:Noarticletext]]. */ div.noarticletext { border: none; background: transparent; padding: 0; } /* add .toccolours because monobook/main.css wasn't being used by the print style */ .toccolours { border: 1px solid #aaa; background-color: #f9f9f9; padding: 5px; font-size: 95%; } /* Don't underline links in portlets/specialchars even with pref "Underline links:Always" */ .portlet a, #editpage-specialchars a { text-decoration: none; } .portlet a:hover, #editpage-specialchars a:hover { text-decoration: underline; } /* Position coordinates */ #coordinates { position: absolute; z-index: 1; border: none; background: none; right: 0; top: 3.7em; float: right; margin: 0; padding: 0; padding-right: 30px; line-height: 1.5em; text-align: right; text-indent: 0; font-size: 85%; text-transform: none; white-space: nowrap; } /* Prep for moving coordinates into mw-indicator */ #mw-indicator-attached-kml, #mw-indicator-coordinates { font-size: 13px; } .ve-ce-surface #coordinates { margin-top: -3em; top: 0; padding: 0; } /* FR topicon position */ div.flaggedrevs_short { position: absolute; z-index: 10; top: 10px; right: 110px; } /* Add bolding to ooui destructive buttons */ #mw-prefs-restoreprefs, #wpConfirmB, #mw-editform-cancel, #oo-ui-flaggedElement-destructive, .oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive, .oo-ui-buttonElement-framed.oo-ui-flaggedElement-destructive, .oo-ui-buttonElement-framed.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button, .oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { font-weight: 700; } @media (max-width:550px) { /* Break long words when they cause overflow */ .mw-body { overflow-wrap: break-word; } } /* Workaroud for [[phab:T309948]] */ .ext-ipinfo-button { height: 1em; } /* Styling for tags in changes pages */ .mw-tag-markers { font-style: italic; } pkezpoenewhr353x6ya95fu3stmww1s Ayrland 0 7306 311232 222515 2026-10-28T20:19:02Z Andor206 47921 Fixed typo 311232 wikitext text/x-wiki {{Coord|53|20|39|N|6|16|3|W|display=title}} {{Dalalka |native_name = Jamhuuriyadda Ireland |conventional_long_name = Republic of Ireland |common_name = Ireland |qaaradda = [[Yurub]]. |sawir_calan = Flag of Ireland.svg |sawir_qaran = Coat of arms of Ireland.svg |image_map = EU-Ireland.svg |astaan_calan = [[Calanka Irland]] |image_map = EU-Ireland.svg |caasimadda = [[Dublin]] |luuqadaha = [[Ingiriis]], [[Irish]] |caasimada = [[Dublin]] |Dawladda = Irland |darajo_hogaamiye1 = [[Madaxweyne]] |darajo_hogaamiye2 = [[madaxwayne kuxigeen]] |magac_hogaamiye1 = [[Michael D. Higgins]] |magac_hogaamiye2 = [[Micheál Martin TD]] |sovereignty_type = '''Ka xoroobey''' |sovereignty_note = Gumeystihii [[ingiriiska]] |established_event1 = Taariikhda |established_date1 = 24 [[April]], [[1916]] |area = 70,273 km2 (119th) |areami² = 68000 |biyo = 1.6 |population_estimate =4,581,269 <sup>3</sup> 4,722,028 |population_estimate_year = (2008) (2012) |lacagta = [[Euro]] |Magaca internetka = &nbsp;[[ie]] |wakhti = [[UTC+1]] |furaha_debedda = 252 |furaha internetka = .ie |furaha telefonka = +353 |Magaalada uguwayn = Dublin }} '''Jamhuuriyada Ireland''' afka Iriska weaxa loogu dhawaqaa (Éire) Waaqaybta uguwayn jasiirada Irland waxa ay kutaalaa koonfurta bari ee [[Badweynta Atlaantik]] ingiriiska iyo Irland waxa udhexeeya marin yar oo bad ah. == Taariikh == Wadanka Irland waxa uu soomaray taariikho gaar ah waxyaabaha ay taariikhda Irland kaga duwantahay taariikhha kale waxa kamida marka koobaad Irland waxa ay kutaalaa goob ahamid juquraafi leh talabaad waa xidhiidhka ay la leedahay wadanka Ingiriiska oo dhawr jeer isku dayay in uu qabsadoo wadanka Irland. tasadexaad dagaalada lagu hoobtay ee Irland ay soomartay.ta afarad waa dhibaatooyinka dhanka diinta ee soogaadhay shacabka kunool wadanka irland kaas oo kaga imanyay dhanka kaniisadaha waxa intaa u dheer dhibaatooyin siyaasadeed iyo dhaqaale oo in badan oo shacabka Irland ah ku kaliftay in ay dabada u haajiraan,markii u horaysay ee Irland laga haajiraa waxa ay ahyd 6000 kahor dhalashaddii nabi [[Ciise]] markaas oo ay wadanka soo galeen dad kayimi xaga [[Skotland] kuwaas oo qabsaday Irland.hijradii labaad ee wadanka Irland laga guuraa waxa ay dhacday sandkii 2000 kahor dhalashaddii nabi [[Ciise]] C.S, diinta kiristanku waxa ay wadanka Irland gaadhay qarnigii lixaad ee taariikhda miilaadiga, kadib markii ay wadanka gacanta kudhigiin dadkii looyaqaanay [[Noormaan]]ka ''Normans'' kadib waxa wadanka qabsaday ingiriiska sanadkii 1172 xiligaas waxaa ingiriiska boqor ka ahaa [[Henry II]] sanadkii 1801 Irland waxa ay kamid noqotay [[Midowga boqortooyada Britan]] sanadkii 1916 qolyaha xagjirkaa ee Irland ayaa waxa ay bilaabeen dagaal kacaana oo ay kagasoo horjeedaan gumaystihii ingiriiska laakiin kacdoonkaasi wuu fashilmay oo dadkii ka qaybqaatay badidoodii waa latoogtay. sanadkii 1921 ingiriisku jasiirada Irland waxa uu u qaybiyay laba qaybood.sanadkii 1922 waxa madax banaani qaatay wadanka looyaqaano hada Jamhuuriyada Irland, halka qaybta waqooyi ee jasiiradu ay kasii midtahay ilaa iminka [[Midowga boqortooyada Britan]] taas oo keentay dagaal sokeeye oo ilaa iminka aan laxalin. == Deegaanka == Badhtamaha dlka Ireland, waa dhul banaan oo hooseeya waana dhul beereed, waana dhul kaymo ah waxa kuyaalo harooyin aad iyo aad u badan, wabiga ugu dheer wadanka waxa lagu magacaabaa. [[Wabiga Shannon]] harada wadanka ugu wayn waxa lagu magacaabaa [[(Lough Neagh]] == Cimilada == Cimalda Jamhuuriyada Ireland xiliga [[Jiilaal]]ka aad ayay u qabawdahay.heerka qabawgu waxa uu gaadhaa darajada fadhiisiga biyaha iyo wixii dareera.laakiin xiliga [[Xagaa]]ga cimilada Ireland waa meel dhaxaad maalinkastana waxa da [[Roob]] == Magaalooyinka ugu waawayn == Magaalada [[Dublin]] waa caasimada Ireland waana magaalda ugu wayn waxaa kunool dad gaadhaya 499,156 kun oo qof, magaalada labaad ee ugu wayn wadanka waxa weeye magaalda [[Corcaigh]] magaalda sadexaad waa [[Gaillimh]] == Dhaqaalaha == === Beeraha === Suuqa Ierland waa mid yar marka loo eego suuqyada [[Yurub]] ee kale laakiin waa suuq dagan oo waxkal iibsi uu kasocdo *[[Waqooyiga Ayrland]] * [https://www.jw.org/en/library/magazines/g201407/visit-ireland/ A Visit to Ireland] * [[William Bedell]] [[Category:Yurub]] 72op3owhp12dh1tldtk7zw19l6dssyv Module:Protected edit request 828 13791 311253 310245 2026-10-29T11:26:13Z Isma4l 41797 311253 Scribunto text/plain require('strict') local yesno = require('Module:Yesno') local makeMessageBox = require('Module:Message box').main local getArgs local activeBox -- si dadban ayaa loo furayaa haddii weydiintu firfircoon tahay ---------------------------------------------------------------------- -- Qeexida fasalka sanduuqa (Box class) ---------------------------------------------------------------------- local box = {} box.__index = box function box.new(protectionType, args) local obj = {} obj.args = args setmetatable(obj, box) obj.tmboxArgs = {} -- Waxaa loo adeegsadaa kaydinta doodaha loo gudbinayo tmbox iyadoo la adeegsanayo habka box:export. -- Deji beeraha xogta. obj.tmboxArgs.attrs = { ['data-origlevel'] = protectionType } return obj end function box:setArg(key, value) -- Waxay degetaa qiime loo gudbinayo tmbox. if key then self.tmboxArgs[key] = value end end function box:export() local title = mw.title.getCurrentTitle() local skipCheck = yesno(self.args.demo) or yesno(self.args.skiptalk) if not title.isTalkPage and not skipCheck then return '<span class="error">Khalad: Codsiyada tafatirtada dhowrsan waxaa keliya oo lagu samayn karaa bogga wada-hadalka.</span>[[Category:Bogagga aan wada-hadalka ahayn oo leh gusaamada codsiga tafatirtada]]' end -- Isku weydii magacyada bogagga la bixiyay local titles = {} for k, v in pairs(self.args) do if type(k) == 'number' then table.insert(titles, self.args[k]) end end local pagesText if #titles == 0 then pagesText = '' elseif #titles == 1 and mw.title.getCurrentTitle().subjectPageTitle.fullText == titles[1] then pagesText = '' else for i, v in pairs(titles) do if i == 1 then pagesText = ' ee ku saabsan [[:' .. v .. ']]' elseif i == #titles then pagesText = pagesText .. ' iyo [[:' .. v .. ']]' else pagesText = pagesText .. ', [[:' .. v .. ']]' end end end self:setArg('smalltext', "[[Wikipedia:Codsiyada tafatirtada|Codsigana tafatireed]]" .. pagesText .. " waa la kajawabay. Deji kheyraadka <code style=\"white-space: nowrap;\">&#124;answered&#61;</code> oo ka dhig '''no''' si aad dib uga hawlgeliso codsigaaga.") self:setArg('small', true) self:setArg('class', 'editrequest') return makeMessageBox('tmbox', self.tmboxArgs) end ---------------------------------------------------------------------- -- Habaynta doodaha iyo furidda walxaha ---------------------------------------------------------------------- local p = {} function p._main(protectionType, args) local boxType = box if not yesno(args.answered or args.ans, true) then if not activeBox then activeBox = require('Module:Protected edit request/active')(box, yesno, makeMessageBox) end boxType = activeBox end local requestBox = boxType.new(protectionType, args) return requestBox:export() end local mt = {} function mt.__index(t, k) if not getArgs then getArgs = require('Module:Arguments').getArgs end return function (frame) return t._main(k, getArgs(frame, {wrappers = {'Template:Edit fully-protected', 'Template:Edit semi-protected', 'Template:Edit template-protected', 'Template:Edit extended-protected', 'Template:Edit interface-protected', 'Template:Edit protected'}})) end end return setmetatable(p, mt) 8cyybgtfquwj4ifrnyvdlm7lnxuccfh Barış Alper Yılmaz 0 40545 311252 265491 2026-10-29T10:09:07Z Zafer 10671 Photo changed 311252 wikitext text/x-wiki {{short description|Turkish footballer}} {{Use dmy dates|date=June 2024}} {{Infobox football biography | name = Barış Alper Yılmaz | image = Barış Alper Yılmaz 20251019.jpg | caption = Yılmaz in 2025 | full_name = Barış Alper Yılmaz | birth_date = {{Birth date and age|2000|5|23|df=y}} | birth_place = [[Rize]], Turkey | height = 1.86 m | position = [[Winger (association football)|Winger]] | currentclub = [[Galatasaray SK|Galatasaray]] | clubnumber = 53 | youthyears1 = 2012–2017 | youthclubs1 = Rize İl Özel İdarespor | years1 = 2017–2020 | clubs1 = [[Ankara Demirspor]] | caps1 = 39 | goals1 = 1 | years2 = 2020–2021 | clubs2 = [[Ankara Keçiörengücü]] | caps2 = 34 | goals2 = 8 | years3 = 2021– | clubs3 = [[Galatasaray SK|Galatasaray]] | caps3 = 79 | goals3 = 10 | nationalyears1 = 2021– | nationalteam1 = [[Turkey national under-21 football team|Turkey U21]] | nationalcaps1 = 6 | nationalgoals1 = 1 | nationalyears2 = 2021– | nationalteam2 = [[Turkey national football team|Turkey]] | nationalcaps2 = 20 | nationalgoals2 = 2 | club-update = 23:31, 26 May 2024 (UTC) | nationalteam-update = 23:11, 6 July 2024 (UTC) }} '''Barış Alper Yılmaz''' (dhashay 23 May 2000) waa cayaaryahan u dhashay wadanka [[Turkiga]]. wuxuuna hadda dhanka weerarka uga ciyaaraa kooxda [[Galatasaray SK|Galatasaray]] ee ka dhisan magaalada [[Istanbuul|Istanbul]] iyo xulka qaranka dalka Turkiga. 8ol3n7a655gfxbhuh1y9swnhvt7isbn Module:Navbar/configuration 828 44165 311225 288471 2026-10-28T15:10:07Z Isma4l 41797 311225 Scribunto text/plain return { ['templatestyles'] = 'Module:Navbar/styles.css', ['hlist_templatestyles'] = 'Hlist/styles.css', ['box_text'] = 'This box: ', -- default text box when not plain or mini ['title_namespace'] = 'Template', -- namespace to default to for title ['invalid_title'] = 'Invalid title ', ['classes'] = { -- set a line to nil if you don't want it ['navbar'] = 'navbar', ['plainlinks'] = 'plainlinks', -- plainlinks ['horizontal_list'] = 'hlist', -- horizontal list class ['mini'] = 'navbar-mini', -- class indicating small links in the navbar ['box_text'] = 'navbar-boxtext', ['brackets'] = 'navbar-brackets', -- 'collapsible' is the key for a class to indicate the navbar is -- setting up the collapsible element in addition to the normal -- navbar. ['collapsible'] = 'navbar-collapse', ['collapsible_title_mini'] = 'navbar-ct-mini', ['collapsible_title_full'] = 'navbar-ct-full' } } itag4bw69ebqpc0fw4hgkr4pkizazgr MediaWiki:Vector-2022.css 8 53660 311220 310841 2026-10-28T13:42:21Z Isma4l 41797 311220 css text/css /** * Note: [[MediaWiki:Common.css]] is loaded in addition to these styles * Please use [[Extension:TemplateStyles]] where possible. */ #coordinates { line-height: 2; font-size: 92%; white-space: nowrap; } /* Don't display some stuff on the main page */ .page-Bogga_Hore #deleteconfirm, .page-Bogga_Hore #t-cite, .page-Bogga_Hore #footer-info-lastmod, .action-view.page-Bogga_Hore #siteSub, .action-view.page-Bogga_Hore #contentSub, .action-view.page-Bogga_Hore #contentSub2 { display: none !important; } /* Override [[phab:T265947]] */ .mw-body-content blockquote { border-left: none; } /* Styling for tags in changes pages */ .mw-tag-markers { font-style: italic; font-size: 90%; } /* Wikipedia 25, remove somewhen */ .mw-logo-icon { display: none; } .mw-logo { margin: 6px 0; } @media screen { html.skin-theme-clientpref-night .navbox a:not(.new):not(.mw-selflink):link, html.skin-theme-clientpref-night .infobox a:not(.new):not(.mw-selflink):link { color: var( --color-progressive ) !important; } /* T370074 */ html.skin-theme-clientpref-night .mw-parser-output > figure img { background: var( --background-color-disabled-fixed, #C8CCD1 ); } } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os .navbox a:not(.new):not(.mw-selflink):link, html.skin-theme-clientpref-os .infobox a:not(.new):not(.mw-selflink):link { color: var( --color-progressive ) !important; } /* T370074 */ html.skin-theme-clientpref-os .mw-parser-output > figure img { background: var( --background-color-disabled-fixed, #C8CCD1 ); } } 0v2d7dji4mdckdvruc57jf7kfb66bk5 MediaWiki:Vector.css 8 53661 311222 310843 2026-10-28T13:47:59Z Isma4l 41797 311222 css text/css /* Don't display some stuff on the main page */ .page-Bogga_Hore #deleteconfirm, .page-Bogga_Hore #t-cite, .page-Bogga_Hore #footer-info-lastmod, .action-view.page-Bogga_Hore #siteSub, .action-view.page-Bogga_Hore #contentSub, .action-view.page-Bogga_Hore #contentSub2 { display: none !important; } #coordinates { position: absolute; top: 3.5em; right: 0; line-height: 1.6; text-align: right; font-size: 92%; white-space: nowrap; float: right; margin: 0; padding: 0; text-indent: 0; text-transform: none; } /* correct position for VE */ .ve-ce-surface #coordinates { margin-right: 2em; margin-top: -1em; } /* FR topicon position */ div.flaggedrevs_short { position: absolute; top: -3em; right: 100px; z-index: 1; } /* Make "From Wikipedia, the free encyclopedia" a bit smaller */ #siteSub { font-size: 92%; } /* Move page status indicators down slightly */ .mw-indicators { padding-top: 0.4em; } /* Override [[phab:T265947]] */ .mw-body-content blockquote { border-left: none; } /* Styling for tags in changes pages */ .mw-tag-markers { font-style: italic; font-size: 90%; } 3iartx8jxha7nvshwict9sotc2pney3 MediaWiki:Gadget-twinkleconfig.js 8 53690 311227 310880 2026-10-28T15:54:15Z Isma4l 41797 311227 javascript text/javascript // <nowiki> (function() { /* **************************************** *** twinkleconfig.js: Qaybta doorbidda **************************************** * Qaabka loo yeero: Wuxuu ku darayaa foomka qaab-yaynta Wikipedia:Twinkle/Preferences, wuxuuna ku darayaa sanduuq xayaysiis ah dusha sare ee hoos-boggaga isticmaalaha ee leh isticmaalaha hadda soo galay oo ku dhammaada '.js' * Ka shaqeeya: Waxa aan hadda sheegay. Haa. */ Twinkle.config = {}; Twinkle.config.watchlistEnums = { yes: 'Ku dar liiska la socodka (si aan xad lahayn)', no: "Ha ku darin liiska la socodka", default: 'Raac doorbidyada boggaaga', '1 week': 'La soco 1 toddobaad', '1 month': 'La soco 1 bil', '3 months': 'La soco 3 bilood', '6 months': 'La soco 6 bilood' }; Twinkle.config.commonSets = { csdCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f8: 'F8', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, csdCriteriaNotification: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5 ("xadgudubka ciqaabta guud" kaliya)', g6: 'G6 ("guuritaanka koobi-iyo-dheji" kaliya)', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', u6: 'U6', u7: 'U7' }, csdAndImageDeletionCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f11: 'F11', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, namespacesNoSpecial: { 0: 'Maqaal', 1: 'Wada-hadal (maqaal)', 2: 'Isticmaale', 3: 'Wada-hadalka isticmaalaha', 4: 'Wikipedia', 5: 'Wada-hadalka Wikipedia', 6: 'Fayl', 7: 'Wada-hadalka faylka', 8: 'MediaWiki', 9: 'Wada-hadalka MediaWiki', 10: 'Qaab', 11: 'Wada-hadalka qaabka', 12: 'Caawimaad', 13: 'Wada-hadalka caawimaada', 14: 'Qayb', 15: 'Wada-hadalka qaybta', 100: 'Bogga hordhaca ah', 101: 'Wada-hadalka bogga hordhaca ah', 118: 'Qabyo', 119: 'Wada-hadalka qabyada', 710: 'TimedText', 711: 'Wada-hadalka TimedText', 828: 'Module', 829: 'Wada-hadalka module-ka' } }; Twinkle.config.commonSets.csdCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteria); Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteriaNotification); Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdAndImageDeletionCriteria); Twinkle.config.sections = [ { title: 'Guud', module: 'general', preferences: [ { name: 'userTalkPageMode', label: 'Marka la furayo bogga wada-hadalka isticmaalaha, fur', type: 'enum', enumValues: { window: 'Daaqad cusub, adigoo beddelaya wada-hadallada kale ee isticmaalaha', tab: 'Tab cusub', blank: 'Daaqad cusub oo dhammaystiran' } }, { name: 'dialogLargeFont', label: 'Isticmaal qoraal ka weyn wada-sheekaysiga Twinkle', type: 'boolean' }, { name: 'disabledModules', label: 'Demi qaybaha Twinkle ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', type: 'set', setValues: { arv: 'ARV', warn: 'Dig', welcome: 'Soo dhawoow', talkback: 'Talkback', speedy: 'CSD', prod: 'PROD', xfd: 'XfD', image: 'Fayl (DI)', protect: 'Dhowr (RPP)', tag: 'Calaamadi', diff: 'Isbarbardhig', unlink: 'Ka goy xiriirinta', rollback: 'Rogo iyo dib u celi' } }, { name: 'disabledSysopModules', label: 'Demi qaybaha maamulayaasha kaliya ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', adminOnly: true, type: 'set', setValues: { block: 'Xannib', deprod: 'DePROD', batchdelete: 'Tirtiridda wadareed', batchprotect: 'Dhowridda wadareed', batchundelete: 'Soo-celinta wadareed' } } ] }, { title: 'ARV', module: 'arv', preferences: [ { name: 'spiWatchReport', label: 'Ku dar boggaga warbixinta lammaanaha liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Xannib isticmaalaha', module: 'block', adminOnly: true, preferences: [ { name: 'defaultToBlock64', label: 'Ciwaannada IPv6, dooro ikhtiyaarka ah in la xannibo xadka /64 si caadi ah', type: 'boolean' }, { name: 'defaultToPartialBlocks', label: 'Dooro xannibaadaha qayb ahaan si caadi ah marka la furayo liiska xannibaadda', helptip: 'Haddii isticmaalaha horay loo xannibay, tan waa la beddeli doonaa iyadoo la doorbidayo nooca xannibaadda ee hadda', type: 'boolean' }, { name: 'blankTalkpageOnIndefBlock', label: 'Tirtir bogga wada-hadalka marka si aan xad lahayn loo xannibayo isticmaaleyaasha', helptip: 'Fiiri <a href="' + mw.util.getUrl('Wikipedia:WikiProject_User_warnings/Usage_and_layout#Indefinitely_blocked_users') + '">WP:UWUL</a> wixii macluumaad dheeraad ah.', type: 'boolean' } ] }, { title: 'Tirtiridda faylka (DI)', module: 'image', preferences: [ { name: 'notifyUserOnDeli', label: 'Calaamadi sanduuqa "ogeysii soo geliyaha bilowga ah" si caadi ah', type: 'boolean' }, { name: 'deliWatchPage', label: 'Ku dar bogga faylka liiska la socodka marka la calaamadinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'deliWatchUser', label: 'Ku dar bogga wada-hadalka ee soo geliyaha bilowga ah liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Dhowridda bogga ' + (Morebits.userIsSysop ? '(PP)' : '(RPP)'), module: 'protect', preferences: [ { name: 'watchRequestedPages', label: 'Ku dar bogga liiska la socodka marka la codsanayo dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchPPTaggedPages', label: 'Ku dar bogga liiska la socodka marka lagu calaamadinayo qaabka dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchProtectedPages', label: 'Ku dar bogga liiska la socodka marka la dhowrayo', helptip: 'Haddii sidoo kale bogga la calaamadiyo dhowridda ka dib, doorbiditaankaas ayaa la mudnaansiin doonaa.', adminOnly: true, type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Tirtiridda la soo jeediyay (PROD)', module: 'prod', preferences: [ { name: 'watchProdPages', label: 'Ku dar maqaalka liiska la socodka marka la dabaqayo qaabka prod', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markProdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, { name: 'prodReasonDefault', label: 'Sababta PROD ee horay loo sii buuxiyay', type: 'string' }, { name: 'logProdPages', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u calaamadiso PROD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u calaamadiso PROD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'prodLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee PROD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga PROD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee PROD.', type: 'string' } ] }, { title: 'Rogo iyo dib u celi', module: 'rollback', preferences: [ { name: 'autoMenuAfterRollback', label: 'Si otomaatig ah u fur liiska digida Twinkle ee bogga wada-hadalka isticmaalaha ka dib dib-u-celinta Twinkle', helptip: 'Wuxuu shaqeeyaa kaliya haddii sanduuqa khuseeya la calaamadiyay xagga hoose.', type: 'boolean' }, { name: 'openTalkPage', label: 'Fur bogga wada-hadalka isticmaalaha ka dib noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda' } }, { name: 'openTalkPageOnAutoRevert', label: 'Fur bogga wada-hadalka isticmaalaha marka laga yeerayo dib-u-celinta tabarucaadka isticmaalaha ama isbeddellada dhow', helptip: 'Marka tani shidan tahay, xulashooyinka la rabay waa in la hawlgeliyaa qaybtii hore si ay tani u shaqeyso.', type: 'boolean' }, { name: 'rollbackInPlace', label: 'Ha dib u soo dejin bogga marka dib looga celinayo tabarucaadka ama isbeddellada dhow', helptip: 'Marka tani shidan tahay, Twinkle dib u soo dejin maayo quudinta tabarucaadka ama isbeddellada dhow ka dib dib u celinta, taasoo kuu oggolaanaysa inaad dib u celiso wax ka badan hal tifatir hal mar.', type: 'boolean' }, { name: 'markRevertedPagesAsMinor', label: 'Calaamadi sida tifatir yar noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, { name: 'watchRevertedPages', label: 'Ku dar boggaga liiska la socodka noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, { name: 'watchRevertedExpiry', label: 'Marka dib loo celinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'offerReasonOnNormalRevert', label: 'Weydii sababta dib u celinta caadiga ah', helptip: 'Dib u celinta "Caadiga ah" waa kuwa laga yeero xiriirka dhex[rollback].', type: 'boolean' }, { name: 'confirmOnRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (dhammaan qalabka)', helptip: 'Isticmaalayaasha qalabka qoraalka ama taabashada, iyo dadka go\'aan la\'aanta joogtada ah hayso.', type: 'boolean' }, { name: 'confirmOnMobileRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (qalabka gacanta kaliya)', helptip: 'Iska ilaali dib u celinta shilalka ah marka aad joogto qalabka gacanta.', type: 'boolean' }, { name: 'showRollbackLinks', label: 'Muuji xiriiriyeyaasha dib-u-celinta boggagani', type: 'set', setValues: { diff: 'Boggaga isbarbardhigga', others: 'Boggaga tabarucaadka ee isticmaaleyaasha kale', mine: 'Bogga tabarucaadkayga', recent: 'Isbeddellada dhow iyo boggaga gaarka ah ee la xiriira', history: 'Boggaga taariikhda' } } ] }, { title: 'Tirtiridda degdegga ah (CSD)', module: 'speedy', preferences: [ { name: 'speedySelectionStyle', label: 'Goorta la sii wado oo la calaamadiyo/tirtiro bogga', type: 'enum', enumValues: { buttonClick: 'Marka aan gujiyo "Gudbi"', radioClick: 'Isla marka aan gujiyo ikhtiyaar' } }, { name: 'watchSpeedyPages', label: 'Ku dar bogga liiska la socodka marka la isticmaalayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdCriteria, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder }, { name: 'watchSpeedyExpiry', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markSpeedyPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, { name: 'watchSpeedyUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'welcomeUserOnSpeedyDeletionNotification', label: 'Soo dhawee abuuraha bogga marka lagu ogeysiinayo shuruudahan', helptip: 'Soo dhaweynta waxaa la bixiyaa kaliya haddii isticmaalaha lagaga ogeysiiyo tirtiridda, iyo kaliya haddii boggiisa wada-hadalku uusan weli jirin. Qaabka la isticmaalo waa {{firstarticle}}.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, { name: 'notifyUserOnSpeedyDeletionNomination', label: 'Ogeysii abuuraha bogga marka lagu calaamadinayo shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, { name: 'warnUserOnSpeedyDelete', label: 'Ogeysii abuuraha bogga marka la tirtirayo hoos shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, { name: 'promptForSpeedyDeletionSummary', label: 'U oggolow tafatirka kooban-tafsirka tirtiridda marka la tirtirayo hoos shuruudahan', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder }, { name: 'deleteTalkPageOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir bogga wada-hadalka" si caadi ah', adminOnly: true, type: 'boolean' }, { name: 'deleteRedirectsOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir dib-u-jeeddada" si caadi ah', adminOnly: true, type: 'boolean' }, { name: 'deleteSysopDefaultToDelete', label: 'Ka dhig shaashadda CSD mid si caadi ah ugu tagta "tirtir" halkii ay ka noqon lahayd "calaamadi"', helptip: 'Haddii ay jirto calaamad CSD oo horay u joogta, Twinkle wuxuu mar walba si caadi ah ugu noqon doonaa habka "tirtir"', adminOnly: true, type: 'boolean' }, { name: 'speedyWindowWidth', label: 'Ballaca daaqadda tirtiridda degdegga ah (pixels)', type: 'integer' }, { name: 'speedyWindowHeight', label: 'Dhererka daaqadda tirtiridda degdegga ah (pixels)', helptip: 'Haddii aad leedahay kantarool weyn, waxaad jeclaan kartaa inaad kordhiso tan.', type: 'integer' }, { name: 'logSpeedyNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan magacaabista CSD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto CSD adigoo isticmaalaya Twinkle. Faylasha lagu calaamadiyay DI sidoo kale waa la daraa diiwaankan.', type: 'boolean' }, { name: 'speedyLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee CSD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga CSD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee CSD.', type: 'string' }, { name: 'noLogOnSpeedyNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka lagu calaamadinayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder } ] }, { title: 'Calaamadi', module: 'tag', preferences: [ { name: 'watchTaggedVenues', label: 'Ku dar bogga liiska la socodka marka la calaamadinayo noocyadan boggaga ah', type: 'set', setValues: { articles: 'Maqaallo', drafts: 'Qabyo', redirects: 'Dib-u-jeediyo', files: 'Faylal' } }, { name: 'watchTaggedPages', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchMergeDiscussions', label: 'Ku dar boggaga wada-hadalka liiska la socodka marka la bilaabayo doodaha mideynta', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markTaggedPagesAsMinor', label: 'Calaamadi ku darista calaamadaha sida tifatir yar', type: 'boolean' }, { name: 'markTaggedPagesAsPatrolled', label: 'Calaamadi sanduuqa "calaamadi bogga mid la eegay" si caadi ah', type: 'boolean' }, { name: 'tagArticleSortOrder', label: 'Habka aragtida caadiga ah ee calaamadaha maqaalka', type: 'enum', enumValues: { cat: 'Qaybaha', alpha: 'Hab xarfaha ah' } }, { name: 'customTagList', label: 'Calaamadaha dayactirka maqaalka/qabyada gaarka ah ee la soo bandhigayo', helptip: 'Kuwani waxay u muuqdaan ikhtiyaarro dheeraad ah oo hoos yimaada liiska calaamadaha. Tusaale ahaan, waxaad ku dari kartaa calaamado dayactir oo cusub oo aan weli lagu darin kuwa caadiga ah ee Twinkle.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customFileTagList', label: 'Calaamadaha dayactirka faylka gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto faylasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customRedirectTagList', label: 'Calaamadaha qaybta dib-u-jeeddada gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto dib-u-jeediyeyaasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' } ] }, { title: 'Talkback', module: 'talkback', preferences: [ { name: 'markTalkbackAsMinor', label: 'Calaamadi talkbacks sida tifatir yar', type: 'boolean' }, { name: 'insertTalkbackSignature', label: 'Geli saxiixa gudaheeda talkbacks', type: 'boolean' }, { name: 'talkbackHeading', label: 'Madaxa qaybta ee loo isticmaalo talkback iyo fadlan eeg', tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' }, { name: 'mailHeading', label: 'Madaxa qaybta ee loo isticmaalo ogeysiisyada "waxaad haysataa iimeyl"', tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' } ] }, { title: 'Ka goy xiriirinta', module: 'unlink', preferences: [ { name: 'unlinkNamespaces', label: 'Ka saar xiriirinta boggaga ku jira meelahan magaca', helptip: 'Ka fogow doorashada meelaha magaca wada-hadalka, maaddaama Twinkle uu ku dambayn karo inuu ka saaro xiriirinta keydadka wada-hadalka (arrin weyn oo khaldan).', type: 'set', setValues: Twinkle.config.commonSets.namespacesNoSpecial } ] }, { title: 'Dii isticmaalaha', module: 'warn', preferences: [ { name: 'defaultWarningGroup', label: 'Heerka digida caadiga ah', type: 'enum', enumValues: { 1: 'Heerka 1', 2: 'Heerka 2', 3: 'Heerka 3', 4: 'Heerka 4', 5: 'Heerka 4im', 6: 'Ogeysiisyada hal arrin ah', 7: 'Digidaha hal arrin ah', 9: 'Digidaha gaarka ah', 10: 'Dhammaan qaababka digida', 11: 'Heerka is-doorta (1-4)' } }, { name: 'combinedSingletMenus', label: 'Ku beddel labada liis ee hal arrin ah hal liis oo la mideeyay', helptip: 'Doorashada ogeysiisyada hal arrin ah ama digidaha hal arrin ah sida heerkaaga caadiga ah waxay ka dhigi doontaa tan mid caadi ah haddii la hawlgeliyo.', type: 'boolean' }, { name: 'watchWarnings', label: 'Ku dar bogga wada-hadalka isticmaalaha liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'oldSelect', label: 'Isticmaal liiska xulashada caadiga ah ee aan la raadin karin', type: 'boolean' }, { name: 'customWarningList', label: 'Qaababka digida gaarka ah ee la soo bandhigayo', helptip: 'Waxaad ku dari kartaa qaabab shakhsi ah ama hoos-boggaga isticmaalaha. Digidaha gaarka ah waxay ka muuqdaan qaybta "Digidaha gaarka ah" ee ku dhex jirta sanduuqa wada-sheekaysiga digida.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo liiska digida (sidoo kale loo isticmaalo kooban-tafsirka tifatirka)' } ] }, { title: 'Soo dhawee isticmaalaha', module: 'welcome', preferences: [ { name: 'topWelcomes', label: 'Dhig soo-dhaweynta kor1 nuxurka jira ee boggaga wada-hadalka isticmaalaha', type: 'boolean' }, { name: 'watchWelcomes', label: 'Ku dar boggaga wada-hadalka isticmaalaha liiska la socodka marka la soo dhoweynayo', helptip: 'Tani waxay ku daraysaa qaybta shakhsiga ah ee soo-dhaweynta isticmaalaha - waxaad awoodi doontaa inaad aragto sida ay ula qabsanayaan iyagoo ah cusub, oo laga yaabo inaad caawiso.', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'insertUsername', label: 'Ku dar magacaaga isticmaale qaabka (haddii ay khuseyso)', helptip: 'Qaababyada qaarkood ee soo-dhaweynta waxay leeyihiin jumlad furitaan ah sida "Hallo, waxaan ahay &lt;username&gt;. Soo dhawoow" iwm. Haddii aad demiso ikhtiyaarkan, qaababkani ma soo bandhigi doonaan magacaaga isticmaale habkaas.', type: 'boolean' }, { name: 'quickWelcomeMode', label: 'Gujinta xiriiriyaha "soo dhawoow" ee bogga isbarbardhigga (kaas oo ka muuqda kaliya haddii bogga wada-hadalka isticmaalaha ee tifatiraha uusan weli la abuurin) wuxuu doonayaa inuu', helptip: 'Haddii aad doorato inaad soo dhoweyso si otomaatig ah, qaabka aad hoos ku cayimay ayaa la isticmaali doonaa.', type: 'enum', enumValues: { auto: 'isla markiiba soo dhig qaabka soo-dhaweynta ee hoos ku xusan', norm: 'kuu sheeg inaad doorato qaab' } }, { name: 'quickWelcomeTemplate', label: 'Qaabka la isticmaali doono marka si otomaatig ah loo soo dhoweynayo', helptip: 'Geli magaca qaabka soo-dhaweynta, adigoon lahayn qawsafyo. Xiriiriye ku socda maqaalka la bixiyay ayaa lagu dari doonaa.', type: 'string' }, { name: 'customWelcomeList', label: 'Qaababka soo-dhaweynta gaarka ah ee la soo bandhigayo', helptip: 'Waxaad ku dari kartaa qaabab kale oo soo-dhaweyn ah, ama hoos-boggaga isticmaalaha ee ah qaababka soo-dhaweynta (oo leh hor-odhiga "User:"). Ha iloobin in qaababarkan la beddelo oo la geliyo boggaga wada-hadalka isticmaalaha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga soo-dhaweynta' }, { name: 'customWelcomeSignature', label: 'Si otomaatig ah u saxiix qaababka soo-dhaweynta gaarka ah', helptip: 'Haddii qaababkaaga soo-dhaweynta gaarka ah ay ka kooban yihiin saxiix ku dhex jira qaabka gudihiisa, demi ikhtiyaarkan.', type: 'boolean' } ] }, { title: 'XFD (doodaha tirtiridda)', module: 'xfd', preferences: [ { name: 'logXfdNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u magacaabto dood tirtirid (XfD)', helptip: 'Diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto XfD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'xfdLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee doodda tirtiridda hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga XfD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee XfD.', type: 'string' }, { name: 'noLogOnXfdNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka aad ku magacaabeyso goobtan', type: 'set', setValues: { afd: 'AfD', tfd: 'TfD', ffd: 'FfD', cfd: 'CfD', cfds: 'CfD/S', mfd: 'MfD', rfd: 'RfD', rm: 'RM' } }, { name: 'xfdWatchPage', label: 'Ku dar bogga la magacaabay liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'xfdWatchDiscussion', label: 'Ku dar bogga doodda tirtiridda liiska la socodka', helptip: 'Tani waxay tilmaamaysaa hoos-bogga doodda (ee AfD iyo MfD) ama bogga diiwaanka maalinlaha ah (ee TfD, CfD, RfD iyo FfD)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'xfdWatchList', label: 'Ku dar bogga diiwaanka/liiska maalinlaha ah liiska la socodka (AfD iyo MfD)', helptip: 'Tani waxay khuseysaa oo kaliya AfD iyo MfD, halkaas oo doodaha lagu dhex daro bogga diiwaanka maalinlaha ah (ee AfD) ama bogga weyn ee MfD (ee MfD).', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'xfdWatchUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'xfdWatchRelated', label: 'Ku dar bogga bartilmaameedka ee dib-u-jeeddada la magacaabay liiska la socodka (marka la ogeysiinayo)', helptip: 'Tani waxay khuseysaa oo kaliya RfD, marka la reebayo ogeysiis ku yaal bogga wada-hadalka ee bartilmaameedka dib-u-jeeddada', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markXfdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka loo magacaabayo AFD (haddii ay suurtagal tahay)', type: 'boolean' } ] }, { title: 'Qarsan', hidden: true, preferences: [ { name: 'revertMaxRevisions', type: 'integer' }, { name: 'autolevelStaleDays', type: 'integer' }, { name: 'batchMax', type: 'integer', adminOnly: true }, { name: 'batchChunks', type: 'integer', adminOnly: true } ] } ]; Twinkle.config.init = function twinkleconfigInit() { if ((mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').project && mw.config.get('wgTitle') === 'Twinkle/Preferences') && mw.config.get('wgAction') === 'view') { if (!document.getElementById('twinkle-config')) { return; } document.getElementById('twinkle-config').removeAttribute('style'); document.getElementById('twinkle-config-titlebar').removeAttribute('style'); const contentdiv = document.getElementById('twinkle-config-content'); contentdiv.textContent = ''; if (window.TwinkleConfig || window.FriendlyConfig) { const contentnotice = document.createElement('div'); contentnotice.className = 'plainlinks twinkle-ombox'; contentnotice.innerHTML = '<div>' + '<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/3/38/Imbox_content.png" />' + '</div>' + '<div>' + '<p><big><b>Ka hor inta aadan beddelin habayntaada halkan,</b> waa inaad ka saartaa habayntaadii hore ee Twinkle iyo Friendly JavaScript-ka maqaarkaaga shakhsiga ah.</big></p>' + '<p>Si aad tan u samayso, waxaad <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/' + mw.config.get('skin') + '.js', { action: 'edit' }) + '" target="_blank"><b>tifatiri kartaa faylka javascript maqaarkaaga shakhsiga ah</b></a> ama <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/common.js', { action: 'edit'}) + '" target="_blank"><b>faylkaaga common.js</b></a>, adigoo ka saaraya dhammaan xarumaha koodka ee tixraacaya <code>TwinkleConfig</code> iyo <code>FriendlyConfig</code>.</p>' + '</div>'; contentdiv.appendChild(contentnotice); } const toctable = document.createElement('div'); toctable.className = 'toc'; toctable.style.marginLeft = '0.4em'; const toctitle = document.createElement('div'); toctitle.id = 'toctitle'; const toch2 = document.createElement('h2'); toch2.textContent = 'Muxuu ka kooban yahay '; toctitle.appendChild(toch2); const toctoggle = document.createElement('span'); toctoggle.className = 'toctoggle'; toctoggle.appendChild(document.createTextNode('[')); const toctogglelink = document.createElement('a'); toctogglelink.className = 'internal'; toctogglelink.setAttribute('href', '#tw-tocshowhide'); toctogglelink.textContent = 'qari'; toctoggle.appendChild(toctogglelink); toctoggle.appendChild(document.createTextNode(']')); toctitle.appendChild(toctoggle); toctable.appendChild(toctitle); const tocul = document.createElement('ul'); toctogglelink.addEventListener('click', () => { const $tocul = $(tocul); $tocul.toggle(); if ($tocul.find(':visible').length) { toctogglelink.textContent = 'qari'; } else { toctogglelink.textContent = 'muuji'; } }, false); toctable.appendChild(tocul); contentdiv.appendChild(toctable); const contentform = document.createElement('form'); contentform.setAttribute('action', 'javascript:void(0)'); contentform.addEventListener('submit', Twinkle.config.save, true); contentdiv.appendChild(contentform); const container = document.createElement('table'); container.style.width = '100%'; contentform.appendChild(container); $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; } const tocli = document.createElement('li'); tocli.className = 'toclevel-1'; const toca = document.createElement('a'); toca.setAttribute('href', '#' + section.module); toca.appendChild(document.createTextNode(section.title)); tocli.appendChild(toca); tocul.appendChild(tocli); let row = document.createElement('tr'); let cell = document.createElement('td'); cell.setAttribute('colspan', '3'); const heading = document.createElement('h4'); heading.style.borderBottom = '1px solid gray'; heading.style.marginTop = '0.2em'; heading.id = section.module; heading.appendChild(document.createTextNode(section.title)); cell.appendChild(heading); row.appendChild(cell); container.appendChild(row); let rowcount = 1; $(section.preferences).each((prefkey, pref) => { if (pref.adminOnly && !Morebits.userIsSysop) { return true; } row = document.createElement('tr'); row.style.marginBottom = '0.2em'; if (rowcount++ % 2 === 0) { row.style.backgroundColor = 'rgba(128, 128, 128, 0.1)'; } cell = document.createElement('td'); let label, input; const gotPref = Twinkle.getPref(pref.name); switch (pref.type) { case 'boolean': cell.setAttribute('colspan', '2'); label = document.createElement('label'); input = document.createElement('input'); input.setAttribute('type', 'checkbox'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (gotPref === true) { input.setAttribute('checked', 'checked'); } label.appendChild(input); label.appendChild(document.createTextNode(pref.label)); cell.appendChild(label); break; case 'string': case 'integer': cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('input'); input.setAttribute('type', 'text'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (pref.type === 'integer') { input.setAttribute('size', 6); input.setAttribute('type', 'number'); input.setAttribute('step', '1'); } if (gotPref) { input.setAttribute('value', gotPref); } cell.appendChild(input); break; case 'enum': cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('select'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); $.each(pref.enumValues, (enumvalue, enumdisplay) => { const option = document.createElement('option'); option.setAttribute('value', enumvalue); if ((gotPref === enumvalue) || (typeof gotPref === 'boolean' && ((gotPref && enumvalue === 'yes') || (!gotPref && enumvalue === 'no')))) { option.setAttribute('selected', 'selected'); } option.appendChild(document.createTextNode(enumdisplay)); input.appendChild(option); }); cell.appendChild(input); break; case 'set': cell.setAttribute('colspan', '2'); label = document.createElement('label'); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); var checkdiv = document.createElement('div'); checkdiv.style.paddingLeft = '1em'; var worker = function(itemkey, itemvalue) { const checklabel = document.createElement('label'); checklabel.style.marginRight = '0.7em'; checklabel.style.display = 'inline-block'; const check = document.createElement('input'); check.setAttribute('type', 'checkbox'); check.setAttribute('id', pref.name + '_' + itemkey); check.setAttribute('name', pref.name + '_' + itemkey); if (gotPref && gotPref.includes(itemkey)) { check.setAttribute('checked', 'checked'); } if (pref.name === 'unlinkNamespaces') { if (gotPref && gotPref.includes(parseInt(itemkey, 10))) { check.setAttribute('checked', 'checked'); } } checklabel.appendChild(check); checklabel.appendChild(document.createTextNode(itemvalue)); checkdiv.appendChild(checklabel); }; if (pref.setDisplayOrder) { $.each(pref.setDisplayOrder, (itemkey, item) => { worker(item, pref.setValues[item]); }); } else { $.each(pref.setValues, worker); } cell.appendChild(checkdiv); break; case 'customList': cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); cell = document.createElement('td'); cell.style.paddingRight = '1em'; var button = document.createElement('button'); button.setAttribute('id', pref.name); button.setAttribute('name', pref.name); button.setAttribute('type', 'button'); button.addEventListener('click', Twinkle.config.listDialog.display, false); $(button).data({ value: gotPref, pref: pref }); button.appendChild(document.createTextNode('Wax ka beddel walxaha')); cell.appendChild(button); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } row.appendChild(cell); cell = document.createElement('td'); cell.className = 'twinkle-config-helptip'; if (pref.helptip) { cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g, '{{<a href="' + mw.util.getUrl('Template:') + '$1" target="_blank">$1</a>}}'); } if (pref.type !== 'customList') { const resetlink = document.createElement('a'); resetlink.setAttribute('href', '#tw-reset'); resetlink.setAttribute('id', 'twinkle-config-reset-' + pref.name); resetlink.addEventListener('click', Twinkle.config.resetPrefLink, false); resetlink.style.cssFloat = 'right'; resetlink.style.margin = '0 0.6em'; resetlink.appendChild(document.createTextNode('Dib u deji')); cell.appendChild(resetlink); } row.appendChild(cell); container.appendChild(row); return true; }); return true; }); const footerbox = document.createElement('div'); footerbox.setAttribute('id', 'twinkle-config-buttonpane'); const button = document.createElement('button'); button.setAttribute('id', 'twinkle-config-submit'); button.setAttribute('type', 'submit'); button.appendChild(document.createTextNode('Kaydi isbeddellada')); footerbox.appendChild(button); const footerspan = document.createElement('span'); footerspan.className = 'plainlinks'; footerspan.style.marginLeft = '2.4em'; footerspan.style.fontSize = '90%'; const footera = document.createElement('a'); footera.setAttribute('href', '#tw-reset-all'); footera.setAttribute('id', 'twinkle-config-resetall'); footera.addEventListener('click', Twinkle.config.resetAllPrefs, false); footera.appendChild(document.createTextNode('Soo celi waxyaabaha caadiga ah')); footerspan.appendChild(footera); footerbox.appendChild(footerspan); contentform.appendChild(footerbox); if (window.location.hash) { const loc = window.location.hash; window.location.hash = ''; window.location.hash = loc; } } else if (mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user && mw.config.get('wgTitle').indexOf(mw.config.get('wgUserName')) === 0 && mw.config.get('wgPageName').slice(-3) === '.js') { const box = document.createElement('div'); box.setAttribute('id', 'twinkle-config-headerbox'); let link; const scriptPageName = mw.config.get('wgPageName').slice( mw.config.get('wgPageName').lastIndexOf('/') + 1, mw.config.get('wgPageName').lastIndexOf('.js') ); if (scriptPageName === 'twinkleoptions') { box.setAttribute('class', 'config-twopt-box'); if (mw.config.get('wgArticleId') > 0) { box.appendChild(document.createTextNode('Boggani wuxuu ka kooban yahay doorbidyadaada Twinkle. Waxaad ku beddeli kartaa adigoo isticmaalaya ')); } else { box.appendChild(document.createTextNode('Waxaad habayn kartaa Twinkle si uu ugu habboonaado doorbidyadaada adigoo isticmaalaya ')); } link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode(', ama adigoo tifatiraya boggan.')); $(box).insertAfter($('#contentSub')); } else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].includes(scriptPageName)) { box.setAttribute('class', 'config-userskin-box'); box.appendChild(document.createTextNode('Haddii aad rabto inaad dejiso doorbidyada Twinkle, waxaad isticmaali kartaa ')); link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode('.')); $(box).insertAfter($('#contentSub')); } } }; Twinkle.config.listDialog = {}; Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow($dlgtable, value, label) { let $contenttr, $valueInput, $labelInput; $dlgtable.append( $contenttr = $('<tr>').append( $('<td>').append( $('<button>') .attr('type', 'button') .on('click', () => { $contenttr.remove(); }) .text('Tirtir') ), $('<td>').append( $valueInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-value') .css('width', '97%') ), $('<td>').append( $labelInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-label') .css('width', '98%') ) ) ); if (value) { $valueInput.val(value); } if (label) { $labelInput.val(label); } }; Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) { const $prefbutton = $(e.target); const curvalue = $prefbutton.data('value'); const curpref = $prefbutton.data('pref'); const dialog = new Morebits.SimpleWindow(720, 400); dialog.setTitle(curpref.label); dialog.setScriptName('Doorbidyada Twinkle'); let $dlgtbody; dialog.setContent( $('<div>').append( $('<table>') .addClass('wikitable') .css({ margin: '1.4em 1em', width: 'auto' }) .append( $dlgtbody = $('<tbody>').append( $('<tr>').append( $('<th>') .css('width', '5%'), $('<th>') .css('width', '35%') .text(curpref.customListValueTitle ? curpref.customListValueTitle : 'Qiimaha'), $('<th>') .css('width', '60%') .text(curpref.customListLabelTitle ? curpref.customListLabelTitle : 'Calaamadda') ) ), $('<tfoot>').append( $('<tr>').append( $('<td>') .attr('colspan', '3') .append( $('<button>') .text('Ku dar') .css('min-width', '8em') .attr('type', 'button') .on('click', () => { Twinkle.config.listDialog.addRow($dlgtbody); }) ) ) ) ), $('<button>') .text('Kaydi isbeddellada') .attr('type', 'submit') .on('click', () => { Twinkle.config.listDialog.save($prefbutton, $dlgtbody); dialog.close(); }), $('<button>') .text('Dib u deji') .attr('type', 'submit') .on('click', () => { Twinkle.config.listDialog.reset($prefbutton, $dlgtbody); }), $('<button>') .text('Jooji') .attr('type', 'submit') .on('click', () => { dialog.close(); }) )[0] ); let gotRow = false; $.each(curvalue, (k, v) => { gotRow = true; Twinkle.config.listDialog.addRow($dlgtbody, v.value, v.label); }); if (!gotRow) { Twinkle.config.listDialog.addRow($dlgtbody); } dialog.display(); }; Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset($button, $tbody) { const curpref = $button.data('pref'); const oldvalue = $button.data('value'); Twinkle.config.resetPref(curpref); $tbody.find('tr').slice(1).remove(); const curvalue = $button.data('value'); $.each(curvalue, (k, v) => { Twinkle.config.listDialog.addRow($tbody, v.value, v.label); }); $button.data('value', oldvalue); }; Twinkle.config.listDialog.save = function twinkleconfigListDialogSave($button, $tbody) { const result = []; let current = {}; $tbody.find('input[type="text"]').each((inputkey, input) => { if ($(input).hasClass('twinkle-config-customlist-value')) { current = { value: input.value }; } else { current.label = input.value; if (current.value || current.label) { result.push(current); } } }); $button.data('value', result); }; Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) { const wantedpref = e.target.id.slice(21); $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; } let foundit = false; $(section.preferences).each((prefkey, pref) => { if (pref.name !== wantedpref) { return true; } Twinkle.config.resetPref(pref); foundit = true; return false; }); if (foundit) { return false; } }); return false; }; Twinkle.config.resetPref = function twinkleconfigResetPref(pref) { switch (pref.type) { case 'boolean': document.getElementById(pref.name).checked = Twinkle.defaultConfig[pref.name]; break; case 'string': case 'integer': case 'enum': document.getElementById(pref.name).value = Twinkle.defaultConfig[pref.name]; break; case 'set': $.each(pref.setValues, (itemkey) => { if (document.getElementById(pref.name + '_' + itemkey)) { document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].includes(itemkey); } }); break; case 'customList': $(document.getElementById(pref.name)).data('value', Twinkle.defaultConfig[pref.name]); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } }; Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() { $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; } $(section.preferences).each((prefkey, pref) => { if (!pref.adminOnly || Morebits.userIsSysop) { Twinkle.config.resetPref(pref); } }); return true; }); return false; }; Twinkle.config.save = function twinkleconfigSave(e) { Morebits.Status.init(document.getElementById('twinkle-config-content')); const userjs = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user] + ':' + mw.config.get('wgUserName') + '/twinkleoptions.js'; const wikipediaPage = new Morebits.wiki.Page(userjs, 'Kaydinaya doorbidyada ' + userjs); wikipediaPage.setCallbackParameters(e.target); wikipediaPage.load(Twinkle.config.writePrefs); return false; }; Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) { const form = pageobj.getCallbackParameters(); const newConfig = {optionsVersion: 2.1}; const compare = function(a, b) { if (Array.isArray(a)) { if (a.length !== b.length) { return false; } const asort = a.sort(), bsort = b.sort(); for (let i = 0; asort[i]; ++i) { if ((typeof asort[i] === 'object') && (asort[i].label !== bsort[i].label || asort[i].value !== bsort[i].value)) { return false; } else if (asort[i].toString() !== bsort[i].toString()) { return false; } } return true; } return a === b; }; $(Twinkle.config.sections).each((sectionkey, section) => { if (section.adminOnly && !Morebits.userIsSysop) { return; } $(section.preferences).each((prefkey, pref) => { let userValue; if (!pref.adminOnly || Morebits.userIsSysop) { if (!section.hidden) { switch (pref.type) { case 'boolean': userValue = form[pref.name].checked; break; case 'string': case 'enum': userValue = form[pref.name].value; break; case 'integer': userValue = parseInt(form[pref.name].value, 10); if (isNaN(userValue)) { Morebits.Status.warn('Kaydinaya', 'Qiimaha aad u cayimay ' + pref.name + ' (' + pref.value + ') wuxuu ahaa mid aan shaqaynayn. Kaydintu waa sii socon doontaa, laakiin xogta khaldan waa la dhaafi doonaa.'); userValue = null; } break; case 'set': userValue = []; if (pref.setDisplayOrder) { $.each(pref.setDisplayOrder, (itemkey, item) => { if (form[pref.name + '_' + item].checked) { userValue.push(item); } }); } else { $.each(pref.setValues, (itemkey) => { if (form[pref.name + '_' + itemkey].checked) { userValue.push(itemkey); } }); } break; case 'customList': userValue = $(form[pref.name]).data('value'); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } } else if (Twinkle.prefs) { userValue = Twinkle.prefs[pref.name]; } } if (userValue !== undefined && !compare(userValue, Twinkle.defaultConfig[pref.name])) { newConfig[pref.name] = userValue; } }); }); let text = '// twinkleoptions.js: faylka doorbidyada shakhsiga ah ee Twinkle\n' + '//\n' + '// FIIRO GAAR AH: Habka ugu fudud ee aad ku beddeli karto doorbidyadaada Twinkle waa adigoo isticmaalaya\n' + '// guddiga doorbididda Twinkle, ee [[:' + Morebits.pageNameNorm + ']].\n' + '//\n' + '// Faylkan waxaa la soo saaray SI OTOMAATIG AH. Wixii isbeddel ah ee aad samayso (marka laga reebo\n' + '// beddelidda cabbiraadaha habaynta si JavaScript sax ah u ah) waxaa lagu\n' + '// dul qori doonaa marka xigta ee aad gujiso "kaydi" guddiga doorbididda\n' + '// Twinkle. Haddii aad wax ka beddelayso faylkan, hubi inaad isticmaasho JavaScript sax ah.\n' + '// <no' + 'wiki>\n' + '\n' + 'window.Twinkle.prefs = '; text += JSON.JSON.stringify(newConfig, null, 2); // Waa la hubiyay saxnaanta JSON-ka text += ';\n' + '\n' + '// </no' + 'wiki>\n' + '// Dhamaadka twinkleoptions.js\n'; pageobj.setPageText(text); pageobj.setEditSummary('Kaydinaya doorbidyada Twinkle: tifatir otomaatig ah oo ka yimid [[:' + Morebits.pageNameNorm + ']]'); pageobj.setChangeTags(Twinkle.changeTags); pageobj.setCreateOption('recreate'); pageobj.save(Twinkle.config.saveSuccess); }; Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) { pageobj.getStatusElement().info('waa lagu guulaystay'); const noticebox = document.createElement('div'); noticebox.className = 'cdx-message cdx-message--success'; noticebox.style.fontSize = '100%'; noticebox.innerHTML = '<p><b>Doorbidyadaada Twinkle waa la kaydiyay.</b> Si aad u aragto isbeddellada, waxaad u baahan doontaa inaad gebi ahaanba nadiifiso kaydka biraawsarkaaga (fiiri <a href="' + mw.util.getUrl('WP:BYPASS') + '" title="WP:BYPASS">WP:BYPASS</a> tilmaamaha).</p>'; mw.loader.using('mediawiki.htmlform.codex.styles', () => { Morebits.Status.root.appendChild(noticebox); }); const noticeclear = document.createElement('br'); noticeclear.style.clear = 'both'; Morebits.Status.root.appendChild(noticeclear); }; Twinkle.addInitCallback(Twinkle.config.init); }()); // </nowiki> cl1bdsaevcflj3lpyvvjucvi3nzhekv 311228 311227 2026-10-28T16:13:24Z Isma4l 41797 311228 javascript text/javascript // <nowiki> (function() { /* **************************************** *** twinkleconfig.js: Qaybta doorbidda **************************************** * Qaabka loo yeero: Wuxuu ku darayaa foomka qaab-yaynta Wikipedia:Twinkle/Preferences, wuxuuna ku darayaa sanduuq xayaysiis ah dusha sare ee hoos-boggaga isticmaalaha ee leh isticmaalaha hadda soo galay oo ku dhammaada '.js' * Ka shaqeeya: Waxa aan hadda sayey. Haa. */ Twinkle.config = {}; Twinkle.config.watchlistEnums = { yes: 'Ku dar liiska la socodka (si aan xad lahayn)', no: "Ha ku darin liiska la socodka", default: 'Raac doorbidyada boggaaga', '1 week': 'La soco 1 toddobaad', '1 month': 'La soco 1 bil', '3 months': 'La soco 3 bilood', '6 months': 'La soco 6 bilood' }; Twinkle.config.commonSets = { csdCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f8: 'F8', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, csdCriteriaNotification: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5 ("xadgudubka ciqaabta guud" kaliya)', g6: 'G6 ("guuritaanka koobi-iyo-dheji" kaliya)', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', u6: 'U6', u7: 'U7' }, csdAndImageDeletionCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f11: 'F11', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, namespacesNoSpecial: { 0: 'Maqaal', 1: 'Wada-hadal (maqaal)', 2: 'Isticmaale', 3: 'Wada-hadalka isticmaalaha', 4: 'Wikipedia', 5: 'Wada-hadalka Wikipedia', 6: 'Fayl', 7: 'Wada-hadalka faylka', 8: 'MediaWiki', 9: 'Wada-hadalka MediaWiki', 10: 'Qaab', 11: 'Wada-hadalka qaabka', 12: 'Caawimaad', 13: 'Wada-hadalka caawimaada', 14: 'Qayb', 15: 'Wada-hadalka qaybta', 100: 'Bogga hordhaca ah', 101: 'Wada-hadalka bogga hordhaca ah', 118: 'Qabyo', 119: 'Wada-hadalka qabyada', 710: 'TimedText', 711: 'Wada-hadalka TimedText', 828: 'Module', 829: 'Wada-hadalka module-ka' } }; Twinkle.config.commonSets.csdCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteria); Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteriaNotification); Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdAndImageDeletionCriteria); /** * Faahfaahinta qaybaha cutubyada: * * { * title: <magaca cutubka ee la akhrin karo>, * module: <magaca qaybta la xiriirta, ee loo isticmaalo in lagu xiro cutubyada>, * adminOnly: <run ah cutubyada maamulayaasha kaliya>, * hidden: <run ah doorbidyada horumarsan ee naadirka ah in la beddelo - weli waxaa lagu beddeli karaa adigoo si gacanta ah u tifatiraya twinkleoptions.js>, * preferences: [ * { * name: <magaca hantida TwinkleConfig>, * label: <sharaxaad gaaban oo la akhrin karo - oo loo isticmaalo sidii sumad foomka ah>, * helptip: <(ikhtiyaari) qoraal la akhrin karo (oo isticmaalaya HTML sax ah) oo buuxinaya sharaxaadda, sida xadka, digidaha, iwm.> * adminOnly: <run ah doorbidyada maamulayaasha kaliya>, * type: <string|boolean|integer|enum|set|customList> (customList waxay kaydisaa safafka walxaha JSON { value, label }), * enumValues: <nooca = "enum": shay JSON ah halkaas oo furayaashu yihiin magacyada gudaha iyo qiyamku yihiin xargaha la akhrin karo>, * setValues: <nooca = "set": shay JSON ah halkaas oo furayaashu yihiin magacyada gudaha iyo qiyamku yihiin xargaha la akhrin karo>, * setDisplayOrder: <(ikhtiyaari) nooca = "set": xarig ay ku jiraan furayaasha setValues (sida xargaha) habka loo soo bandhigayo>, * customListValueTitle: <nooca = "customList": cinwaanka tiirka bidix "qiimaha" ee tifaftiraha liiska gaarka ah>, * customListLabelTitle: <nooca = "customList": cinwaanka tiirka midig "calaamadda" ee tifaftiraha liiska gaarka ah> * }, * . . . * ] * }, * . . . * */ Twinkle.config.sections = [ { title: 'Guud', module: 'general', preferences: [ // TwinkleConfig.userTalkPageMode waxay qaadan kartaa doodaha: // 'window': fur daaqad cusub, xasuuso daaqadda la furay // 'tab': waxay ku furaysaa tab cusub, haddii ay suurtagal tahay. // 'blank': ku qasbi in lagu furo daaqad cusub, xitaa haddii daaqad sidaas oo kale ah ay jirto { name: 'userTalkPageMode', label: 'Marka la furayo bogga wada-hadalka isticmaalaha, fur', type: 'enum', enumValues: { window: 'Daaqad cusub, adigoo beddelaya wada-hadallada kale ee isticmaalaha', tab: 'Tab cusub', blank: 'Daaqad cusub oo dhammaystiran' } }, // TwinkleConfig.dialogLargeFont (boolean) { name: 'dialogLargeFont', label: 'Isticmaal qoraal ka weyn wada-sheekaysiga Twinkle', type: 'boolean' }, // Twinkle.config.disabledModules (array) { name: 'disabledModules', label: 'Demi qaybaha Twinkle ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', type: 'set', setValues: { arv: 'ARV', warn: 'Dig', welcome: 'Soo dhawoow', talkback: 'Talkback', speedy: 'CSD', prod: 'PROD', xfd: 'XfD', image: 'Fayl (DI)', protect: 'Dhowr (RPP)', tag: 'Calaamadi', diff: 'Isbarbardhig', unlink: 'Ka goy xiriirinta', rollback: 'Rogo iyo dib u celi' } }, // Twinkle.config.disabledSysopModules (array) { name: 'disabledSysopModules', label: 'Demi qaybaha maamulayaasha kaliya ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', adminOnly: true, type: 'set', setValues: { block: 'Xannib', deprod: 'DePROD', batchdelete: 'Tirtiridda wadareed', batchprotect: 'Dhowridda wadareed', batchundelete: 'Soo-celinta wadareed' } } ] }, { title: 'ARV', module: 'arv', preferences: [ { name: 'spiWatchReport', label: 'Ku dar boggaga warbixinta lammaanaha liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Xannib isticmaalaha', module: 'block', adminOnly: true, preferences: [ // TwinkleConfig.defaultToBlock64 (boolean) // Haddii si caadi ah loo xannibayo /64 ama in kale { name: 'defaultToBlock64', label: 'Ciwaannada IPv6, dooro ikhtiyaarka ah in la xannibo xadka /64 si caadi ah', type: 'boolean' }, // TwinkleConfig.defaultToPartialBlocks (boolean) // Haddii si caadi ah loo dooranayo xannibaadaha qayb ahaan { name: 'defaultToPartialBlocks', label: 'Dooro xannibaadaha qayb ahaan si caadi ah marka la furayo liiska xannibaadda', helptip: 'Haddii isticmaalaha horay loo xannibay, tan waa la beddeli doonaa iyadoo la doorbidayo nooca xannibaadda ee hadda', type: 'boolean' }, // TwinkleConfig.blankTalkpageOnIndefBlock (boolean) // haddii ay run tahay, tirtir bogga wada-hadalka marka la soo saarayo digid xannibaad aan xad lahayn (sida ku jirta [[WP:UWUL#Indefinitely blocked users]]) { name: 'blankTalkpageOnIndefBlock', label: 'Tirtir bogga wada-hadalka marka si aan xad lahayn loo xannibayo isticmaaleyaasha', helptip: 'Fiiri <a href="' + mw.util.getUrl('Wikipedia:WikiProject_User_warnings/Usage_and_layout#Indefinitely_blocked_users') + '">WP:UWUL</a> wixii macluumaad dheeraad ah.', type: 'boolean' } ] }, { title: 'Tirtiridda faylka (DI)', module: 'image', preferences: [ // TwinkleConfig.notifyUserOnDeli (boolean) // Haddii isticmaalaha la ogeysiinayo ka dib marka la geliyo calaamadda tirtiridda faylka { name: 'notifyUserOnDeli', label: 'Calaamadi sanduuqa "ogeysii soo geliyaha bilowga ah" si caadi ah', type: 'boolean' }, // TwinkleConfig.deliWatchPage (string) // Dejinta liiska la socodka ee bogga loo calaamadiyay tirtiridda. { name: 'deliWatchPage', label: 'Ku dar bogga faylka liiska la socodka marka la calaamadinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.deliWatchUser (string) // Dejinta liiska la socodka ee bogga wada-hadalka isticmaalaha haddii ogeysiis la geliyo. { name: 'deliWatchUser', label: 'Ku dar bogga wada-hadalka ee soo geliyaha bilowga ah liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Dhowridda bogga ' + (Morebits.userIsSysop ? '(PP)' : '(RPP)'), module: 'protect', preferences: [ { name: 'watchRequestedPages', label: 'Ku dar bogga liiska la socodka marka la codsanayo dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchPPTaggedPages', label: 'Ku dar bogga liiska la socodka marka lagu calaamadinayo qaabka dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchProtectedPages', label: 'Ku dar bogga liiska la socodka marka la dhowrayo', helptip: 'Haddii sidoo kale bogga la calaamadiyo dhowridda ka dib, doorbiditaankaas ayaa la mudnaansiin doonaa.', adminOnly: true, type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Tirtiridda la soo jeediyay (PROD)', module: 'prod', preferences: [ // TwinkleConfig.watchProdPages (string) // Dejinta liiska la socodka marka la dabaqayo qaabka prod ee bogga { name: 'watchProdPages', label: 'Ku dar maqaalka liiska la socodka marka la dabaqayo qaabka prod', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.markProdPagesAsPatrolled (boolean) // Haddii, marka la dabaqayo qaabka prod bogga, in bogga lagu calaamadiyo mid la eegay/la kormeeraay (haddii bogga laga gaaray NewPages) { name: 'markProdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, // TwinkleConfig.prodReasonDefault (string) // Sababta PROD ee horay loo sii buuxiyay. { name: 'prodReasonDefault', label: 'Sababta PROD ee horay loo sii buuxiyay', type: 'string' }, { name: 'logProdPages', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u calaamadiso PROD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u calaamadiso PROD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'prodLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee PROD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga PROD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee PROD.', type: 'string' } ] }, { title: 'Rogo iyo dib u celi', module: 'rollback', preferences: [ // TwinkleConfig.autoMenuAfterRollback (bool) // Ikhtiyaar si otomaatig ah u furaya liiska digida haddii bogga wada-hadalka isticmaalaha la furo ka dib dib-u-celinta { name: 'autoMenuAfterRollback', label: 'Si otomaatig ah u fur liiska digida Twinkle ee bogga wada-hadalka isticmaalaha ka dib dib-u-celinta Twinkle', helptip: 'Wuxuu shaqeeyaa kaliya haddii sanduuqa khuseeya la calaamadiyay xagga hoose.', type: 'boolean' }, // TwinkleConfig.openTalkPage (array) // Noocyada falalka ee keenaya in la furo bogga wada-hadalka { name: 'openTalkPage', label: 'Fur bogga wada-hadalka isticmaalaha ka dib noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda' } }, // TwinkleConfig.openTalkPageOnAutoRevert (bool) // Waxay qeexaysaa haddii bogga wada-hadalka la furayo marka laga yeerayo dib-u-celinta tabarucaadka ama isbeddellada dhow. Haddii loo dhigo run, openTalkPage ayaa markaas qeexaysa in bogga wada-hadalka la furayo iyo in kale. { name: 'openTalkPageOnAutoRevert', label: 'Fur bogga wada-hadalka isticmaalaha marka laga yeerayo dib-u-celinta tabarucaadka isticmaalaha ama isbeddellada dhow', helptip: 'Marka tani shidan tahay, xulashooyinka la rabay waa in la hawlgeliyaa qaybtii hore si ay tani u shaqeyso.', type: 'boolean' }, // TwinkleConfig.rollbackInPlace (bool) // { name: 'rollbackInPlace', label: 'Ha dib u soo dejin bogga marka dib looga celinayo tabarucaadka ama isbeddellada dhow', helptip: 'Marka tani shidan tahay, Twinkle dib u soo dejin maayo quudinta tabarucaadka ama isbeddellada dhow ka dib dib u celinta, taasoo kuu oggolaanaysa inaad dib u celiso wax ka badan hal tifatir hal mar.', type: 'boolean' }, // TwinkleConfig.markRevertedPagesAsMinor (array) // Noocyada falalka ee keenaya in tifatirka lagu calaamadiyo mid yar { name: 'markRevertedPagesAsMinor', label: 'Calaamadi sida tifatir yar noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, // TwinkleConfig.watchRevertedPages (array) // Noocyada falalka ee keenaya in lagu daro liiska la socodka si qasab ah { name: 'watchRevertedPages', label: 'Ku dar boggaga liiska la socodka noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, // TwinkleConfig.watchRevertedExpiry // Haddii mid ka mid ah walxaha kore la doorto, in wakhtiga la socodka la dhameeyo iyo in kale { name: 'watchRevertedExpiry', label: 'Marka dib loo celinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.offerReasonOnNormalRevert (boolean) // In la bixiyo codsi sabab kooban oo dheeri ah oo ku saabsan dib-u-celinta caadiga ah, caadi ahaan run ah { name: 'offerReasonOnNormalRevert', label: 'Weydii sababta dib u celinta caadiga ah', helptip: 'Dib u celinta "Caadiga ah" waa kuwa laga yeero xiriirka dhex[rollback].', type: 'boolean' }, { name: 'confirmOnRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (dhammaan qalabka)', helptip: 'Isticmaalayaasha qalabka qoraalka ama taabashada, iyo dadka go\'aan la\'aanta joogtada ah hayso.', type: 'boolean' }, { name: 'confirmOnMobileRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (qalabka gacanta kaliya)', helptip: 'Iska ilaali dib u celinta shilalka ah marka aad joogto qalabka gacanta.', type: 'boolean' }, // TwinkleConfig.showRollbackLinks (array) // Meesha ay tahay in Twinkle uu ka muujiyo xiriiriyeyaasha dib-u-celinta: // diff, others, mine, contribs, history, recent { name: 'showRollbackLinks', label: 'Muuji xiriiriyeyaasha dib-u-celinta boggagani', type: 'set', setValues: { diff: 'Boggaga isbarbardhigga', others: 'Boggaga tabarucaadka ee isticmaaleyaasha kale', mine: 'Bogga tabarucaadkayga', recent: 'Isbeddellada dhow iyo boggaga gaarka ah ee la xiriira', history: 'Boggaga taariikhda' } } ] }, { title: 'Tirtiridda degdegga ah (CSD)', module: 'speedy', preferences: [ { name: 'speedySelectionStyle', label: 'Goorta la sii wado oo la calaamadiyo/tirtiro bogga', type: 'enum', enumValues: { buttonClick: 'Marka aan gujiyo "Gudbi"', radioClick: 'Isla marka aan gujiyo ikhtiyaar' } }, // TwinkleConfig.watchSpeedyPages (array) // Haddii lagu darayo boggaga degdegga ah ee la calaamadiyay ama la tirtiray liiska la socodka { name: 'watchSpeedyPages', label: 'Ku dar bogga liiska la socodka marka la isticmaalayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdCriteria, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder }, // TwinkleConfig.watchSpeedyExpiry // Haddii mid ka mid ah walxaha kore la doorto, in wakhtiga la socodka la dhameeyo iyo in kale { name: 'watchSpeedyExpiry', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.markSpeedyPagesAsPatrolled (boolean) // Haddii, marka la dabaqayo qaabka degdegga ah bogga, in bogga lagu calaamadiyo mid la eegay/la kormeeraay (haddii bogga laga gaaray NewPages) { name: 'markSpeedyPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, // TwinkleConfig.watchSpeedyUser (string) // Dejinta liiska la socodka ee bogga wada-hadalka isticmaalaha haddii ay helaan ogeysiis. { name: 'watchSpeedyUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings) // Noocyada ogeysiisyada tirtiridda degdegga ah ee ay tahay in isticmaalaha lagu soo dhoweeyo // ogeysiis "firstarticle" ah haddii boggiisa wada-hadalku uusan weli la abuurin. { name: 'welcomeUserOnSpeedyDeletionNotification', label: 'Soo dhawee abuuraha bogga marka lagu ogeysiinayo shuruudahan', helptip: 'Soo dhaweynta waxaa la bixiyaa kaliya haddii isticmaalaha lagaga ogeysiiyo tirtiridda, iyo kaliya haddii boggiisa wada-hadalku uusan weli jirin. Qaabka la isticmaalo waa {{firstarticle}}.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array) // Noocyada falalka ee keenaya in qoraaga bogga la ogeysiiyo magacaabista { name: 'notifyUserOnSpeedyDeletionNomination', label: 'Ogeysii abuuraha bogga marka lagu calaamadinayo shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.warnUserOnSpeedyDelete (array) // Noocyada falalka ee keenaya in qoraaga bogga la ogeysiiyo tirtiridda degdegga ah (maamulaha kaliya) { name: 'warnUserOnSpeedyDelete', label: 'Ogeysii abuuraha bogga marka la tirtirayo hoos shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.promptForSpeedyDeletionSummary (array of strings) { name: 'promptForSpeedyDeletionSummary', label: 'U oggolow tafatirka kooban-tafsirka tirtiridda marka la tirtirayo hoos shuruudahan', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder }, // TwinkleConfig.deleteTalkPageOnDelete (boolean) // Haddii bogga wada-hadalka haddii uu jiro sidoo kale la tirtirayo (CSD G8) marka la tirtirayo bog (maamulaha kaliya) { name: 'deleteTalkPageOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir bogga wada-hadalka" si caadi ah', adminOnly: true, type: 'boolean' }, { name: 'deleteRedirectsOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir dib-u-jeeddada" si caadi ah', adminOnly: true, type: 'boolean' }, // TwinkleConfig.deleteSysopDefaultToDelete (boolean) // Ka dhig shaashadda CSD mid si caadi ah u doorata "tirtir" halkii ay ka noqon lahayd "calaamadi" (maamulaha kaliya) { name: 'deleteSysopDefaultToDelete', label: 'Ka dhig shaashadda CSD mid si caadi ah ugu tagta "tirtir" halkii ay ka noqon lahayd "calaamadi"', helptip: 'Haddii ay jirto calaamad CSD oo horay u joogta, Twinkle wuxuu mar walba si caadi ah ugu noqon doonaa habka "tirtir"', adminOnly: true, type: 'boolean' }, // TwinkleConfig.speedyWindowWidth (integer) // Waxay qeexaysaa ballaca daaqadda Twinkle SD ee pixels { name: 'speedyWindowWidth', label: 'Ballaca daaqadda tirtiridda degdegga ah (pixels)', type: 'integer' }, // TwinkleConfig.speedyWindowWidth (integer) // Waxay qeexaysaa ballaca daaqadda Twinkle SD ee pixels { name: 'speedyWindowHeight', label: 'Dhererka daaqadda tirtiridda degdegga ah (pixels)', helptip: 'Haddii aad leedahay kantarool weyn, waxaad jeclaan kartaa inaad kordhiso tan.', type: 'integer' }, { name: 'logSpeedyNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan magacaabista CSD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto CSD adigoo isticmaalaya Twinkle. Faylasha lagu calaamadiyay DI sidoo kale waa la daraa diiwaankan.', type: 'boolean' }, { name: 'speedyLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee CSD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga CSD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee CSD.', type: 'string' }, { name: 'noLogOnSpeedyNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka lagu calaamadinayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder } ] }, { title: 'Calaamadi', module: 'tag', preferences: [ { name: 'watchTaggedVenues', label: 'Ku dar bogga liiska la socodka marka la calaamadinayo noocyadan boggaga ah', type: 'set', setValues: { articles: 'Maqaallo', drafts: 'Qabyo', redirects: 'Dib-u-jeediyo', files: 'Faylal' } }, { name: 'watchTaggedPages', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchMergeDiscussions', label: 'Ku dar boggaga wada-hadalka liiska la socodka marka la bilaabayo doodaha mideynta', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markTaggedPagesAsMinor', label: 'Calaamadi ku darista calaamadaha sida tifatir yar', type: 'boolean' }, { name: 'markTaggedPagesAsPatrolled', label: 'Calaamadi sanduuqa "calaamadi bogga mid la eegay" si caadi ah', type: 'boolean' }, { name: 'tagArticleSortOrder', label: 'Habka aragtida caadiga ah ee calaamadaha maqaalka', type: 'enum', enumValues: { cat: 'Qaybaha', alpha: 'Hab xarfaha ah' } }, { name: 'customTagList', label: 'Calaamadaha dayactirka maqaalka/qabyada gaarka ah ee la soo bandhigayo', helptip: 'Kuwani waxay u muuqdaan ikhtiyaarro dheeraad ah oo hoos yimaada liiska calaamadaha. Tusaale ahaan, waxaad ku dari kartaa calaamado dayactir oo cusub oo aan weli lagu darin kuwa caadiga ah ee Twinkle.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customFileTagList', label: 'Calaamadaha dayactirka faylka gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto faylasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customRedirectTagList', label: 'Calaamadaha qaybta dib-u-jeeddada gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto dib-u-jeediyeyaasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' } ] }, { title: 'Talkback', module: 'talkback', preferences: [ { name: 'markTalkbackAsMinor', label: 'Calaamadi talkbacks sida tifatir yar', type: 'boolean' }, { name: 'insertTalkbackSignature', label: 'Geli saxiixa gudaheeda talkbacks', type: 'boolean' }, { name: 'talkbackHeading', label: 'Madaxa qaybta ee loo isticmaalo talkback iyo fadlan eeg', tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' }, { name: 'mailHeading', label: 'Madaxa qaybta ee loo isticmaalo ogeysiisyada "waxaad haysataa iimeyl"', tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' } ] }, { title: 'Ka goy xiriirinta', module: 'unlink', preferences: [ // TwinkleConfig.unlinkNamespaces (array) // Meelaha magaca ee ay tahay in xiriirinta laga saaro, caadi ahaan 0 (maqaal), 10 (qaab), 100 (bogga hordhaca ah), iyo 118 (qabyo) { name: 'unlinkNamespaces', label: 'Ka saar xiriirinta boggaga ku jira meelahan magaca', helptip: 'Ka fogow doorashada meelaha magaca wada-hadalka, maaddaama Twinkle uu ku dambayn karo inuu ka saaro xiriirinta keydadka wada-hadalka (arrin weyn oo khaldan).', type: 'set', setValues: Twinkle.config.commonSets.namespacesNoSpecial } ] }, { title: 'Dii isticmaalaha', module: 'warn', preferences: [ // TwinkleConfig.defaultWarningGroup (int) // Heerka digida ee ay tahay inuu noqdo kooxda la doortay ee caadiga ah, caadi ahaan waa 1 { name: 'defaultWarningGroup', label: 'Heerka digida caadiga ah', type: 'enum', enumValues: { 1: 'Heerka 1', 2: 'Heerka 2', 3: 'Heerka 3', 4: 'Heerka 4', 5: 'Heerka 4im', 6: 'Ogeysiisyada hal arrin ah', 7: 'Digidaha hal arrin ah', 9: 'Digidaha gaarka ah', 10: 'Dhammaan qaababka digida', 11: 'Heerka is-doorta (1-4)' } }, // TwinkleConfig.combinedSingletMenus (boolean) // haddii ay run tahay, muuji hal liis oo wata ogeysiisyada hal arrin ah iyo digidaha halkii ay ka noqon lahaayeen laba si gooni ah { name: 'combinedSingletMenus', label: 'Ku beddel labada liis ee hal arrin ah hal liis oo la mideeyay', helptip: 'Doorashada ogeysiisyada hal arrin ah ama digidaha hal arrin ah sida heerkaaga caadiga ah waxay ka dhigi doontaa tan mid caadi ah haddii la hawlgeliyo.', type: 'boolean' }, // TwinkleConfig.watchWarnings (string) // Dejinta liiska la socodka ee bogga loo diray digid ama ogeysiis { name: 'watchWarnings', label: 'Ku dar bogga wada-hadalka isticmaalaha liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.oldSelect (boolean) // haddii ay run tahay, isticmaal liiska xulashada dhaladka ah halkii aad ka isticmaali lahayd midka ku saleysan select2 { name: 'oldSelect', label: 'Isticmaal liiska xulashada caadiga ah ee aan la raadin karin', type: 'boolean' }, { name: 'customWarningList', label: 'Qaababka digida gaarka ah ee la soo bandhigayo', helptip: 'Waxaad ku dari kartaa qaabab shakhsi ah ama hoos-boggaga isticmaalaha. Digidaha gaarka ah waxay ka muuqdaan qaybta "Digidaha gaarka ah" ee ku dhex jirta sanduuqa wada-sheekaysiga digida.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo liiska digida (sidoo kale loo isticmaalo kooban-tafsirka tifatirka)' } ] }, { title: 'Soo dhawee isticmaalaha', module: 'welcome', preferences: [ { name: 'topWelcomes', label: 'Dhig soo-dhaweynta kor1 nuxurka jira ee boggaga wada-hadalka isticmaalaha', type: 'boolean' }, { name: 'watchWelcomes', label: 'Ku dar boggaga wada-hadalka isticmaalaha liiska la socodka marka la soo dhoweynayo', helptip: 'Tani waxay ku daraysaa qaybta shakhsiga ah ee soo-dhaweynta isticmaalaha - waxaad awoodi doontaa inaad aragto sida ay ula qabsanayaan iyagoo ah cusub, oo laga yaabo inaad caawiso.', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'insertUsername', label: 'Ku dar magacaaga isticmaale qaabka (haddii ay khuseyso)', helptip: 'Qaababyada qaarkood ee soo-dhaweynta waxay leeyihiin jumlad furitaan ah sida "Hallo, waxaan ahay &lt;username&gt;. Soo dhawoow" iwm. Haddii aad demiso ikhtiyaarkan, qaababkani ma soo bandhigi doonaan magacaaga isticmaale habkaas.', type: 'boolean' }, { name: 'quickWelcomeMode', label: 'Gujinta xiriiriyaha "soo dhawoow" ee bogga isbarbardhigga (kaas oo ka muuqda kaliya haddii bogga wada-hadalka isticmaalaha ee tifatiraha uusan weli la abuurin) wuxuu doonayaa inuu', helptip: 'Haddii aad doorato inaad soo dhoweyso si otomaatig ah, qaabka aad hoos ku cayimay ayaa la isticmaali doonaa.', type: 'enum', enumValues: { auto: 'isla markiiba soo dhig qaabka soo-dhaweynta ee hoos ku xusan', norm: 'kuu sheeg inaad doorato qaab' } }, { name: 'quickWelcomeTemplate', label: 'Qaabka la isticmaali doono marka si otomaatig ah loo soo dhoweynayo', helptip: 'Geli magaca qaabka soo-dhaweynta, adigoon lahayn qawsafyo. Xiriiriye ku socda maqaalka la bixiyay ayaa lagu dari doonaa.', type: 'string' }, { name: 'customWelcomeList', label: 'Qaababka soo-dhaweynta gaarka ah ee la soo bandhigayo', helptip: 'Waxaad ku dari kartaa qaabab kale oo soo-dhaweyn ah, ama hoos-boggaga isticmaalaha ee ah qaababka soo-dhaweynta (oo leh hor-odhiga "User:"). Ha iloobin in qaababarkan la beddelo oo la geliyo boggaga wada-hadalka isticmaalaha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga soo-dhaweynta' }, { name: 'customWelcomeSignature', label: 'Si otomaatig ah u saxiix qaababka soo-dhaweynta gaarka ah', helptip: 'Haddii qaababkaaga soo-dhaweynta gaarka ah ay ka kooban yihiin saxiix ku dhex jira qaabka gudihiisa, demi ikhtiyaarkan.', type: 'boolean' } ] }, { title: 'XFD (doodaha tirtiridda)', module: 'xfd', preferences: [ { name: 'logXfdNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u magacaabto dood tirtirid (XfD)', helptip: 'Diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto XfD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'xfdLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee doodda tirtiridda hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga XfD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee XfD.', type: 'string' }, { name: 'noLogOnXfdNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka aad ku magacaabeyso goobtan', type: 'set', setValues: { afd: 'AfD', tfd: 'TfD', ffd: 'FfD', cfd: 'CfD', cfds: 'CfD/S', mfd: 'MfD', rfd: 'RfD', rm: 'RM' } }, // TwinkleConfig.xfdWatchPage (string) // Dejinta liiska la socodka ee bogga loo magacaabayo XfD. { name: 'xfdWatchPage', label: 'Ku dar bogga la magacaabay liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchDiscussion (string) // Dejinta liiska la socodka ee bogga XfD ee äla sameeyay (ee loogu talagalay habraacyadaas abuuraya boggaga doodda magacaabis kasta), // ama bogga liiska ee habraacyada kale. { name: 'xfdWatchDiscussion', label: 'Ku dar bogga doodda tirtiridda liiska la socodka', helptip: 'Tani waxay tilmaamaysaa hoos-bogga doodda (ee AfD iyo MfD) ama bogga diiwaanka maalinlaha ah (ee TfD, CfD, RfD iyo FfD)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchList (string) // Dejinta liiska la socodka ee bogga liiska XfD, *haddii* dooddu ay ku taal bog gooni ah. { name: 'xfdWatchList', label: 'Ku dar bogga diiwaanka/liiska maalinlaha ah liiska la socodka (AfD iyo MfD)', helptip: 'Tani waxay khuseysaa oo kaliya AfD iyo MfD, halkaas oo doodaha lagu dhex daro bogga diiwaanka maalinlaha ah (ee AfD) ama bogga weyn ee MfD (ee MfD).', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchUser (string) // Dejinta liiska la socodka ee bogga wada-hadalka isticmaalaha haddii ay helaan ogeysiis. { name: 'xfdWatchUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchRelated (string) // Dejinta liiska la socodka ee bartilmaameedka dib-u-jeeddada loo magacaabayo RfD. { name: 'xfdWatchRelated', label: 'Ku dar bogga bartilmaameedka ee dib-u-jeeddada la magacaabay liiska la socodka (marka la ogeysiinayo)', helptip: 'Tani waxay khuseysaa oo kaliya RfD, marka la reebayo ogeysiis ku yaal bogga wada-hadalka ee bartilmaameedka dib-u-jeeddada', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markXfdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka loo magacaabayo AFD (haddii ay suurtagal tahay)', type: 'boolean' } ] }, { title: 'Qarsan', hidden: true, preferences: [ // twinklerollback.js: waxay qeexaysaa inta dib-u-eegis ee la waydiinayo ugu badnaan, ugu badnaanta suurtagalka ah waa 50, caadi ahaan waa 50 { name: 'revertMaxRevisions', type: 'integer' }, // twinklewarn.js: Marka la isticmaalayo ikhtiyaarka xulashada heerka otomaatiga ah, immisa maalmood ayaa ka dhigaya digid horay u dhacday mid duugowday { name: 'autolevelStaleDays', type: 'integer' }, // Immisa bog ayaa ay tahay in la waydiiyo deprod iyo batchdelete/protect/undelete { name: 'batchMax', type: 'integer', adminOnly: true }, // Immisa bog ayaa ay tahay in hal mar la farsameeyo deprod iyo batchdelete/protect/undelete { name: 'batchChunks', type: 'integer', adminOnly: true } ] } ]; // dhammaadka Twinkle.config.sections Twinkle.config.init = function twinkleconfigInit() { // abuur bogga habaynta ee Wikipedia:Twinkle/Preferences if ((mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').project && mw.config.get('wgTitle') === 'Twinkle/Preferences') && mw.config.get('wgAction') === 'view') { if (!document.getElementById('twinkle-config')) { return; // malaha bogga waa mid si khaldan loo habeeyay, ama wax kale - laakiin isku day kasta oo lagu beddelayo wuxuu noqon doonaa mid aan micno lahayn } // u deji qaabka waxba si looga hortago khilaaf ka imaanaya CSS-ka dibadda document.getElementById('twinkle-config').removeAttribute('style'); document.getElementById('twinkle-config-titlebar').removeAttribute('style'); const contentdiv = document.getElementById('twinkle-config-content'); contentdiv.textContent = ''; // tirtir carruurta // u ogolaow isticmaalaha inuu ogaado khilaafka suurtagalka ah ee skin js/common.js file if (window.TwinkleConfig || window.FriendlyConfig) { const contentnotice = document.createElement('div'); contentnotice.className = 'plainlinks twinkle-ombox'; contentnotice.innerHTML = '<div>' + '<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/3/38/Imbox_content.png" />' + '</div>' + '<div>' + '<p><big><b>Ka hor inta aadan beddelin habayntaada halkan,</b> waa inaad ka saartaa habayntaadii hore ee Twinkle iyo Friendly JavaScript-ka maqaarkaaga shakhsiga ah.</big></p>' + '<p>Si aad tan u samayso, waxaad <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/' + mw.config.get('skin') + '.js', { action: 'edit' }) + '" target="_blank"><b>tifatiri kartaa faylka javascript maqaarkaaga shakhsiga ah</b></a> ama <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/common.js', { action: 'edit'}) + '" target="_blank"><b>faylkaaga common.js</b></a>, adigoo ka saaraya dhammaan xarumaha koodka ee tixraacaya <code>TwinkleConfig</code> iyo <code>FriendlyConfig</code>.</p>' + '</div>'; contentdiv.appendChild(contentnotice); } // bilow miiska tusmada const toctable = document.createElement('div'); toctable.className = 'toc'; toctable.style.marginLeft = '0.4em'; // abuur cinwaanka TOC const toctitle = document.createElement('div'); toctitle.id = 'toctitle'; const toch2 = document.createElement('h2'); toch2.textContent = 'Muxuu ka kooban yahay '; toctitle.appendChild(toch2); // ku dar xiriiriyaha tusmada muuji/qari const toctoggle = document.createElement('span'); toctoggle.className = 'toctoggle'; toctoggle.appendChild(document.createTextNode('[')); const toctogglelink = document.createElement('a'); toctogglelink.className = 'internal'; toctogglelink.setAttribute('href', '#tw-tocshowhide'); toctogglelink.textContent = 'qari'; toctoggle.appendChild(toctogglelink); toctoggle.appendChild(document.createTextNode(']')); toctitle.appendChild(toctoggle); toctable.appendChild(toctitle); // abuur weelka shayga: tani waa waxa aan ku darno waxyaabaha const tocul = document.createElement('ul'); toctogglelink.addEventListener('click', () => { const $tocul = $(tocul); $tocul.toggle(); if ($tocul.find(':visible').length) { toctogglelink.textContent = 'qari'; } else { toctogglelink.textContent = 'muuji'; } }, false); toctable.appendChild(tocul); contentdiv.appendChild(toctable); const contentform = document.createElement('form'); contentform.setAttribute('action', 'javascript:void(0)'); // waxay ahayd #tw-save - waxaa loo beddelay void(0) si looga shaqeeyo arrinta Chrome contentform.addEventListener('submit', Twinkle.config.save, true); contentdiv.appendChild(contentform); const container = document.createElement('table'); container.style.width = '100%'; contentform.appendChild(container); $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; // macnaheedu waa "sii wad" xaaladdan } // ku dar TOC const tocli = document.createElement('li'); tocli.className = 'toclevel-1'; const toca = document.createElement('a'); toca.setAttribute('href', '#' + section.module); toca.appendChild(document.createTextNode(section.title)); tocli.appendChild(toca); tocul.appendChild(tocli); let row = document.createElement('tr'); let cell = document.createElement('td'); cell.setAttribute('colspan', '3'); const heading = document.createElement('h4'); heading.style.borderBottom = '1px solid gray'; heading.style.marginTop = '0.2em'; heading.id = section.module; heading.appendChild(document.createTextNode(section.title)); cell.appendChild(heading); row.appendChild(cell); container.appendChild(row); let rowcount = 1; // ee qaabaynta safafka // ku dar mid kasta oo ka mid ah doorbidyada foomka $(section.preferences).each((prefkey, pref) => { if (pref.adminOnly && !Morebits.userIsSysop) { return true; // macnaheedu waa "sii wad" xaaladdan } row = document.createElement('tr'); row.style.marginBottom = '0.2em'; // abuur qaabka safafka kala duwan if (rowcount++ % 2 === 0) { row.style.backgroundColor = 'rgba(128, 128, 128, 0.1)'; } cell = document.createElement('td'); let label, input; const gotPref = Twinkle.getPref(pref.name); switch (pref.type) { case 'boolean': // abuur sanduuq calaamadeed cell.setAttribute('colspan', '2'); label = document.createElement('label'); input = document.createElement('input'); input.setAttribute('type', 'checkbox'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (gotPref === true) { input.setAttribute('checked', 'checked'); } label.appendChild(input); label.appendChild(document.createTextNode(pref.label)); cell.appendChild(label); break; case 'string': // abuur sanduuq gelin ah case 'integer': // ku dar sumadda tiirka koowaad cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar sanduuqa gelinta tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('input'); input.setAttribute('type', 'text'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (pref.type === 'integer') { input.setAttribute('size', 6); input.setAttribute('type', 'number'); input.setAttribute('step', '1'); // lambarka buuxa oo keliya } if (gotPref) { input.setAttribute('value', gotPref); } cell.appendChild(input); break; case 'enum': // abuur sanduuq isku-dhafan // ku dar sumadda tiirka koowaad cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar sanduuqa gelinta tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('select'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); $.each(pref.enumValues, (enumvalue, enumdisplay) => { const option = document.createElement('option'); option.setAttribute('value', enumvalue); if ((gotPref === enumvalue) || // Khadka loogu beddelayo doorbidyada hore ee boolean watchlist // oo loo beddelayo enums u dhigma (typeof gotPref === 'boolean' && ((gotPref && enumvalue === 'yes') || (!gotPref && enumvalue === 'no')))) { option.setAttribute('selected', 'selected'); } option.appendChild(document.createTextNode(enumdisplay)); input.appendChild(option); }); cell.appendChild(input); break; case 'set': // abuur sanduuqyo calaamadeed oo kala duwan // ku dar sumadda marka hore cell.setAttribute('colspan', '2'); label = document.createElement('label'); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); var checkdiv = document.createElement('div'); checkdiv.style.paddingLeft = '1em'; var worker = function(itemkey, itemvalue) { const checklabel = document.createElement('label'); checklabel.style.marginRight = '0.7em'; checklabel.style.display = 'inline-block'; const check = document.createElement('input'); check.setAttribute('type', 'checkbox'); check.setAttribute('id', pref.name + '_' + itemkey); check.setAttribute('name', pref.name + '_' + itemkey); if (gotPref && gotPref.includes(itemkey)) { check.setAttribute('checked', 'checked'); } if (pref.name === 'unlinkNamespaces') { if (gotPref && gotPref.includes(parseInt(itemkey, 10))) { check.setAttribute('checked', 'checked'); } } checklabel.appendChild(check); checklabel.appendChild(document.createTextNode(itemvalue)); checkdiv.appendChild(checklabel); }; if (pref.setDisplayOrder) { // ku dar sanduuqyada calaamadeed iyadoo la raacayo habka la bixiyay $.each(pref.setDisplayOrder, (itemkey, item) => { worker(item, pref.setValues[item]); }); } else { // ku dar sanduuqyada calaamadeed iyadoo la raacayo habka naloo soo geliyay $.each(pref.setValues, worker); } cell.appendChild(checkdiv); break; case 'customList': // ku dar sumadda tiirka koowaad cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar badhanka tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; var button = document.createElement('button'); button.setAttribute('id', pref.name); button.setAttribute('name', pref.name); button.setAttribute('type', 'button'); button.addEventListener('click', Twinkle.config.listDialog.display, false); // isticmaal xogta jQuery ee badhanka si aad u kaydiso qiimaha habaynta ee hadda $(button).data({ value: gotPref, pref: pref }); button.appendChild(document.createTextNode('Wax ka beddel walxaha')); cell.appendChild(button); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } row.appendChild(cell); // ku dar tilmaamaha caawimaadda cell = document.createElement('td'); cell.className = 'twinkle-config-helptip'; if (pref.helptip) { // u beddel xiriiriyeya la gujin karo xusidda qaababka ee ku jira tilmaamaha caawimaadda cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g, '{{<a href="' + mw.util.getUrl('Template:') + '$1" target="_blank">$1</a>}}'); } // ku dar xiriiriyaha dib-u-dejinta if (pref.type !== 'customList') { const resetlink = document.createElement('a'); resetlink.setAttribute('href', '#tw-reset'); resetlink.setAttribute('id', 'twinkle-config-reset-' + pref.name); resetlink.addEventListener('click', Twinkle.config.resetPrefLink, false); resetlink.style.cssFloat = 'right'; resetlink.style.margin = '0 0.6em'; resetlink.appendChild(document.createTextNode('Dib u deji')); cell.appendChild(resetlink); } row.appendChild(cell); container.appendChild(row); return true; }); return true; }); const footerbox = document.createElement('div'); footerbox.setAttribute('id', 'twinkle-config-buttonpane'); const button = document.createElement('button'); button.setAttribute('id', 'twinkle-config-submit'); button.setAttribute('type', 'submit'); button.appendChild(document.createTextNode('Kaydi isbeddellada')); footerbox.appendChild(button); const footerspan = document.createElement('span'); footerspan.className = 'plainlinks'; footerspan.style.marginLeft = '2.4em'; footerspan.style.fontSize = '90%'; const footera = document.createElement('a'); footera.setAttribute('href', '#tw-reset-all'); footera.setAttribute('id', 'twinkle-config-resetall'); footera.addEventListener('click', Twinkle.config.resetAllPrefs, false); footera.appendChild(document.createTextNode('Soo celi waxyaabaha caadiga ah')); footerspan.appendChild(footera); footerbox.appendChild(footerspan); contentform.appendChild(footerbox); // maaddaama dhammaan cinwaannada cutubyada ay jiraan hadda, waxaan isku dayi karnaa inaan tagno barroosinka la codsaday if (window.location.hash) { const loc = window.location.hash; window.location.hash = ''; window.location.hash = loc; } } else if (mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user && mw.config.get('wgTitle').indexOf(mw.config.get('wgUserName')) === 0 && mw.config.get('wgPageName').slice(-3) === '.js') { const box = document.createElement('div'); box.setAttribute('id', 'twinkle-config-headerbox'); let link; const scriptPageName = mw.config.get('wgPageName').slice( mw.config.get('wgPageName').lastIndexOf('/') + 1, mw.config.get('wgPageName').lastIndexOf('.js') ); if (scriptPageName === 'twinkleoptions') { box.setAttribute('class', 'config-twopt-box'); if (mw.config.get('wgArticleId') > 0) { box.appendChild(document.createTextNode('Boggani wuxuu ka kooban yahay doorbidyadaada Twinkle. Waxaad ku beddeli kartaa adigoo isticmaalaya ')); } else { box.appendChild(document.createTextNode('Waxaad habayn kartaa Twinkle si uu ugu habboonaado doorbidyadaada adigoo isticmaalaya ')); } link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode(', ama adigoo tifatiraya boggan.')); $(box).insertAfter($('#contentSub')); } else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].includes(scriptPageName)) { box.setAttribute('class', 'config-userskin-box'); box.appendChild(document.createTextNode('Haddii aad rabto inaad dejiso doorbidyada Twinkle, waxaad isticmaali kartaa ')); link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode('.')); $(box).insertAfter($('#contentSub')); } } }; // alaabta la xiriirta liiska gaarka ah Twinkle.config.listDialog = {}; Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow($dlgtable, value, label) { let $contenttr, $valueInput, $labelInput; $dlgtable.append( $contenttr = $('<tr>').append( $('<td>').append( $('<button>') .attr('type', 'button') .on('click', () => { $contenttr.remove(); }) .text('Tirtir') ), $('<td>').append( $valueInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-value') .css('width', '97%') ), $('<td>').append( $labelInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-label') .css('width', '98%') ) ) ); if (value) { $valueInput.val(value); } if (label) { $labelInput.val(label); } }; Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) { const $prefbutton = $(e.target); const curvalue = $prefbutton.data('value'); const curpref = $prefbutton.data('pref'); const dialog = new Morebits.SimpleWindow(720, 400); dialog.setTitle(curpref.label); dialog.setScriptName('Doorbidyada Twinkle'); let $dlgtbody; dialog.setContent( $('<div>').append( $('<table>') .addClass('wikitable') .css({ margin: '1.4em 1em', width: 'auto' }) .append( $dlgtbody = $('<tbody>').append( $('<tr>').append( $('<th>') .css('width', '5%'), $('<th>') .css('width', '35%') .text(curpref.customListValueTitle ? curpref.customListValueTitle : 'Qiimaha'), $('<th>') .css('width', '60%') .text(curpref.customListLabelTitle ? curpref.customListLabelTitle : 'Calaamadda') ) ), $('<tfoot>').append( $('<tr>').append( $('<td>') .attr('colspan', '3') .append( $('<button>') .text('Ku dar') .css('min-width', '8em') .attr('type', 'button') .on('click', () => { Twinkle.config.listDialog.addRow($dlgtbody); }) ) ) ) ), $('<button>') .text('Kaydi isbeddellada') .attr('type', 'submit') .on('click', () => { Twinkle.config.listDialog.save($prefbutton, $dlgtbody); dialog.close(); }), $('<button>') .text('Dib u deji') .attr('type', 'submit') .on('click', () => { Twinkle.config.listDialog.reset($prefbutton, $dlgtbody); }), $('<button>') .text('Jooji') .attr('type', 'submit') .on('click', () => { dialog.close(); }) )[0] ); let gotRow = false; $.each(curvalue, (k, v) => { gotRow = true; Twinkle.config.listDialog.addRow($dlgtbody, v.value, v.label); }); if (!gotRow) { Twinkle.config.listDialog.addRow($dlgtbody); } dialog.display(); }; Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset($button, $tbody) { const curpref = $button.data('pref'); const oldvalue = $button.data('value'); Twinkle.config.resetPref(curpref); $tbody.find('tr').slice(1).remove(); const curvalue = $button.data('value'); $.each(curvalue, (k, v) => { Twinkle.config.listDialog.addRow($tbody, v.value, v.label); }); $button.data('value', oldvalue); }; Twinkle.config.listDialog.save = function twinkleconfigListDialogSave($button, $tbody) { const result = []; let current = {}; $tbody.find('input[type="text"]').each((inputkey, input) => { if ($(input).hasClass('twinkle-config-customlist-value')) { current = { value: input.value }; } else { current.label = input.value; if (current.value || current.label) { result.push(current); } } }); $button.data('value', result); }; Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) { const wantedpref = e.target.id.slice(21); $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; } let foundit = false; $(section.preferences).each((prefkey, pref) => { if (pref.name !== wantedpref) { return true; } Twinkle.config.resetPref(pref); foundit = true; return false; }); if (foundit) { return false; } }); return false; }; Twinkle.config.resetPref = function twinkleconfigResetPref(pref) { switch (pref.type) { case 'boolean': document.getElementById(pref.name).checked = Twinkle.defaultConfig[pref.name]; break; case 'string': case 'integer': case 'enum': document.getElementById(pref.name).value = Twinkle.defaultConfig[pref.name]; break; case 'set': $.each(pref.setValues, (itemkey) => { if (document.getElementById(pref.name + '_' + itemkey)) { document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].includes(itemkey); } }); break; case 'customList': $(document.getElementById(pref.name)).data('value', Twinkle.defaultConfig[pref.name]); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } }; Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() { $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; } $(section.preferences).each((prefkey, pref) => { if (!pref.adminOnly || Morebits.userIsSysop) { Twinkle.config.resetPref(pref); } }); return true; }); return false; }; Twinkle.config.save = function twinkleconfigSave(e) { Morebits.Status.init(document.getElementById('twinkle-config-content')); const userjs = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user] + ':' + mw.config.get('wgUserName') + '/twinkleoptions.js'; const wikipediaPage = new Morebits.wiki.Page(userjs, 'Kaydinaya doorbidyada ' + userjs); wikipediaPage.setCallbackParameters(e.target); wikipediaPage.load(Twinkle.config.writePrefs); return false; }; Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) { const form = pageobj.getCallbackParameters(); const newConfig = {optionsVersion: 2.1}; const compare = function(a, b) { if (Array.isArray(a)) { if (a.length !== b.length) { return false; } const asort = a.sort(), bsort = b.sort(); for (let i = 0; asort[i]; ++i) { if ((typeof asort[i] === 'object') && (asort[i].label !== bsort[i].label || asort[i].value !== bsort[i].value)) { return false; } else if (asort[i].toString() !== bsort[i].toString()) { return false; } } return true; } return a === b; }; $(Twinkle.config.sections).each((sectionkey, section) => { if (section.adminOnly && !Morebits.userIsSysop) { return; } $(section.preferences).each((prefkey, pref) => { let userValue; if (!pref.adminOnly || Morebits.userIsSysop) { if (!section.hidden) { switch (pref.type) { case 'boolean': userValue = form[pref.name].checked; break; case 'string': case 'enum': userValue = form[pref.name].value; break; case 'integer': userValue = parseInt(form[pref.name].value, 10); if (isNaN(userValue)) { Morebits.Status.warn('Kaydinaya', 'Qiimaha aad u cayimay ' + pref.name + ' (' + pref.value + ') wuxuu ahaa mid aan shaqaynayn. Kaydintu waa sii socon doontaa, laakiin xogta khaldan waa la dhaafi doonaa.'); userValue = null; } break; case 'set': userValue = []; if (pref.setDisplayOrder) { $.each(pref.setDisplayOrder, (itemkey, item) => { if (form[pref.name + '_' + item].checked) { userValue.push(item); } }); } else { $.each(pref.setValues, (itemkey) => { if (form[pref.name + '_' + itemkey].checked) { userValue.push(itemkey); } }); } break; case 'customList': userValue = $(form[pref.name]).data('value'); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } } else if (Twinkle.prefs) { userValue = Twinkle.prefs[pref.name]; } } if (userValue !== undefined && !compare(userValue, Twinkle.defaultConfig[pref.name])) { newConfig[pref.name] = userValue; } }); }); let text = '// twinkleoptions.js: faylka doorbidyada shakhsiga ah ee Twinkle\n' + '//\n' + '// FIIRO GAAR AH: Habka ugu fudud ee aad ku beddeli karto doorbidyadaada Twinkle waa adigoo isticmaalaya\n' + '// guddiga doorbididda Twinkle, ee [[:' + Morebits.pageNameNorm + ']].\n' + '//\n' + '// Faylkan waxaa la soo saaray SI OTOMAATIG AH. Wixii isbeddel ah ee aad samayso (marka laga reebo\n' + '// beddelidda cabbiraadaha habaynta si JavaScript sax ah u ah) waxaa lagu\n' + '// dul qori doonaa marka xigta ee aad gujiso "kaydi" guddiga doorbididda\n' + '// Twinkle. Haddii aad wax ka beddelayso faylkan, hubi inaad isticmaasho JavaScript sax ah.\n' + '// <no' + 'wiki>\n' + '\n' + 'window.Twinkle.prefs = '; text += JSON.stringify(newConfig, null, 2); text += ';\n' + '\n' + '// </no' + 'wiki>\n' + '// Dhamaadka twinkleoptions.js\n'; pageobj.setPageText(text); pageobj.setEditSummary('Kaydinaya doorbidyada Twinkle: tifatir otomaatig ah oo ka yimid [[:' + Morebits.pageNameNorm + ']]'); pageobj.setChangeTags(Twinkle.changeTags); pageobj.setCreateOption('recreate'); pageobj.save(Twinkle.config.saveSuccess); }; Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) { pageobj.getStatusElement().info('waa lagu guulaystay'); const noticebox = document.createElement('div'); noticebox.className = 'cdx-message cdx-message--success'; noticebox.style.fontSize = '100%'; noticebox.innerHTML = '<p><b>Doorbidyadaada Twinkle waa la kaydiyay.</b> Si aad u aragto isbeddellada, waxaad u baahan doontaa inaad gebi ahaanba nadiifiso kaydka biraawsarkaaga (fiiri <a href="' + mw.util.getUrl('WP:BYPASS') + '" title="WP:BYPASS">WP:BYPASS</a> tilmaamaha).</p>'; mw.loader.using('mediawiki.htmlform.codex.styles', () => { Morebits.Status.root.appendChild(noticebox); }); const noticeclear = document.createElement('br'); noticeclear.style.clear = 'both'; Morebits.Status.root.appendChild(noticeclear); }; Twinkle.addInitCallback(Twinkle.config.init); }()); // </nowiki> 5x6xa2ji586dr7ljpu5t8ekpihzz1xl 311229 311228 2026-10-28T16:33:23Z Isma4l 41797 311229 javascript text/javascript // <nowiki> (function() { /* **************************************** *** twinkleconfig.js: Qaybta doorbidda **************************************** * Qaabka loo yeero: Wuxuu ku darayaa foomka qaab-yaynta Wikipedia:Twinkle/Preferences, wuxuuna ku darayaa sanduuq xayaysiis ah dusha sare ee hoos-boggaga isticmaalaha ee leh isticmaalaha hadda soo galay oo ku dhammaada '.js' * Ka shaqeeya: Waxa aan hadda sayey. Haa. */ Twinkle.config = {}; Twinkle.config.watchlistEnums = { yes: 'Ku dar liiska la socodka (si aan xad lahayn)', no: "Ha ku darin liiska la socodka", default: 'Raac doorbidyada boggaaga', '1 week': 'La soco 1 toddobaad', '1 month': 'La soco 1 bil', '3 months': 'La soco 3 bilood', '6 months': 'La soco 6 bilood' }; Twinkle.config.commonSets = { csdCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f8: 'F8', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, csdCriteriaNotification: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', f1: 'F1', f2: 'F2', f3: 'F3', f7: 'F7', f9: 'F9', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5 ("xadgudubka ciqaabta guud" kaliya)', g6: 'G6 ("guuritaanka koobi-iyo-dheji" kaliya)', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', u6: 'U6', u7: 'U7' }, csdAndImageDeletionCriteria: { db: 'Sababayn gaar ah ({{db}})', a1: 'A1', a2: 'A2', a3: 'A3', a7: 'A7', a9: 'A9', a10: 'A10', a11: 'A11', c1: 'C1', c4: 'C4', f1: 'F1', f2: 'F2', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f11: 'F11', g1: 'G1', g2: 'G2', g3: 'G3', g4: 'G4', g5: 'G5', g6: 'G6', g7: 'G7', g8: 'G8', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', r2: 'R2', r3: 'R3', r4: 'R4', t5: 'T5', u1: 'U1', u2: 'U2', u6: 'U6', u7: 'U7' }, namespacesNoSpecial: { 0: 'Maqaal', 1: 'Wada-hadal (maqaal)', 2: 'Isticmaale', 3: 'Wada-hadalka isticmaalaha', 4: 'Wikipedia', 5: 'Wada-hadalka Wikipedia', 6: 'Fayl', 7: 'Wada-hadalka faylka', 8: 'MediaWiki', 9: 'Wada-hadalka MediaWiki', 10: 'Qaab', 11: 'Wada-hadalka qaabka', 12: 'Caawimaad', 13: 'Wada-hadalka caawimaada', 14: 'Qayb', 15: 'Wada-hadalka qaybta', 100: 'Portal', 101: 'Wada-hadalka portal-ka', 118: 'Qabyo', 119: 'Wada-hadalka qabyada', 710: 'TimedText', 711: 'Wada-hadalka TimedText', 828: 'Module', 829: 'Wada-hadalka module-ka' } }; Twinkle.config.commonSets.csdCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteria); Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder = Object.keys(Twinkle.config.commonSets.csdCriteriaNotification); Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder = Object.keys(Twinkle.config.commonSets.csdAndImageDeletionCriteria); /** * Faahfaahinta qaybaha cutubyada: * * { * title: <magaca cutubka ee la akhrin karo>, * module: <magaca qaybta la xiriirta, ee loo isticmaalo in lagu xiro cutubyada>, * adminOnly: <run ah cutubyada maamulayaasha kaliya>, * hidden: <run ah doorbidyada horumarsan ee naadirka ah in la beddelo - weli waxaa lagu beddeli karaa adigoo si gacanta ah u tifatiraya twinkleoptions.js>, * preferences: [ * { * name: <magaca hantida TwinkleConfig>, * label: <sharaxaad gaaban oo la akhrin karo - oo loo isticmaalo sidii sumad foomka ah>, * helptip: <(ikhtiyaari) qoraal la akhrin karo (oo isticmaalaya HTML sax ah) oo buuxinaya sharaxaadda, sida xadka, digidaha, iwm.> * adminOnly: <run ah doorbidyada maamulayaasha kaliya>, * type: <string|boolean|integer|enum|set|customList> (customList waxay kaydisaa safafka walxaha JSON { value, label }), * enumValues: <nooca = "enum": shay JSON ah halkaas oo furayaashu yihiin magacyada gudaha iyo qiyamku yihiin xargaha la akhrin karo>, * setValues: <nooca = "set": shay JSON ah halkaas oo furayaashu yihiin magacyada gudaha iyo qiyamku yihiin xargaha la akhrin karo>, * setDisplayOrder: <(ikhtiyaari) nooca = "set": xarig ay ku jiraan furayaasha setValues (sida xargaha) habka loo soo bandhigayo>, * customListValueTitle: <nooca = "customList": cinwaanka tiirka bidix "qiimaha" ee tifaftiraha liiska gaarka ah>, * customListLabelTitle: <nooca = "customList": cinwaanka tiirka midig "calaamadda" ee tifaftiraha liiska gaarka ah> * }, * . . . * ] * }, * . . . * */ Twinkle.config.sections = [ { title: 'Guud', module: 'general', preferences: [ // TwinkleConfig.userTalkPageMode waxay qaadan kartaa doodaha: // 'window': fur daaqad cusub, xasuuso daaqadda la furay // 'tab': waxay ku furaysaa tab cusub, haddii ay suurtagal tahay. // 'blank': ku qasbi in lagu furo daaqad cusub, xitaa haddii daaqad sidaas oo kale ah ay jirto { name: 'userTalkPageMode', label: 'Marka la furayo bogga wada-hadalka isticmaalaha, fur', type: 'enum', enumValues: { window: 'Daaqad cusub, adigoo beddelaya wada-hadallada kale ee isticmaalaha', tab: 'Tab cusub', blank: 'Daaqad cusub oo dhammaystiran' } }, // TwinkleConfig.dialogLargeFont (boolean) { name: 'dialogLargeFont', label: 'Isticmaal qoraal ka weyn wada-sheekaysiga Twinkle', type: 'boolean' }, // Twinkle.config.disabledModules (array) { name: 'disabledModules', label: 'Demi qaybaha Twinkle ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', type: 'set', setValues: { arv: 'ARV', warn: 'Dig', welcome: 'Soo dhawoow', talkback: 'Talkback', speedy: 'CSD', prod: 'PROD', xfd: 'XfD', image: 'Fayl (DI)', protect: 'Dhowr (RPP)', tag: 'Calaamadi', diff: 'Isbarbardhig', unlink: 'Ka goy xiriirinta', rollback: 'Rogo iyo dib u celi' } }, // Twinkle.config.disabledSysopModules (array) { name: 'disabledSysopModules', label: 'Demi qaybaha maamulayaasha kaliya ee la doortay', helptip: 'Wax kasta oo aad halkan ka doorato LAGUMA heli doono isticmaaal, markaa si taxaddar leh u soco. Ka saar calaamadda si aad dib ugu hawlgeliso.', adminOnly: true, type: 'set', setValues: { block: 'Xannib', deprod: 'DePROD', batchdelete: 'Tirtiridda wadareed', batchprotect: 'Dhowridda wadareed', batchundelete: 'Soo-celinta wadareed' } } ] }, { title: 'ARV', module: 'arv', preferences: [ { name: 'spiWatchReport', label: 'Ku dar boggaga warbixinta lammaanaha liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Xannib isticmaalaha', module: 'block', adminOnly: true, preferences: [ // TwinkleConfig.defaultToBlock64 (boolean) // Haddii si caadi ah loo xannibayo /64 ama in kale { name: 'defaultToBlock64', label: 'Ciwaannada IPv6, dooro ikhtiyaarka ah in la xannibo xadka /64 si caadi ah', type: 'boolean' }, // TwinkleConfig.defaultToPartialBlocks (boolean) // Whether to default partial blocks on or off { name: 'defaultToPartialBlocks', label: 'Dooro xannibaadaha qayb ahaan si caadi ah marka la furayo liiska xannibaadda', helptip: 'Haddii isticmaalaha horay loo xannibay, tan waa la beddeli doonaa iyadoo la doorbidayo nooca xannibaadda ee hadda', type: 'boolean' }, // TwinkleConfig.blankTalkpageOnIndefBlock (boolean) // if true, blank the talk page when issuing an indef block notice (per [[WP:UWUL#Indefinitely blocked users]]) { name: 'blankTalkpageOnIndefBlock', label: 'Tirtir bogga wada-hadalka marka si aan xad lahayn loo xannibayo isticmaaleyaasha', helptip: 'Fiiri <a href="' + mw.util.getUrl('Wikipedia:WikiProject_User_warnings/Usage_and_layout#Indefinitely_blocked_users') + '">WP:UWUL</a> wixii macluumaad dheeraad ah.', type: 'boolean' } ] }, { title: 'Tirtiridda faylka (DI)', module: 'image', preferences: [ // TwinkleConfig.notifyUserOnDeli (boolean) // If the user should be notified after placing a file deletion tag { name: 'notifyUserOnDeli', label: 'Calaamadi sanduuqa "ogeysii soo geliyaha bilowga ah" si caadi ah', type: 'boolean' }, // TwinkleConfig.deliWatchPage (string) // The watchlist setting of the page tagged for deletion. { name: 'deliWatchPage', label: 'Ku dar bogga faylka liiska la socodka marka la calaamadinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.deliWatchUser (string) // The watchlist setting of the user talk page if a notification is placed. { name: 'deliWatchUser', label: 'Ku dar bogga wada-hadalka ee soo geliyaha bilowga ah liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Dhowridda bogga ' + (Morebits.userIsSysop ? '(PP)' : '(RPP)'), module: 'protect', preferences: [ { name: 'watchRequestedPages', label: 'Ku dar bogga liiska la socodka marka la codsanayo dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchPPTaggedPages', label: 'Ku dar bogga liiska la socodka marka lagu calaamadinayo qaabka dhowridda', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchProtectedPages', label: 'Ku dar bogga liiska la socodka marka la dhowrayo', helptip: 'Haddii sidoo kale bogga la calaamadiyo dhowridda ka dib, doorbiditaankaas ayaa la mudnaansiin doonaa.', adminOnly: true, type: 'enum', enumValues: Twinkle.config.watchlistEnums } ] }, { title: 'Tirtiridda la soo jeediyay (PROD)', module: 'prod', preferences: [ // TwinkleConfig.watchProdPages (string) // Watchlist setting when applying prod template to page { name: 'watchProdPages', label: 'Ku dar maqaalka liiska la socodka marka la calaamadinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.markProdPagesAsPatrolled (boolean) // If, when applying prod template to page, to mark the page as curated/patrolled (if the page was reached from NewPages) { name: 'markProdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, // TwinkleConfig.prodReasonDefault (string) // The prefilled PROD reason. { name: 'prodReasonDefault', label: 'Sababta PROD ee horay loo sii buuxiyay', type: 'string' }, { name: 'logProdPages', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u calaamadiso PROD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u calaamadiso PROD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'prodLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee PROD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga PROD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee PROD.', type: 'string' } ] }, { title: 'Rogo iyo dib u celi', module: 'rollback', preferences: [ // TwinkleConfig.autoMenuAfterRollback (bool) // Option to automatically open the warning menu if the user talk page is opened post-reversion { name: 'autoMenuAfterRollback', label: 'Si otomaatig ah u fur liiska digida Twinkle ee bogga wada-hadalka isticmaalaha ka dib dib-u-celinta Twinkle', helptip: 'Wuxuu shaqeeyaa kaliya haddii sanduuqa khuseeya la calaamadiyay xagga hoose.', type: 'boolean' }, // TwinkleConfig.openTalkPage (array) // What types of actions that should result in opening of talk page { name: 'openTalkPage', label: 'Fur bogga wada-hadalka isticmaalaha ka dib noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda' } }, // TwinkleConfig.openTalkPageOnAutoRevert (bool) // Defines if talk page should be opened when calling revert from contribs or recent changes pages. If set to true, openTalkPage defines then if talk page will be opened. { name: 'openTalkPageOnAutoRevert', label: 'Fur bogga wada-hadalka isticmaalaha marka laga yeerayo dib-u-celinta tabarucaadka isticmaalaha ama isbeddellada dhow', helptip: 'Marka tani shidan tahay, xulashooyinka la rabay waa in la hawlgeliyaa qaybtii hore si ay tani u shaqeyso.', type: 'boolean' }, // TwinkleConfig.rollbackInPlace (bool) // { name: 'rollbackInPlace', label: "Ha dib u soo dejin bogga marka dib looga celinayo tabarucaadka ama isbeddellada dhow", helptip: "Marka tani shidan tahay, Twinkle dib u soo dejin maayo quudinta tabarucaadka ama isbeddellada dhow ka dib dib u celinta, taasoo kuu oggolaanaysa inaad dib u celiso wax ka badan hal tifatir hal mar.", type: 'boolean' }, // TwinkleConfig.markRevertedPagesAsMinor (array) // What types of actions that should result in marking edit as minor { name: 'markRevertedPagesAsMinor', label: 'Calaamadi sida tifatir yar noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, // TwinkleConfig.watchRevertedPages (array) // What types of actions that should result in forced addition to watchlist { name: 'watchRevertedPages', label: 'Ku dar boggaga liiska la socodka noocyadan dib-u-celinta ah', type: 'set', setValues: { agf: 'Dib u celinta AGF', norm: 'Dib u celinta caadiga ah', vand: 'Dib u celinta kharibaadda', torev: '"Soo celi nuqulkan"' } }, // TwinkleConfig.watchRevertedExpiry // If any of the above items are selected, whether to expire the watch { name: 'watchRevertedExpiry', label: 'Marka dib loo celinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.offerReasonOnNormalRevert (boolean) // If to offer a prompt for extra summary reason for normal reverts, default to true { name: 'offerReasonOnNormalRevert', label: 'Weydii sababta dib u celinta caadiga ah', helptip: 'Dib u celinta "Caadiga ah" waa kuwa laga yeero xiriirka dhex[rollback].', type: 'boolean' }, { name: 'confirmOnRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (dhammaan qalabka)', helptip: 'Isticmaalayaasha qalabka qoraalka ama taabashada, iyo dadka go\'aan la\'aanta joogtada ah hayso.', type: 'boolean' }, { name: 'confirmOnMobileRollback', label: 'U baahan xaqiijin ka hor inta aan la dib u celin (qalabka gacanta kaliya)', helptip: 'Iska ilaali dib u celinta shilalka ah marka aad joogto qalabka gacanta.', type: 'boolean' }, // TwinkleConfig.showRollbackLinks (array) // Where Twinkle should show rollback links: // diff, others, mine, contribs, history, recent // Note from TTO: |contribs| seems to be equal to |others| + |mine|, i.e. redundant, so I left it out heres { name: 'showRollbackLinks', label: 'Muuji xiriiriyeyaasha dib-u-celinta boggagani', type: 'set', setValues: { diff: 'Boggaga isbarbardhigga', others: 'Boggaga tabarucaadka ee isticmaaleyaasha kale', mine: 'Bogga tabarucaadkayga', recent: 'Isbeddellada dhow iyo boggaga gaarka ah ee la xiriira', history: 'Boggaga taariikhda' } } ] }, { title: 'Tirtiridda degdegga ah (CSD)', module: 'speedy', preferences: [ { name: 'speedySelectionStyle', label: 'Goorta la sii wado oo la calaamadiyo/tirtiro bogga', type: 'enum', enumValues: { buttonClick: 'Marka aan gujiyo "Gudbi"', radioClick: 'Isla marka aan gujiyo ikhtiyaar' } }, // TwinkleConfig.watchSpeedyPages (array) // Whether to add speedy tagged or deleted pages to watchlist { name: 'watchSpeedyPages', label: 'Ku dar bogga liiska la socodka marka la isticmaalayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdCriteria, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder }, // TwinkleConfig.watchSpeedyExpiry // If any of the above items are selected, whether to expire the watch { name: 'watchSpeedyExpiry', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.markSpeedyPagesAsPatrolled (boolean) // If, when applying speedy template to page, to mark the page as triaged/patrolled (if the page was reached from NewPages) { name: 'markSpeedyPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka la calaamadinayo (haddii ay suurtagal tahay)', helptip: 'Tani waa inaysan u badnayn in la calaamadiyo maadaama ay ka hor imanayso dhaqanka ugu fiican ee la isla gartay', type: 'boolean' }, // TwinkleConfig.watchSpeedyUser (string) // The watchlist setting of the user talk page if they receive a notification. { name: 'watchSpeedyUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings) // On what types of speedy deletion notifications shall the user be welcomed // with a "firstarticle" notice if their talk page has not yet been created. { name: 'welcomeUserOnSpeedyDeletionNotification', label: 'Soo dhawee abuuraha bogga marka lagu ogeysiinayo shuruudahan', helptip: 'Soo dhaweynta waxaa la bixiyaa kaliya haddii isticmaalaha lagaga ogeysiiyo tirtiridda, iyo kaliya haddii boggiisa wada-hadalku uusan weli jirin. Qaabka la isticmaalo waa {{firstarticle}}.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array) // What types of actions should result in the author of the page being notified of nomination { name: 'notifyUserOnSpeedyDeletionNomination', label: 'Ogeysii abuuraha bogga marka lagu calaamadinayo shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.warnUserOnSpeedyDelete (array) // What types of actions should result in the author of the page being notified of speedy deletion (admin only) { name: 'warnUserOnSpeedyDelete', label: 'Ogeysii abuuraha bogga marka la tirtirayo hoos shuruudahan', helptip: 'Xitaa haddii aad doorato inaad ka ogeysiiso shaashadda CSD, ogeysiisku wuxuu dhici doonaa kaliya shuruudahaas laga doortay halkan.', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdCriteriaNotification, setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder }, // TwinkleConfig.promptForSpeedyDeletionSummary (array of strings) { name: 'promptForSpeedyDeletionSummary', label: 'U oggolow tafatirka kooban-tafsirka tirtiridda marka la tirtirayo hoos shuruudahan', adminOnly: true, type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder }, // TwinkleConfig.deleteTalkPageOnDelete (boolean) // If talk page if exists should also be deleted (CSD G8) when spedying a page (admin only) { name: 'deleteTalkPageOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir bogga wada-hadalka" si caadi ah', adminOnly: true, type: 'boolean' }, { name: 'deleteRedirectsOnDelete', label: 'Calaamadi sanduuqa "sidoo kale tirtir dib-u-jeeddada" si caadi ah', adminOnly: true, type: 'boolean' }, // TwinkleConfig.deleteSysopDefaultToDelete (boolean) // Make the CSD screen default to "delete" instead of "tag" (admin only) { name: 'deleteSysopDefaultToDelete', label: 'Ka dhig shaashadda CSD mid si caadi ah ugu tagta "tirtir" halkii ay ka noqon lahayd "calaamadi"', helptip: 'Haddii ay jirto calaamad CSD oo horay u joogta, Twinkle wuxuu mar walba si caadi ah ugu noqon doonaa habka "tirtir"', adminOnly: true, type: 'boolean' }, // TwinkleConfig.speedyWindowWidth (integer) // Defines the width of the Twinkle SD window in pixels { name: 'speedyWindowWidth', label: 'Ballaca daaqadda tirtiridda degdegga ah (pixels)', type: 'integer' }, // TwinkleConfig.speedyWindowWidth (integer) // Defines the width of the Twinkle SD window in pixels { name: 'speedyWindowHeight', label: 'Dhererka daaqadda tirtiridda degdegga ah (pixels)', helptip: 'Haddii aad leedahay kantarool weyn, waxaad jeclaan kartaa inaad kordhiso tan.', type: 'integer' }, { name: 'logSpeedyNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan magacaabista CSD', helptip: 'Maaddaama aanay maamulayaashu lahayn marin ay u helaan tabarucaadooda la tirtiray, diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto CSD adigoo isticmaalaya Twinkle. Faylasha lagu calaamadiyay DI sidoo kale waa la daraa diiwaankan.', type: 'boolean' }, { name: 'speedyLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee CSD hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga CSD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee CSD.', type: 'string' }, { name: 'noLogOnSpeedyNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka lagu calaamadinayo shuruudahan', type: 'set', setValues: Twinkle.config.commonSets.csdAndImageDeletionCriteria, setDisplayOrder: Twinkle.config.commonSets.csdAndImageDeletionCriteriaDisplayOrder } ] }, { title: 'Calaamadi', module: 'tag', preferences: [ { name: 'watchTaggedVenues', label: 'Ku dar bogga liiska la socodka marka la calaamadinayo noocyadan boggaga ah', type: 'set', setValues: { articles: 'Maqaallo', drafts: 'Qabyo', redirects: 'Dib-u-jeediyo', files: 'Faylal' } }, { name: 'watchTaggedPages', label: 'Marka la calaamadinayo bog, muddada la la soconayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'watchMergeDiscussions', label: 'Ku dar boggaga wada-hadalka liiska la socodka marka la bilaabayo doodaha mideynta', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markTaggedPagesAsMinor', label: 'Calaamadi ku darista calaamadaha sida tifatir yar', type: 'boolean' }, { name: 'markTaggedPagesAsPatrolled', label: 'Calaamadi sanduuqa "calaamadi bogga mid la eegay" si caadi ah', type: 'boolean' }, { name: 'tagArticleSortOrder', label: 'Habka aragtida caadiga ah ee calaamadaha maqaalka', type: 'enum', enumValues: { cat: 'Qaybaha', alpha: 'Hab xarfaha ah' } }, { name: 'customTagList', label: 'Calaamadaha dayactirka maqaalka/qabyada gaarka ah ee la soo bandhigayo', helptip: "Kuwani waxay u muuqdaan ikhtiyaarro dheeraad ah oo hoos yimaada liiska calaamadaha. Tusaale ahaan, waxaad ku dari kartaa calaamado dayactir oo cusub oo aan weli lagu darin kuwa caadiga ah ee Twinkle.", type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customFileTagList', label: 'Calaamadaha dayactirka faylka gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto faylasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' }, { name: 'customRedirectTagList', label: 'Calaamadaha qaybta dib-u-jeeddada gaarka ah ee la soo bandhigayo', helptip: 'Calaamado dheeraad ah oo aad rabto inaad ku darto dib-u-jeediyeyaasha.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga calaamadda' } ] }, { title: 'Talkback', module: 'talkback', preferences: [ { name: 'markTalkbackAsMinor', label: 'Calaamadi talkbacks sida tifatir yar', type: 'boolean' }, { name: 'insertTalkbackSignature', label: 'Geli saxiixa gudaheeda talkbacks', type: 'boolean' }, { name: 'talkbackHeading', label: 'Madaxa qaybta ee loo isticmaalo talkback iyo fadlan eeg', tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' }, { name: 'mailHeading', label: "Madaxa qaybta ee loo isticmaalo ogeysiisyada \"waxaad haysataa iimeyl\"", tooltip: 'Waa INAAYSAN ku jirin calaamadaha la midka ah ("==") ee loo isticmaalo qaab-yaynta wikitext', type: 'string' } ] }, { title: 'Ka goy xiriirinta', module: 'unlink', preferences: [ // TwinkleConfig.unlinkNamespaces (array) // In what namespaces unlink should happen, default in 0 (article), 10 (template), 100 (portal), and 118 (draft) { name: 'unlinkNamespaces', label: 'Ka saar xiriirinta boggaga ku jira meelahan magaca', helptip: 'Ka fogow doorashada meelaha magaca wada-hadalka, maaddaama Twinkle uu ku dambayn karo inuu ka saaro xiriirinta keydadka wada-hadalka (arrin weyn oo khaldan).', type: 'set', setValues: Twinkle.config.commonSets.namespacesNoSpecial } ] }, { title: 'Dii isticmaalaha', module: 'warn', preferences: [ // TwinkleConfig.defaultWarningGroup (int) // Which level warning should be the default selected group, default is 1 { name: 'defaultWarningGroup', label: 'Heerka digida caadiga ah', type: 'enum', enumValues: { 1: 'Heerka 1', 2: 'Heerka 2', 3: 'Heerka 3', 4: 'Heerka 4', 5: 'Heerka 4im', 6: 'Ogeysiisyada hal arrin ah', 7: 'Digidaha hal arrin ah', // 8 was used for block templates before #260 9: 'Digidaha gaarka ah', 10: 'Dhammaan qaababka digida', 11: 'Heerka is-doorta (1-4)' } }, // TwinkleConfig.combinedSingletMenus (boolean) // if true, show one menu with both single-issue notices and warnings instead of two separately { name: 'combinedSingletMenus', label: 'Ku beddel labada liis ee hal arrin ah hal liis oo la mideeyay', helptip: 'Doorashada ogeysiisyada hal arrin ah ama digidaha hal arrin ah sida heerkaaga caadiga ah waxay ka dhigi doontaa tan mid caadi ah haddii la hawlgeliyo.', type: 'boolean' }, // TwinkleConfig.watchWarnings (string) // Watchlist setting for the page which has been dispatched an warning or notice { name: 'watchWarnings', label: 'Ku dar bogga wada-hadalka isticmaalaha liiska la socodka marka la ogeysiinayo', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.oldSelect (boolean) // if true, use the native select menu rather the select2-based one { name: 'oldSelect', label: 'Isticmaal liiska xulashada caadiga ah ee aan la raadin karin', type: 'boolean' }, { name: 'customWarningList', label: 'Qaababka digida gaarka ah ee la soo bandhigayo', helptip: 'Waxaad ku dari kartaa qaabab shakhsi ah ama hoos-boggaga isticmaalaha. Digidaha gaarka ah waxay ka muuqdaan qaybta "Digidaha gaarka ah" ee ku dhex jirta sanduuqa wada-sheekaysiga digida.', type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo liiska digida (sidoo kale loo isticmaalo kooban-tafsirka tifatirka)' } ] }, { title: 'Soo dhawee isticmaalaha', module: 'welcome', preferences: [ { name: 'topWelcomes', label: 'Dhig soo-dhaweynta kor nuxurka jira ee boggaga wada-hadalka isticmaalaha', type: 'boolean' }, { name: 'watchWelcomes', label: 'Ku dar boggaga wada-hadalka isticmaalaha liiska la socodka marka la soo dhoweynayo', helptip: 'Tani waxay ku daraysaa qaybta shakhsiga ah ee soo-dhaweynta isticmaalaha - waxaad awoodi doontaa inaad aragto sida ay ula qabsanayaan iyagoo ah cusub, oo laga yaabo inaad caawiso.', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'insertUsername', label: 'Ku dar magacaaga isticmaale qaabka (haddii ay khuseyso)', helptip: "Qaababyada qaarkood ee soo-dhaweynta waxay leeyihiin jumlad furitaan ah sida \"Hallo, waxaan ahay &lt;username&gt;. Soo dhawoow\" iwm. Haddii aad demiso ikhtiyaarkan, qaababkani ma soo bandhigi doonaan magacaaga isticmaale habkaas.", type: 'boolean' }, { name: 'quickWelcomeMode', label: 'Gujinta xiriiriyaha "soo dhawoow" ee bogga isbarbardhigga (kaas oo ka muuqda kaliya haddii bogga wada-hadalka isticmaalaha ee tifatiraha uusan weli la abuurin) wuxuu doonayaa inuu', helptip: 'Haddii aad doorato inaad soo dhoweyso si otomaatig ah, qaabka aad hoos ku cayimay ayaa la isticmaali doonaa.', type: 'enum', enumValues: { auto: 'isla markiiba soo dhig qaabka soo-dhaweynta ee hoos ku xusan', norm: 'kuu sheeg inaad doorato qaab' } }, { name: 'quickWelcomeTemplate', label: 'Qaabka la isticmaali doono marka si otomaatig ah loo soo dhoweynayo', helptip: 'Geli magaca qaabka soo-dhaweynta, adigoon lahayn qawsafyo. Xiriiriye ku socda maqaalka la bixiyay ayaa lagu dari doonaa.', type: 'string' }, { name: 'customWelcomeList', label: 'Qaababka soo-dhaweynta gaarka ah ee la soo bandhigayo', helptip: "Waxaad ku dari kartaa qaabab kale oo soo-dhaweyn ah, ama hoos-boggaga isticmaalaha ee ah qaababka soo-dhaweynta (oo leh hor-odhiga \"User:\"). Ha iloobin in qaababarkan la beddelo oo la geliyo boggaga wada-hadalka isticmaalaha.", type: 'customList', customListValueTitle: 'Magaca qaabka (ma laha qawsafyo)', customListLabelTitle: 'Qoraalka lagu muujinayo wada-sheekaysiga soo-dhaweynta' }, { name: 'customWelcomeSignature', label: 'Si otomaatig ah u saxiix qaababka soo-dhaweynta gaarka ah', helptip: 'Haddii qaababkaaga soo-dhaweynta gaarka ah ay ka kooban yihiin saxiix ku dhex jira qaabka gudihiisa, demi ikhtiyaarkan.', type: 'boolean' } ] }, { title: 'XFD (doodaha tirtiridda)', module: 'xfd', preferences: [ { name: 'logXfdNominations', label: 'Ku hay diiwaan meesha isticmaalaha ee dhammaan boggaga aad u magacaabto dood tirtirid (XfD)', helptip: 'Diiwaanka meesha isticmaalaha wuxuu bixiyaa hab fiican oo lagula socon karo dhammaan boggaga aad u magacaabto XfD adigoo isticmaalaya Twinkle.', type: 'boolean' }, { name: 'xfdLogPageName', label: 'Ku hay diiwaanka meesha isticmaalaha ee doodda tirtiridda hoos-boggan isticmaalaha', helptip: 'Geli magaca hoos-bog sanduuqan. Waxaad ka heli doontaa diiwaankaaga XfD User:<i>username</i>/<i>subpage name</i>. Kaliya wuxuu shaqeeyaa haddii aad shiddo diiwaanka meesha isticmaalaha ee XfD.', type: 'string' }, { name: 'noLogOnXfdNomination', label: 'Ha abuurin gelitaan diiwaanka meesha isticmaalaha marka aad ku magacaabeyso goobtan', type: 'set', setValues: { afd: 'AfD', tfd: 'TfD', ffd: 'FfD', cfd: 'CfD', cfds: 'CfD/S', mfd: 'MfD', rfd: 'RfD', rm: 'RM' } }, // TwinkleConfig.xfdWatchPage (string) // The watchlist setting of the page being nominated for XfD. { name: 'xfdWatchPage', label: 'Ku dar bogga la magacaabay liiska la socodka', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchDiscussion (string) // The watchlist setting of the newly created XfD page (for those processes that create discussion pages for each nomination), // or the list page for the other processes. { name: 'xfdWatchDiscussion', label: 'Ku dar bogga doodda tirtiridda liiska la socodka', helptip: 'Tani waxay tilmaamaysaa hoos-bogga doodda (ee AfD iyo MfD) ama bogga diiwaanka maalinlaha ah (ee TfD, CfD, RfD iyo FfD)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchList (string) // The watchlist setting of the XfD list page, *if* the discussion is on a separate page. { name: 'xfdWatchList', label: 'Ku dar bogga diiwaanka/liiska maalinlaha ah liiska la socodka (AfD iyo MfD)', helptip: 'Tani waxay khuseysaa oo kaliya AfD iyo MfD, halkaas oo doodaha lagu dhex daro bogga diiwaanka maalinlaha ah (ee AfD) ama bogga weyn ee MfD (ee MfD).', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchUser (string) // The watchlist setting of the user talk page if they receive a notification. { name: 'xfdWatchUser', label: 'Ku dar bogga wada-hadalka ee tabarucaaha bilowga ah liiska la socodka (marka la ogeysiinayo)', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, // TwinkleConfig.xfdWatchRelated (string) // The watchlist setting of the target of a redirect being nominated for RfD. { name: 'xfdWatchRelated', label: "Ku dar bogga bartilmaameedka ee dib-u-jeeddada la magacaabay liiska la socodka (marka la ogeysiinayo)", helptip: 'Tani waxay khuseysaa oo kaliya RfD, marka la reebayo ogeysiis ku yaal bogga wada-hadalka ee bartilmaameedka dib-u-jeeddada', type: 'enum', enumValues: Twinkle.config.watchlistEnums }, { name: 'markXfdPagesAsPatrolled', label: 'Calaamadi bogga mid la eegay marka loo magacaabayo AFD (haddii ay suurtagal tahay)', type: 'boolean' } ] }, { title: 'Qarsan', hidden: true, preferences: [ // twinklerollback.js: defines how many revision to query maximum, maximum possible is 50, default is 50 { name: 'revertMaxRevisions', type: 'integer' }, // twinklewarn.js: When using the autolevel select option, how many days makes a prior warning stale // Huggle is three days ([[Special:Diff/918980316]] and [[Special:Diff/919417999]]) while ClueBotNG is two: // https://github.com/DamianZaremba/cluebotng/blob/4958e25d6874cba01c75f11debd2e511fd5a2ce5/bot/action_functions.php#L62 { name: 'autolevelStaleDays', type: 'integer' }, // How many pages should be queried by deprod and batchdelete/protect/undelete { name: 'batchMax', type: 'integer', adminOnly: true }, // How many pages should be processed at a time by deprod and batchdelete/protect/undelete { name: 'batchChunks', type: 'integer', adminOnly: true } ] } ]; // dhammaadka Twinkle.config.sections Twinkle.config.init = function twinkleconfigInit() { // abuur bogga habaynta ee Wikipedia:Twinkle/Preferences if ((mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').project && mw.config.get('wgTitle') === 'Twinkle/Preferences') && mw.config.get('wgAction') === 'view') { if (!document.getElementById('twinkle-config')) { return; // malaha bogga waa mid si khaldan loo habeeyay, ama wax kale - laakiin isku day kasta oo lagu beddelayo wuxuu noqon doonaa mid aan micno lahayn } // u deji qaabka waxba si looga hortago khilaaf ka imaanaya CSS-ka dibadda document.getElementById('twinkle-config').removeAttribute('style'); document.getElementById('twinkle-config-titlebar').removeAttribute('style'); const contentdiv = document.getElementById('twinkle-config-content'); contentdiv.textContent = ''; // tirtir carruurta // u ogolaow isticmaalaha inuu ogaado khilaafka suurtagalka ah ee skin js/common.js file // (settings in that file will still work, but they will be overwritten by twinkleoptions.js settings) if (window.TwinkleConfig || window.FriendlyConfig) { const contentnotice = document.createElement('div'); contentnotice.className = 'plainlinks twinkle-ombox'; contentnotice.innerHTML = '<div>' + '<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/3/38/Imbox_content.png" />' + '</div>' + '<div>' + '<p><big><b>Ka hor inta aadan beddelin habayntaada halkan,</b> waa inaad ka saartaa habayntaadii hore ee Twinkle iyo Friendly JavaScript-ka maqaarkaaga shakhsiga ah.</big></p>' + '<p>Si aad tan u samayso, waxaad <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/' + mw.config.get('skin') + '.js', { action: 'edit' }) + '" target="_blank"><b>tifatiri kartaa faylka javascript maqaarkaaga shakhsiga ah</b></a> ama <a href="' + mw.util.getUrl('User:' + mw.config.get('wgUserName') + '/common.js', { action: 'edit'}) + '" target="_blank"><b>faylkaaga common.js</b></a>, adigoo ka saaraya dhammaan xarumaha koodka ee tixraacaya <code>TwinkleConfig</code> iyo <code>FriendlyConfig</code>.</p>' + '</div>'; contentdiv.appendChild(contentnotice); } // bilow miiska tusmada const toctable = document.createElement('div'); toctable.className = 'toc'; toctable.style.marginLeft = '0.4em'; // abuur cinwaanka TOC const toctitle = document.createElement('div'); toctitle.id = 'toctitle'; const toch2 = document.createElement('h2'); toch2.textContent = 'Muxuu ka kooban yahay '; toctitle.appendChild(toch2); // ku dar xiriiriyaha tusmada muuji/qari const toctoggle = document.createElement('span'); toctoggle.className = 'toctoggle'; toctoggle.appendChild(document.createTextNode('[')); const toctogglelink = document.createElement('a'); toctogglelink.className = 'internal'; toctogglelink.setAttribute('href', '#tw-tocshowhide'); toctogglelink.textContent = 'qari'; toctoggle.appendChild(toctogglelink); toctoggle.appendChild(document.createTextNode(']')); toctitle.appendChild(toctoggle); toctable.appendChild(toctitle); // abuur weelka shayga: tani waa waxa aan ku darno waxyaabaha const tocul = document.createElement('ul'); toctogglelink.addEventListener('click', () => { const $tocul = $(tocul); $tocul.toggle(); if ($tocul.find(':visible').length) { toctogglelink.textContent = 'qari'; } else { toctogglelink.textContent = 'muuji'; } }, false); toctable.appendChild(tocul); contentdiv.appendChild(toctable); const contentform = document.createElement('form'); contentform.setAttribute('action', 'javascript:void(0)'); // was #tw-save - changed to void(0) to work around Chrome issue contentform.addEventListener('submit', Twinkle.config.save, true); contentdiv.appendChild(contentform); const container = document.createElement('table'); container.style.width = '100%'; contentform.appendChild(container); $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; // macnaheedu waa "sii wad" xaaladdan } // ku dar TOC const tocli = document.createElement('li'); tocli.className = 'toclevel-1'; const toca = document.createElement('a'); toca.setAttribute('href', '#' + section.module); toca.appendChild(document.createTextNode(section.title)); tocli.appendChild(toca); tocul.appendChild(tocli); let row = document.createElement('tr'); let cell = document.createElement('td'); cell.setAttribute('colspan', '3'); const heading = document.createElement('h4'); heading.style.borderBottom = '1px solid gray'; heading.style.marginTop = '0.2em'; heading.id = section.module; heading.appendChild(document.createTextNode(section.title)); cell.appendChild(heading); row.appendChild(cell); container.appendChild(row); let rowcount = 1; // ee qaabaynta safafka // ku dar mid kasta oo ka mid ah doorbidyada foomka $(section.preferences).each((prefkey, pref) => { if (pref.adminOnly && !Morebits.userIsSysop) { return true; // macnaheedu waa "sii wad" xaaladdan } row = document.createElement('tr'); row.style.marginBottom = '0.2em'; // abuur qaabka safafka kala duwan if (rowcount++ % 2 === 0) { row.style.backgroundColor = 'rgba(128, 128, 128, 0.1)'; } cell = document.createElement('td'); let label, input; const gotPref = Twinkle.getPref(pref.name); switch (pref.type) { case 'boolean': // abuur sanduuq calaamadeed cell.setAttribute('colspan', '2'); label = document.createElement('label'); input = document.createElement('input'); input.setAttribute('type', 'checkbox'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (gotPref === true) { input.setAttribute('checked', 'checked'); } label.appendChild(input); label.appendChild(document.createTextNode(pref.label)); cell.appendChild(label); break; case 'string': // abuur sanduuq gelin ah case 'integer': // ku dar sumadda tiirka koowaad cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar sanduuqa gelinta tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('input'); input.setAttribute('type', 'text'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); if (pref.type === 'integer') { input.setAttribute('size', 6); input.setAttribute('type', 'number'); input.setAttribute('step', '1'); // lambarka buuxa oo keliya } if (gotPref) { input.setAttribute('value', gotPref); } cell.appendChild(input); break; case 'enum': // abuur sanduuq isku-dhafan // ku dar sumadda tiirka koowaad // note: duplicates the code above, under string/integer cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar sanduuqa gelinta tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; input = document.createElement('select'); input.setAttribute('id', pref.name); input.setAttribute('name', pref.name); $.each(pref.enumValues, (enumvalue, enumdisplay) => { const option = document.createElement('option'); option.setAttribute('value', enumvalue); if ((gotPref === enumvalue) || // Hack to convert old boolean watchlist prefs // to corresponding enums (added in v2.1) (typeof gotPref === 'boolean' && ((gotPref && enumvalue === 'yes') || (!gotPref && enumvalue === 'no')))) { option.setAttribute('selected', 'selected'); } option.appendChild(document.createTextNode(enumdisplay)); input.appendChild(option); }); cell.appendChild(input); break; case 'set': // abuur sanduuqyo calaamadeed oo kala duwan // ku dar sumadda marka hore cell.setAttribute('colspan', '2'); label = document.createElement('label'); // not really necessary to use a label element here, but we do it for consistency of styling label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); var checkdiv = document.createElement('div'); checkdiv.style.paddingLeft = '1em'; var worker = function(itemkey, itemvalue) { const checklabel = document.createElement('label'); checklabel.style.marginRight = '0.7em'; checklabel.style.display = 'inline-block'; const check = document.createElement('input'); check.setAttribute('type', 'checkbox'); check.setAttribute('id', pref.name + '_' + itemkey); check.setAttribute('name', pref.name + '_' + itemkey); if (gotPref && gotPref.includes(itemkey)) { check.setAttribute('checked', 'checked'); } // cater for legacy integer array values for unlinkNamespaces (this can be removed a few years down the track...) if (pref.name === 'unlinkNamespaces') { if (gotPref && gotPref.includes(parseInt(itemkey, 10))) { check.setAttribute('checked', 'checked'); } } checklabel.appendChild(check); checklabel.appendChild(document.createTextNode(itemvalue)); checkdiv.appendChild(checklabel); }; if (pref.setDisplayOrder) { // ku dar sanduuqyada calaamadeed iyadoo la raacayo habka la bixiyay $.each(pref.setDisplayOrder, (itemkey, item) => { worker(item, pref.setValues[item]); }); } else { // ku dar sanduuqyada calaamadeed iyadoo la raacayo habka naloo soo geliyay $.each(pref.setValues, worker); } cell.appendChild(checkdiv); break; case 'customList': // ku dar sumadda tiirka koowaad cell.style.textAlign = 'right'; cell.style.paddingRight = '0.5em'; label = document.createElement('label'); label.setAttribute('for', pref.name); label.appendChild(document.createTextNode(pref.label + ':')); cell.appendChild(label); row.appendChild(cell); // ku dar badhanka tiirka labaad cell = document.createElement('td'); cell.style.paddingRight = '1em'; var button = document.createElement('button'); button.setAttribute('id', pref.name); button.setAttribute('name', pref.name); button.setAttribute('type', 'button'); button.addEventListener('click', Twinkle.config.listDialog.display, false); // isticmaal xogta jQuery ee badhanka si aad u kaydiso qiimaha habaynta ee hadda $(button).data({ value: gotPref, pref: pref }); button.appendChild(document.createTextNode('Wax ka beddel walxaha')); cell.appendChild(button); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } row.appendChild(cell); // ku dar tilmaamaha caawimaadda cell = document.createElement('td'); cell.className = 'twinkle-config-helptip'; if (pref.helptip) { // u beddel xiriiriyeya la gujin karo xusidda qaababka ee ku jira tilmaamaha caawimaadda cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g, '{{<a href="' + mw.util.getUrl('Template:') + '$1" target="_blank">$1</a>}}'); } // ku dar xiriiriyaha dib-u-dejinta (custom lists don't need this, as their config value isn't displayed on the form) if (pref.type !== 'customList') { const resetlink = document.createElement('a'); resetlink.setAttribute('href', '#tw-reset'); resetlink.setAttribute('id', 'twinkle-config-reset-' + pref.name); resetlink.addEventListener('click', Twinkle.config.resetPrefLink, false); resetlink.style.cssFloat = 'right'; resetlink.style.margin = '0 0.6em'; resetlink.appendChild(document.createTextNode('Dib u deji')); cell.appendChild(resetlink); } row.appendChild(cell); container.appendChild(row); return true; }); return true; }); const footerbox = document.createElement('div'); footerbox.setAttribute('id', 'twinkle-config-buttonpane'); const button = document.createElement('button'); button.setAttribute('id', 'twinkle-config-submit'); button.setAttribute('type', 'submit'); button.appendChild(document.createTextNode('Kaydi isbeddellada')); footerbox.appendChild(button); const footerspan = document.createElement('span'); footerspan.className = 'plainlinks'; footerspan.style.marginLeft = '2.4em'; footerspan.style.fontSize = '90%'; const footera = document.createElement('a'); footera.setAttribute('href', '#tw-reset-all'); footera.setAttribute('id', 'twinkle-config-resetall'); footera.addEventListener('click', Twinkle.config.resetAllPrefs, false); footera.appendChild(document.createTextNode('Soo celi waxyaabaha caadiga ah')); footerspan.appendChild(footera); footerbox.appendChild(footerspan); contentform.appendChild(footerbox); // maaddaama dhammaan cinwaannada cutubyada ay jiraan hadda, waxaan isku dayi karnaa inaan tagno barroosinka la codsaday if (window.location.hash) { const loc = window.location.hash; window.location.hash = ''; window.location.hash = loc; } } else if (mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user && mw.config.get('wgTitle').indexOf(mw.config.get('wgUserName')) === 0 && mw.config.get('wgPageName').slice(-3) === '.js') { const box = document.createElement('div'); // Styled in twinkle.css box.setAttribute('id', 'twinkle-config-headerbox'); let link; const scriptPageName = mw.config.get('wgPageName').slice( mw.config.get('wgPageName').lastIndexOf('/') + 1, mw.config.get('wgPageName').lastIndexOf('.js') ); if (scriptPageName === 'twinkleoptions') { // place "why not try the preference panel" notice box.setAttribute('class', 'config-twopt-box'); if (mw.config.get('wgArticleId') > 0) { // page exists box.appendChild(document.createTextNode('Boggani wuxuu ka kooban yahay doorbidyadaada Twinkle. Waxaad ku beddeli kartaa adigoo isticmaalaya ')); } else { // page does not exist box.appendChild(document.createTextNode('Waxaad habayn kartaa Twinkle si uu ugu habboonaado doorbidyadaada adigoo isticmaalaya ')); } link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode(', ama adigoo tifatiraya boggan.')); $(box).insertAfter($('#contentSub')); } else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].includes(scriptPageName)) { // place "Looking for Twinkle options?" notice box.setAttribute('class', 'config-userskin-box'); box.appendChild(document.createTextNode('Haddii aad rabto inaad dejiso doorbidyada Twinkle, waxaad isticmaali kartaa ')); link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').project] + ':Twinkle/Preferences')); link.appendChild(document.createTextNode('guddiga doorbididda Twinkle')); box.appendChild(link); box.appendChild(document.createTextNode('.')); $(box).insertAfter($('#contentSub')); } } }; // alaabta la xiriirta liiska gaarka ah Twinkle.config.listDialog = {}; Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow($dlgtable, value, label) { let $contenttr, $valueInput, $labelInput; $dlgtable.append( $contenttr = $('<tr>').append( $('<td>').append( $('<button>') .attr('type', 'button') .on('click', () => { $contenttr.remove(); }) .text('Tirtir') ), $('<td>').append( $valueInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-value') .css('width', '97%') ), $('<td>').append( $labelInput = $('<input>') .attr('type', 'text') .addClass('twinkle-config-customlist-label') .css('width', '98%') ) ) ); if (value) { $valueInput.val(value); } if (label) { $labelInput.val(label); } }; Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) { const $prefbutton = $(e.target); const curvalue = $prefbutton.data('value'); const curpref = $prefbutton.data('pref'); const dialog = new Morebits.SimpleWindow(720, 400); dialog.setTitle(curpref.label); dialog.setScriptName('Doorbidyada Twinkle'); let $dlgtbody; dialog.setContent( $('<div>').append( $('<table>') .addClass('wikitable') .css({ margin: '1.4em 1em', width: 'auto' }) .append( $dlgtbody = $('<tbody>').append( // header row $('<tr>').append( $('<th>') // top-left cell .css('width', '5%'), $('<th>') // value column header .css('width', '35%') .text(curpref.customListValueTitle ? curpref.customListValueTitle : 'Qiimaha'), $('<th>') // label column header .css('width', '60%') .text(curpref.customListLabelTitle ? curpref.customListLabelTitle : 'Calaamadda') ) ), $('<tfoot>').append( $('<tr>').append( $('<td>') .attr('colspan', '3') .append( $('<button>') .text('Ku dar') .css('min-width', '8em') .attr('type', 'button') .on('click', () => { Twinkle.config.listDialog.addRow($dlgtbody); }) ) ) ) ), $('<button>') .text('Kaydi isbeddellada') .attr('type', 'submit') // so Morebits.SimpleWindow puts the button in the button pane .on('click', () => { Twinkle.config.listDialog.save($prefbutton, $dlgtbody); dialog.close(); }), $('<button>') .text('Dib u deji') .attr('type', 'submit') .on('click', () => { Twinkle.config.listDialog.reset($prefbutton, $dlgtbody); }), $('<button>') .text('Jooji') .attr('type', 'submit') .on('click', () => { dialog.close(); }) )[0] ); // content rows let gotRow = false; $.each(curvalue, (k, v) => { gotRow = true; Twinkle.config.listDialog.addRow($dlgtbody, v.value, v.label); }); // if there are no values present, add a blank row to start the user off if (!gotRow) { Twinkle.config.listDialog.addRow($dlgtbody); } dialog.display(); }; // Resets the data value, re-populates based on the new (default) value, then saves the // old data value again (less surprising behaviour) Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset($button, $tbody) { // reset value on button const curpref = $button.data('pref'); const oldvalue = $button.data('value'); Twinkle.config.resetPref(curpref); // reset form $tbody.find('tr').slice(1).remove(); // all rows except the first (header) row // add the new values const curvalue = $button.data('value'); $.each(curvalue, (k, v) => { Twinkle.config.listDialog.addRow($tbody, v.value, v.label); }); // save the old value $button.data('value', oldvalue); }; Twinkle.config.listDialog.save = function twinkleconfigListDialogSave($button, $tbody) { const result = []; let current = {}; $tbody.find('input[type="text"]').each((inputkey, input) => { if ($(input).hasClass('twinkle-config-customlist-value')) { current = { value: input.value }; } else { current.label = input.value; // exclude totally empty rows if (current.value || current.label) { result.push(current); } } }); $button.data('value', result); }; // reset/restore defaults Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) { const wantedpref = e.target.id.slice(21); // "twinkle-config-reset-" prefix is stripped // search tactics $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; // continue: skip impossibilities } let foundit = false; $(section.preferences).each((prefkey, pref) => { if (pref.name !== wantedpref) { return true; // continue } Twinkle.config.resetPref(pref); foundit = true; return false; // break }); if (foundit) { return false; // break } }); return false; // stop link from scrolling page }; Twinkle.config.resetPref = function twinkleconfigResetPref(pref) { switch (pref.type) { case 'boolean': document.getElementById(pref.name).checked = Twinkle.defaultConfig[pref.name]; break; case 'string': case 'integer': case 'enum': document.getElementById(pref.name).value = Twinkle.defaultConfig[pref.name]; break; case 'set': $.each(pref.setValues, (itemkey) => { if (document.getElementById(pref.name + '_' + itemkey)) { document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].includes(itemkey); } }); break; case 'customList': $(document.getElementById(pref.name)).data('value', Twinkle.defaultConfig[pref.name]); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } }; Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() { // no confirmation message - the user can just refresh/close the page to abort $(Twinkle.config.sections).each((sectionkey, section) => { if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) { return true; // continue: skip impossibilities } $(section.preferences).each((prefkey, pref) => { if (!pref.adminOnly || Morebits.userIsSysop) { Twinkle.config.resetPref(pref); } }); return true; }); return false; // stop link from scrolling page }; Twinkle.config.save = function twinkleconfigSave(e) { Morebits.Status.init(document.getElementById('twinkle-config-content')); const userjs = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user] + ':' + mw.config.get('wgUserName') + '/twinkleoptions.js'; const wikipediaPage = new Morebits.wiki.Page(userjs, 'Kaydinaya doorbidyada ' + userjs); wikipediaPage.setCallbackParameters(e.target); wikipediaPage.load(Twinkle.config.writePrefs); return false; }; Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) { const form = pageobj.getCallbackParameters(); // this is the object which gets serialized into JSON; only // preferences that this script knows about are kept const newConfig = {optionsVersion: 2.1}; // a comparison function is needed later on // it is just enough for our purposes (i.e. comparing strings, numbers, booleans, // arrays of strings, and arrays of { value, label }) // and it is not very robust: e.g. compare([2], ["2"]) === true, and // compare({}, {}) === false, but it's good enough for our purposes here const compare = function(a, b) { if (Array.isArray(a)) { if (a.length !== b.length) { return false; } const asort = a.sort(), bsort = b.sort(); for (let i = 0; asort[i]; ++i) { // comparison of the two properties of custom lists if ((typeof asort[i] === 'object') && (asort[i].label !== bsort[i].label || asort[i].value !== bsort[i].value)) { return false; } else if (asort[i].toString() !== bsort[i].toString()) { return false; } } return true; } return a === b; }; $(Twinkle.config.sections).each((sectionkey, section) => { if (section.adminOnly && !Morebits.userIsSysop) { return; // i.e. "continue" in this context } // reach each of the preferences from the form $(section.preferences).each((prefkey, pref) => { let userValue; // = undefined // only read form values for those prefs that have them if (!pref.adminOnly || Morebits.userIsSysop) { if (!section.hidden) { switch (pref.type) { case 'boolean': // read from the checkbox userValue = form[pref.name].checked; break; case 'string': // read from the input box or combo box case 'enum': userValue = form[pref.name].value; break; case 'integer': // read from the input box userValue = parseInt(form[pref.name].value, 10); if (isNaN(userValue)) { Morebits.Status.warn('Kaydinaya', 'Qiimaha aad u cayimay ' + pref.name + ' (' + pref.value + ') wuxuu ahaa mid aan shaqaynayn. Kaydintu waa sii socon doontaa, laakiin xogta khaldan waa la dhaafi doonaa.'); userValue = null; } break; case 'set': // read from the set of check boxes userValue = []; if (pref.setDisplayOrder) { // read only those keys specified in the display order $.each(pref.setDisplayOrder, (itemkey, item) => { if (form[pref.name + '_' + item].checked) { userValue.push(item); } }); } else { // read all the keys in the list of values $.each(pref.setValues, (itemkey) => { if (form[pref.name + '_' + itemkey].checked) { userValue.push(itemkey); } }); } break; case 'customList': // read from the jQuery data stored on the button object userValue = $(form[pref.name]).data('value'); break; default: alert('twinkleconfig: nooca xogta ee aan la aqoon ee doorbiditaanka ' + pref.name); break; } } else if (Twinkle.prefs) { // Retain the hidden preferences that may have customised by the user from twinkleoptions.js // undefined if not set userValue = Twinkle.prefs[pref.name]; } } // only save those preferences that are *different* from the default if (userValue !== undefined && !compare(userValue, Twinkle.defaultConfig[pref.name])) { newConfig[pref.name] = userValue; } }); }); let text = '// twinkleoptions.js: faylka doorbidyada shakhsiga ah ee Twinkle\n' + '//\n' + '// FIIRO GAAR AH: Habka ugu fudud ee aad ku beddeli karto doorbidyadaada Twinkle waa adigoo isticmaalaya\n' + '// guddiga doorbididda Twinkle, ee [[:' + Morebits.pageNameNorm + ']].\n' + '//\n' + '// Faylkan waxaa la soo saaray SI OTOMAATIG AH. Wixii isbeddel ah ee aad samayso (marka laga reebo\n' + '// beddelidda cabbiraadaha habaynta si JavaScript sax ah u ah) waxaa lagu\n' + '// dul qori doonaa marka xigta ee aad gujiso "kaydi" guddiga doorbididda\n' + '// Twinkle. Haddii aad wax ka beddelayso faylkan, hubi inaad isticmaasho JavaScript sax ah.\n' + // eslint-disable-next-line no-useless-concat '// <no' + 'wiki>\n' + '\n' + 'window.Twinkle.prefs = '; text += JSON.stringify(newConfig, null, 2); text += ';\n' + '\n' + // eslint-disable-next-line no-useless-concat '// </no' + 'wiki>\n' + '// Dhamaadka twinkleoptions.js\n'; pageobj.setPageText(text); pageobj.setEditSummary('Kaydinaya doorbidyada Twinkle: tifatir otomaatig ah oo ka yimid [[:' + Morebits.pageNameNorm + ']]'); pageobj.setChangeTags(Twinkle.changeTags); pageobj.setCreateOption('recreate'); pageobj.save(Twinkle.config.saveSuccess); }; Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) { pageobj.getStatusElement().info('waa lagu guulaystay'); const noticebox = document.createElement('div'); noticebox.className = 'cdx-message cdx-message--success'; noticebox.style.fontSize = '100%'; noticebox.innerHTML = '<p><b>Doorbidyadaada Twinkle waa la kaydiyay.</b> Si aad u aragto isbeddellada, waxaad u baahan doontaa inaad gebi ahaanba nadiifiso kaydka biraawsarkaaga (fiiri <a href="' + mw.util.getUrl('WP:BYPASS') + '" title="WP:BYPASS">WP:BYPASS</a> tilmaamaha).</p>'; mw.loader.using('mediawiki.htmlform.codex.styles', () => { Morebits.Status.root.appendChild(noticebox); }); const noticeclear = document.createElement('br'); noticeclear.style.clear = 'both'; Morebits.Status.root.appendChild(noticeclear); }; Twinkle.addInitCallback(Twinkle.config.init); }()); // </nowiki> t8i05bxdod5r92it0nkidykv2xcamcd MediaWiki:Gadget-morebits.js 8 53721 311230 310915 2026-10-28T16:53:58Z Isma4l 41797 311230 javascript text/javascript // <nowiki> /** * Maktabad ka buuxda faa'iidooyin badan oo loogu talagalay qoraallada isticmaalaha ee wiki-yada MediaWiki, oo ay ku jirto Wikipedia. * * Qodobbada muhiimka ah waxaa ka mid ah: * - {@link Morebits.wiki.Api} - samee wicitaano ku socda MediaWiki API * - {@link Morebits.wiki.Page} - wax ka beddel bogagga wiki-ga (wax ka beddel, dib u soo celis, tirtir, iwm.) * - {@link Morebits.Date} - habaynta shayga taariikhda oo la xoojiyay, oo ah nooc ka mid ah moment.js oo fudud * - {@link Morebits.QuickForm} - soo saar foomamka HTML ee degdegga ah inta lagu jiro duulimaadka * - {@link Morebits.SimpleWindow} - soo saar daaqadaha wadahadalka iyo moodalka * - {@link Morebits.Status} - bandhigaha fariinta xaaladda ee adag, oo ay isticmaalaan fasallada Morebits.wiki * - {@link Morebits.wikitext} - qalab loogu talagalay la tacaalidda wikitext-ka * - {@link Morebits.string} - qalab loogu talagalay maamulidda xargaha (strings) * - {@link Morebits.array} - qalab loogu talagalay maamulidda safafka (arrays) * - {@link Morebits.ip} - qalab gacan ka geysta habaynta ciwaanada IP-ga * * Tiirarka ku xiran (Dependencies): * - Wax walba waxay ku tiirsan yihiin jQuery. Laakiin wiki-yada badankoodu waa inay tan bixiyaan si caadi ah. * - {@link Morebits.QuickForm}, {@link Morebits.SimpleWindow}, iyo {@link Morebits.Status} waxay ku tiirsan yihiin faylka "morebits.css" ee qaabaynkooda. * - Si aad u abuurto qalab ku salaysan morebits.js, isticmaal sintakiskan ku jira MediaWiki:Gadgets-definition: * - `*GadgetName[ResourceLoader|dependencies=mediawiki.user,mediawiki.util,mediawiki.Title]|morebits.js|morebits.css|GadgetName.js` * - Haddii kale, waxaad qaabayn kartaa morebits.js oo ah qalab qarsan oo ku jira MediaWiki:Gadgets-definition: * - `*morebits[ResourceLoader|dependencies=mediawiki.user,mediawiki.util,mediawiki.Title|hidden]|morebits.js|morebits.css` * ka dibna culeys ext.gadget.morebits sida mid ka mid ah tiirarka ku xiran ee qalabka cusub. * * Dhammaan waxyaabaha halkan ku jira waxay ka shaqeeyaan dhammaan daalacashada ay MediaWiki u feydo taageerada JavaScript. * * Maktabaddan waxaa ilaaliya ilaaliyaasha Twinkle. * Wixii su'aalo ah, talooyin, caawinaad, iwm., aad [Wikipedia talk:Twinkle on English Wikipedia](http://en.wikipedia.org/wiki/WT:TW). * Isha horumarinta ugu dambeysa waxaa laga helayaa {@link https://github.com/wikimedia-gadgets/twinkle/blob/master/src/morebits.js|GitHub}. * * @namespace Morebits */ (function() { /** @lends Morebits */ const Morebits = {}; window.Morebits = Morebits; // u oggolow helitaanka caalamiga ah /** * Habaynta gaarka ah ee Wiki ee Morebits */ Morebits.l10n = { /** * Magacyada maxalliga ah ee ereyada sixirka "redirect". * Hubi adigoo isticmaalaya api.php?action=query&format=json&meta=siteinfo&formatversion=2&siprop=magicwords */ redirectTagAliases: ['#REDIRECT'], /** * Waxay qaadataa xargo dood ahaan waxayna hubisaa inay tahay waqti-shaabadeed (timestamp) iyo inkale * Haddii aysan ahayn, waxay soo celineysaa null. Haddii ay tahay, waxay soo celinaysaa saf tirooyin ah * oo qaab ah [year, month, date, hour, minute, second] * taas oo loo gudbin karo Date.UTC() * * @param {string} str * @return {number[] | null} */ signatureTimestampFormat: function(str) { // HH:mm, DD Month YYYY (UTC) const rgx = /(\d{2}):(\d{2}), (\d{1,2}) (\w+) (\d{4}) \(UTC\)/; const match = rgx.exec(str); if (!match) { return null; } const month = Morebits.Date.localeData.months.indexOf(match[4]); if (month === -1) { return null; } // ..... sanadka ... bisha .. taariikhda ... saacada .... daqiiqada return [match[5], month, match[3], match[1], match[2]]; } }; /** * Shaqo caawiye fudud si loo arko kooxaha uu isticmaalahu ka tirsanaan karo. * * @param {string} group - tusaale `sysop`, `extendedconfirmed`, iwm. * @return {boolean} */ Morebits.userIsInGroup = function(group) { return mw.config.get('wgUserGroups').includes(group); }; /** * Wuxuu si adag u qeexayaa in isticmaalaha uu yahay sysop, kaas oo la isticmaalo marar badan. * * @type {boolean} */ Morebits.userIsSysop = Morebits.userIsInGroup('sysop'); /** * Waxay go'aaminaysaa in bogga hadda jira uu yahay leexin (redirect) ama leexin jilicsan. Wuxuu ku guuldareystaa * inuu ogaado leexinta jilicsan ee bogagga wax ka beddelka, taariikhda, iwm. Wuxuu isku dayi doonaa inuu * ogaado Module:RfD, oo wata dhibco isku mid ah oo guuldarro ah. * * @return {boolean} */ Morebits.isPageRedirect = function() { return !!(mw.config.get('wgIsRedirect') || document.getElementById('softredirect') || $('.box-RfD').length); }; /** * Wuxuu kaydiyaa nooc caadi ah (hooseeyayaasha oo loo beddelay meel bannaan) ee * doorsoomaha `wgPageName`. * * @type {string} */ Morebits.pageNameNorm = mw.config.get('wgPageName').replace(/_/g, ' '); /** * Abuur xargo loogu isticmaalo regex oo la jaanqaadaysa magaca bogga. Wuxuu xisaabtanka ku darayaa * xarfaha hore ee waaweyn, hooseeyayaasha oo ah meelo bannaan, iyo astaamaha gaarka ah * ee la baxsado. Sidoo kale eeg {@link Morebits.namespaceRegex}. * * @param {string} pageName - Magaca bogga oo aan lahayn meesha magaca (namespace). * @return {string} - Magaca bogga `Foo bar`, wuxuu soo celinayaa xarigga `[Ff]oo[_ ]bar`. */ Morebits.pageNameRegex = function(pageName) { if (pageName === '') { return ''; } const firstChar = pageName[0], remainder = Morebits.string.escapeRegExp(pageName.slice(1)); if (mw.Title.phpCharToUpper(firstChar) !== firstChar.toLowerCase()) { return '[' + mw.Title.phpCharToUpper(firstChar) + firstChar.toLowerCase() + ']' + remainder; } return Morebits.string.escapeRegExp(firstChar) + remainder; }; /** * Waxay u beddeshaa xarig ama safka gunti-abuurayaasha DOM (DOM nodes) qayb HTML ah. * Sintakiska xiriirinta wiki (`[[...]]`) waxaa loo beddelaa saldhig HTML ah. * Waxaa lagu isticmaalo Morebits.QuickForm iyo Morebits.Status * * @internal * @param {string|Node|(string|Node)[]} input * @return {DocumentFragment} */ Morebits.createHtml = function(input) { const fragment = document.createDocumentFragment(); if (!input) { return fragment; } if (!Array.isArray(input)) { input = [input]; } for (let i = 0; i < input.length; ++i) { if (input[i] instanceof Node) { fragment.appendChild(input[i]); } else { $.parseHTML(Morebits.createHtml.renderWikilinks(input[i])).forEach((node) => { fragment.appendChild(node); }); } } return fragment; }; /** * Waxay u beddeshaa xiriirinta wiki tags-ka saldhigga HTML. * * @param {string} text * @return {string} */ Morebits.createHtml.renderWikilinks = function(text) { const ub = new Morebits.Unbinder(text); // Ha u beddelin xiriirinta wiki ee gudaha calaamadaha koodka maadaama loo isticmaalo soo bandhigidda koodka wiki ub.unbind('<code>', '</code>'); ub.content = ub.content.replace( /\[\[:?(?:([^|\]]+?)\|)?([^\]|]+?)\]\]/g, (_, target, text) => { if (!target) { target = text; } return '<a target="_blank" href="' + mw.util.getUrl(target) + '" title="' + target.replace(/"/g, '&#34;') + '">' + text + '</a>'; }); return ub.rebind(); }; /** * Abuur xarig loogu isticmaalo regex ee ku habboon dhammaan magacyada meelaha (aliases), iyadoon loo eegin * xarfaha waaweyn iyo hooseeyayaasha/meelaha bannaan. Ma ku jirto xarafka hore ee ikhtiyaariga ah * ee `:`, laakiin haddii ay jiraan wax ka badan hal shay, wuxuu ku duubaa liiska koox * aan qabsasho lahayn. Tani waxay ka dhigan tahay inaad samayn karto `Morebits.namespaceRegex([4]) + * ':' + Morebits.pageNameRegex('Twinkle')` si aad u waafajiso bog buuxa. Wuxuu isticmaalaa * {@link Morebits.pageNameRegex}. * * @param {number[]} namespaces - Safka nambarada meelaha (namespaces). Nambarada aan la isticmaalin/ansaxnayn * ee meelaha waxaa si aamusan loo tuuraa. * @example * // waxay soo celinaysaa '(?:[Ff][Ii][Ll][Ee]|[Ii][Mm][Aa][Gg][Ee])' * Morebits.namespaceRegex([6]) * @return {string} - Xarig ku habboon Regex oo ah dhammaan magacyada meelaha. */ Morebits.namespaceRegex = function(namespaces) { if (!Array.isArray(namespaces)) { namespaces = [namespaces]; } const aliases = []; let regex; $.each(mw.config.get('wgNamespaceIds'), (name, number) => { if (namespaces.includes(number)) { // Meelaha magacyadu gabi ahaanba waa kuwo aan u janjeerin xarfaha waaweyn iyo hooseeyayaasha, // waxaana xarigga regex uu yahay mid faa'iido badan / la jaanqaadi kara marka loo eego shayga RegExp, // markaas annaguna waxaan aqbalnay xaraf kasta kiis kasta oo warqad ah. aliases.push(name.split('').map((char) => Morebits.pageNameRegex(char)).join('')); } }); switch (aliases.length) { case 0: regex = ''; break; case 1: regex = aliases[0]; break; default: regex = '(?:' + aliases.join('|') + ')'; break; } return regex; }; /* **************** Morebits.QuickForm **************** */ /** * Abuuritaanka foomam fudud oo heer sare ah iyada oo aan la helin codayn gaar ah oo badan. * * @namespace Morebits.QuickForm * @memberof Morebits * @class * @param {event} event - Shaqada la fulinayo marka foomka la gudbiyo. * @param {string} [eventType=submit] - Nooca dhacdada. */ Morebits.QuickForm = function QuickForm(event, eventType) { this.root = new Morebits.QuickForm.Element({ type: 'form', event: event, eventType: eventType }); }; /** * Waxay soo bandhigeysaa wax soo saarka HTML ee quickForm. * * @memberof Morebits.QuickForm * @return {HTMLElement} */ Morebits.QuickForm.prototype.render = function QuickFormRender() { const ret = this.root.render(); ret.names = {}; return ret; }; /** * Ku dar shay foomka. * * @memberof Morebits.QuickForm * @param {(object|Morebits.QuickForm.Element)} data - Shayga quickform, ama shayga uu ku dhisanyahay * shayga quickform. * @return {Morebits.QuickForm.Element} - Sida shayga loo gudbiyay shaqada. */ Morebits.QuickForm.prototype.append = function QuickFormAppend(data) { return this.root.append(data); }; /** * Abuur shay cusub oo loogu talagalay foomka. * * Tusmada noocyada Morebits.QuickForm.Element: * - Sifooyinka caalamiga ah: id, className, style, tooltip, extra, $data, adminonly * - `select`: Sanduuqa isku-dhafka (sidoo kale loo yaqaan drop-down). * - Sifooyinka: name, label, multiple, size, list, event, disabled * - `option`: Shay loogu talagalay sanduuqa isku-dhafka. * - Sifooyinka: value, label, selected, disabled * - `optgroup`: Koox ka kooban "option"yo. * - Sifooyinka: label, list * - `field`: Goob beer (sidoo kale loo yaqaan group box). * - Sifooyinka: name, label, disabled * - `checkbox`: Calaamadda hubinta (checkbox). Waa in la isticmaalo cabbirka "list". * - Sifooyinka: name, list, event * - Sifooyinka (gudaha list): name, label, value, checked, disabled, event, subgroup * - `radio`: Badhanka raadiyaha. Waa in la isticmaalo cabbirka "list". * - Sifooyinka: name, list, event * - Sifooyinka (gudaha list): name, label, value, checked, disabled, event, subgroup * - `input`: Sanduuqa gelinta qoraalka. * - Sifooyinka: name, label, value, size, placeholder, maxlength, disabled, required, readonly, event * - `number`: Sanduuqa gelinta nambarka. * - Sifooyinka: Wax walba oo uu `input` qoraalku leeyahay, iyo sidoo kale: min, max, step, list * - `dyninput`: Qayb ka mid ah sanduuqyada qoraalka oo wata badhamada "Remove" iyo badhanka "Add". * - Sifooyinka: name, label, min, max, inputs, sublabel, value, size, maxlength, event * - `hidden`: Goob foom oo aan la arki karin. * - Sifooyinka: name, value * - `header`: Madaxa heerka 5aad. * - Sifooyinka: label * - `div`: Shay meel-hayte guud ah ama sumad. * - Sifooyinka: name, label * - `submit`: Badhanka gudbinta. Morebits.SimpleWindow waxay kuwan u raraysaa hooseeyaasha wadahadalka. * - Sifooyinka: name, label, disabled * - `button`: Badhan guud. * - Sifooyinka: name, label, disabled, event * - `textarea`: Sanduuq qoraal oo weyn oo safaf badan leh. * - Sifooyinka: name, label, value, cols, rows, disabled, required, readonly * - `fragment`: Shay DocumentFragment ah. * - Ma laha sifooyin, mana laha sifooyin caalami ah marka laga reebo adminonly. * Waxaa jira xoogaa kala duwanaansho ah oo ku saabsan sida noocyadu u maamulaan sifooyinka `label`: * - `div`, `select`, `field`, `checkbox`/`radio`, `input`, `textarea`, `header`, iyo `dyninput` waxay aqbali karaan safar shay ah, * waxaana walxaha sumaddu noqon karaan `Element`. * - `option`, `optgroup`, `_dyninput_cell`, `submit`, iyo `button` waxay aqbalaan hal xarig oo keliya. * * @memberof Morebits.QuickForm * @class * @param {Object} data - Shayag matalaya shayga quickform. Waa inuu *eexayaa mid ka mid ah noocyada la heli karo ee ka yimid tusmada sare, iyo sidoo kale sifooyin kasta * ee khuseeya oo la heli karo. * @example new Morebits.QuickForm.Element({ * name: 'target', * type: 'input', * label: 'Your target:', * tooltip: 'Enter your target. Required.', * required: true * }); */ Morebits.QuickForm.Element = function QuickFormElement(data) { this.data = data; this.childs = []; }; /** * @memberof Morebits.QuickForm.Element * @type {number} */ Morebits.QuickForm.Element.id = 0; /** * Wuxuu ku darayaa shay shayga hadda jira. * * @memberof Morebits.QuickForm.Element * @param {Morebits.QuickForm.Element} data - Shay quickForm ah ama shayga loo baahan yahay si * loo abuuro shayga quickForm. * @return {Morebits.QuickForm.Element} Shayga la mid ah ee la soo gudbiyay. */ Morebits.QuickForm.Element.prototype.append = function QuickFormElementAppend(data) { let child; if (data instanceof Morebits.QuickForm.Element) { child = data; } else { child = new Morebits.QuickForm.Element(data); } this.childs.push(child); return child; }; /** * Waxay soo bandhigeysaa wax soo saarka HTML ee shayga quickForm. Tan waa in la waco * iyada oo aan la marin xuduudo: `form.render()`. * * @memberof Morebits.QuickForm.Element * @return {HTMLElement} */ Morebits.QuickForm.Element.prototype.render = function QuickFormElementRender(internal_subgroup_id) { const currentNode = this.compute(this.data, internal_subgroup_id); for (let i = 0; i < this.childs.length; ++i) { // ha u gudbin internal_subgroup_id wicitaannada soo noqnoqoshada (recursive) currentNode[1].appendChild(this.childs[i].render()); } return currentNode[0]; }; /** @memberof Morebits.QuickForm.Element */ Morebits.QuickForm.Element.prototype.compute = function QuickFormElementCompute(data, in_id) { let node; let childContainer = null; let label; const id = (in_id ? in_id + '_' : '') + 'node_' + Morebits.QuickForm.Element.id++; if (data.adminonly && !Morebits.userIsSysop) { // hargab hack alpha data.type = 'hidden'; } let i, current, subnode; switch (data.type) { case 'form': node = document.createElement('form'); node.className = 'quickform'; node.setAttribute('action', 'javascript:void(0);'); if (data.event) { node.addEventListener(data.eventType || 'submit', data.event, false); } break; case 'fragment': node = document.createDocumentFragment(); // jajabyadu ma yeelan karaan sifooyin kasta, markaa si toos ah u soo celi return [node, node]; // Mararka qaarkood Twinkle waxay isticmaashaa "select" xulashooyin raadin oo qurux badan. Tan waxaa xoojinaya maktabadda dhinac saddexaad ee "select2". Ku shaqee adigoo abuuraya shay Morebits "select", ka dibna wac `$('select[name=sub_group]').select2({});` ama wax la mid ah dhamaadka koodkaaga ugu weyn. case 'select': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('label')); label.setAttribute('for', id); label.appendChild(Morebits.createHtml(data.label)); label.style.marginRight = '3px'; } var select = node.appendChild(document.createElement('select')); if (data.event) { select.addEventListener('change', data.event, false); } if (data.multiple) { select.setAttribute('multiple', 'multiple'); } if (data.size) { select.setAttribute('size', data.size); } if (data.disabled) { select.setAttribute('disabled', 'disabled'); } select.setAttribute('name', data.name); if (data.list) { for (i = 0; i < data.list.length; ++i) { current = data.list[i]; if (current.list) { current.type = 'optgroup'; } else { current.type = 'option'; } subnode = this.compute(current); select.appendChild(subnode[0]); } } childContainer = select; break; case 'option': node = document.createElement('option'); node.values = data.value; node.setAttribute('value', data.value); if (data.selected) { node.setAttribute('selected', 'selected'); } if (data.disabled) { node.setAttribute('disabled', 'disabled'); } node.setAttribute('label', data.label); node.appendChild(document.createTextNode(data.label)); break; case 'optgroup': node = document.createElement('optgroup'); node.setAttribute('label', data.label); if (data.list) { for (i = 0; i < data.list.length; ++i) { current = data.list[i]; current.type = 'option'; // waa inay noqdaan options halkan subnode = this.compute(current); node.appendChild(subnode[0]); } } break; case 'field': node = document.createElement('fieldset'); label = node.appendChild(document.createElement('legend')); label.appendChild(Morebits.createHtml(data.label)); if (data.name) { node.setAttribute('name', data.name); } if (data.disabled) { node.setAttribute('disabled', 'disabled'); } break; case 'checkbox': case 'radio': node = document.createElement('div'); if (data.list) { for (i = 0; i < data.list.length; ++i) { const cur_id = id + '_' + i; current = data.list[i]; var cur_div; if (current.type === 'header') { // inline hack cur_div = node.appendChild(document.createElement('h6')); cur_div.appendChild(document.createTextNode(current.label)); if (current.tooltip) { Morebits.QuickForm.Element.generateTooltip(cur_div, current); } continue; } cur_div = node.appendChild(document.createElement('div')); subnode = cur_div.appendChild(document.createElement('input')); subnode.values = current.value; subnode.setAttribute('value', current.value); subnode.setAttribute('type', data.type); subnode.setAttribute('id', cur_id); subnode.setAttribute('name', current.name || data.name); // Haddii magaca la bixiyo sanduuqa hubinta shaqsi ahaaneed, ku dar xog-hal (data-single) // sifo taas oo muujinaysa inaysan qayb ka ahayn liiska sanduuqyada hubinta ee leh // magac isku mid ah. Waxaa lagu isticmaalaagetInputData() if (current.name) { subnode.setAttribute('data-single', 'data-single'); } if (current.checked) { subnode.setAttribute('checked', 'checked'); } if (current.disabled) { subnode.setAttribute('disabled', 'disabled'); } label = cur_div.appendChild(document.createElement('label')); label.appendChild(Morebits.createHtml(current.label)); label.setAttribute('for', cur_id); if (current.tooltip) { Morebits.QuickForm.Element.generateTooltip(label, current); } // qaababku waxay galaan sumadda, macno ma samaynayso in la habeeyo checkbox/radio if (current.style) { label.setAttribute('style', current.style); } var event; if (current.subgroup) { let tmpgroup = current.subgroup; if (!Array.isArray(tmpgroup)) { tmpgroup = [tmpgroup]; } var subgroupRaw = new Morebits.QuickForm.Element({ type: 'div', id: id + '_' + i + '_subgroup' }); $.each(tmpgroup, (idx, el) => { const newEl = $.extend({}, el); if (!newEl.type) { newEl.type = data.type; } newEl.name = (current.name || data.name) + '.' + newEl.name; subgroupRaw.append(newEl); }); const subgroup = subgroupRaw.render(cur_id); subgroup.className = 'quickformSubgroup'; subnode.subgroup = subgroup; subnode.shown = false; event = function(e) { if (e.target.checked) { e.target.parentNode.appendChild(e.target.subgroup); if (e.target.type === 'radio') { const name = e.target.name; if (e.target.form.names[name] !== undefined) { e.target.form.names[name].parentNode.removeChild(e.target.form.names[name].subgroup); } e.target.form.names[name] = e.target; } } else { e.target.parentNode.removeChild(e.target.subgroup); } }; subnode.addEventListener('change', event, true); if (current.checked) { subnode.parentNode.appendChild(subgroup); } } else if (data.type === 'radio') { event = function(e) { if (e.target.checked) { const name = e.target.name; if (e.target.form.names[name] !== undefined) { e.target.form.names[name].parentNode.removeChild(e.target.form.names[name].subgroup); } delete e.target.form.names[name]; } }; subnode.addEventListener('change', event, true); } // ku dar dhacdada isticmaalayaasha ugu dambayn, si ay ula falgeli karto kooxda hoose (subgroup) if (data.event) { subnode.addEventListener('change', data.event, false); } else if (current.event) { subnode.addEventListener('change', current.event, true); } } } if (data.shiftClickSupport && data.type === 'checkbox') { Morebits.checkboxShiftClickSupport(Morebits.QuickForm.getElements(node, data.name)); } break; // gelintu waa nooc qoraal ah, markaa nambarka halkan wuxuu ka dhaxlaa waxyaabihii la mid ahaa case 'number': case 'input': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('label')); label.appendChild(Morebits.createHtml(data.label)); label.setAttribute('for', data.id || id); label.style.marginRight = '3px'; } subnode = node.appendChild(document.createElement('input')); subnode.setAttribute('name', data.name); if (data.type === 'input') { subnode.setAttribute('type', 'text'); } else { subnode.setAttribute('type', 'number'); ['min', 'max', 'step', 'list'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, data[att]); } }); } ['value', 'size', 'placeholder', 'maxlength'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, data[att]); } }); ['disabled', 'required', 'readonly'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, att); } }); if (data.event) { subnode.addEventListener('input', data.event, false); } childContainer = subnode; break; case 'dyninput': var min = data.min || 1; var max = data.max || Infinity; node = document.createElement('div'); label = node.appendChild(document.createElement('h5')); label.appendChild(Morebits.createHtml(data.label)); var listNode = node.appendChild(document.createElement('div')); var more = this.compute({ type: 'button', label: 'more', disabled: min >= max, event: function(e) { const new_node = new Morebits.QuickForm.Element(e.target.sublist); e.target.area.appendChild(new_node.render()); if (++e.target.counter >= e.target.max) { e.target.setAttribute('disabled', 'disabled'); } e.stopPropagation(); } }); node.appendChild(more[0]); var moreButton = more[1]; var sublist = { type: '_dyninput_row', remove: false, maxlength: data.maxlength, event: data.event, inputs: data.inputs || [{ // waafajinta (compatibility) label: data.sublabel || data.label, name: data.name, value: data.value, size: data.size }] }; for (i = 0; i < min; ++i) { const elem = new Morebits.QuickForm.Element(sublist); listNode.appendChild(elem.render()); } sublist.remove = true; sublist.morebutton = moreButton; sublist.listnode = listNode; moreButton.sublist = sublist; moreButton.area = listNode; moreButton.max = max - min; moreButton.counter = 0; break; case '_dyninput_row': // Gaar ah (Private) node = document.createElement('div'); data.inputs.forEach((subdata) => { const cell = new Morebits.QuickForm.Element($.extend(subdata, { type: '_dyninput_cell' })); node.appendChild(cell.render()); }); if (data.remove) { const remove = this.compute({ type: 'button', label: 'remove', event: function(e) { const list = e.target.listnode; const node = e.target.inputnode; const more = e.target.morebutton; list.removeChild(node); --more.counter; more.removeAttribute('disabled'); e.stopPropagation(); } }); node.appendChild(remove[0]); const removeButton = remove[1]; removeButton.inputnode = node; removeButton.listnode = data.listnode; removeButton.morebutton = data.morebutton; } break; case '_dyninput_cell': // Gaar ah (Private), la mid ah gelinta caadiga ah node = document.createElement('span'); if (data.label) { label = node.appendChild(document.createElement('label')); label.appendChild(document.createTextNode(data.label)); label.setAttribute('for', id + '_input'); label.style.marginRight = '3px'; } subnode = node.appendChild(document.createElement('input')); subnode.setAttribute('id', id + '_input'); if (data.value) { subnode.setAttribute('value', data.value); } subnode.setAttribute('name', data.name); subnode.setAttribute('type', 'text'); subnode.setAttribute('data-dyninput', 'data-dyninput'); if (data.size) { subnode.setAttribute('size', data.size); } if (data.maxlength) { subnode.setAttribute('maxlength', data.maxlength); } if (data.required) { subnode.setAttribute('required', 'required'); } if (data.disabled) { subnode.setAttribute('required', 'disabled'); } if (data.event) { subnode.addEventListener('input', data.event, false); } node.style.marginRight = '3px'; break; case 'hidden': node = document.createElement('input'); node.setAttribute('type', 'hidden'); node.values = data.value; node.setAttribute('value', data.value); node.setAttribute('name', data.name); break; case 'header': node = document.createElement('h5'); node.appendChild(Morebits.createHtml(data.label)); break; case 'div': node = document.createElement('div'); if (data.name) { node.setAttribute('name', data.name); } if (data.label) { const result = document.createElement('span'); result.className = 'quickformDescription'; result.appendChild(Morebits.createHtml(data.label)); node.appendChild(result); } break; case 'submit': node = document.createElement('span'); childContainer = node.appendChild(document.createElement('input')); childContainer.setAttribute('type', 'submit'); if (data.label) { childContainer.setAttribute('value', data.label); } childContainer.setAttribute('name', data.name || 'submit'); if (data.disabled) { childContainer.setAttribute('disabled', 'disabled'); } break; case 'button': node = document.createElement('span'); childContainer = node.appendChild(document.createElement('input')); childContainer.setAttribute('type', 'button'); if (data.label) { childContainer.setAttribute('value', data.label); } childContainer.setAttribute('name', data.name); if (data.disabled) { childContainer.setAttribute('disabled', 'disabled'); } if (data.event) { childContainer.addEventListener('click', data.event, false); } break; case 'textarea': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('h5')); const labelElement = document.createElement('label'); labelElement.appendChild(Morebits.createHtml(data.label)); labelElement.setAttribute('for', data.id || id); label.appendChild(labelElement); } subnode = node.appendChild(document.createElement('textarea')); subnode.setAttribute('name', data.name); if (data.cols) { subnode.setAttribute('cols', data.cols); } if (data.rows) { subnode.setAttribute('rows', data.rows); } if (data.disabled) { subnode.setAttribute('disabled', 'disabled'); } if (data.required) { subnode.setAttribute('required', 'required'); } if (data.readonly) { subnode.setAttribute('readonly', 'readonly'); } if (data.value) { subnode.value = data.value; } childContainer = subnode; break; default: throw new Error('Morebits.QuickForm: unknown element type ' + data.type.toString()); } if (!childContainer) { childContainer = node; } if (data.tooltip) { Morebits.QuickForm.Element.generateTooltip(label || node, data); } if (data.extra) { childContainer.extra = data.extra; } if (data.$data) { $(childContainer).data(data.$data); } if (data.style) { childContainer.setAttribute('style', data.style); } if (data.className) { childContainer.className = childContainer.className ? childContainer.className + ' ' + data.className : data.className; } childContainer.setAttribute('id', data.id || id); return [node, childContainer]; }; Morebits.QuickForm.$tooltip = null; /** * Abuur tilmaam qalab (tooltip). * * @memberof Morebits.QuickForm.Element * @param {HTMLElement} node - Shayga HTML ee agtiisa lagu abuurayo tilmaam qalab. * @param {Object} data - Xogta qaabaynta ee la xiriirta tilmaam qalab. */ Morebits.QuickForm.Element.generateTooltip = function QuickFormElementGenerateTooltip(node, data) { if (!Morebits.QuickForm.$tooltip) { Morebits.QuickForm.$tooltip = $('<div>') .attr('id', 'morebits-ui-tooltip') .attr('role', 'tooltip') .addClass('morebits-ui-tooltip') .appendTo('body'); } const $tooltip = Morebits.QuickForm.$tooltip; const $button = $('<span>') .addClass('morebits-tooltipButton') .text('?') .appendTo(node); $button.on('mouseenter', () => { $tooltip.html(data.tooltip).addClass('visible'); const buttonRect = $button[0].getBoundingClientRect(); const tooltipRect = $tooltip[0].getBoundingClientRect(); const topOffset = buttonRect.bottom + tooltipRect.height < window.innerHeight ? buttonRect.bottom : // Waxay ku habboon tahay xagga sare ee calaamadda su'aasha - geli halkaas Math.max(0, buttonRect.top - tooltipRect.height); // Haddii kale, geli xagga hoose ee calaamadda su'aasha const leftOffset = buttonRect.right + tooltipRect.width < window.innerWidth ? buttonRect.right : // Waxay ku habboon tahay xagga midig ee calaamadda su'aasha - geli halkaas Math.max(0, buttonRect.left - tooltipRect.width); // Haddii kale, geli xagga bidix ee calaamadda su'aasha $tooltip.css('top', window.scrollY + topOffset); $tooltip.css('left', window.scrollX + leftOffset); }).on('mouseleave', () => { $tooltip.removeClass('visible'); }); }; // Hababka qaar ee caawiya ee lagu maamulo quickForms ka dib abuuritaankooda: // (Midkoodna ugama shaqeeyo noocyada goobaha "dyninput" hadda) /** * Waxay soo celinaysaa shay ka kooban dhammaan xogta foomka ee buuxda ee uu geliyay isticmaalahu, iyada oo furayaasha * shaygu ay yihiin magacyada shayga foomka. Goobaha la joojiyay waa la iska indhatiri doonaa, laakiin ma aha goobaha qarsoon. * * @memberof Morebits.QuickForm * @param {HTMLFormElement} form * @return {Object} Iyadoo magacyada goobaha ay yihiin furayaal, xogta gelintuna ay tahay qiimayaal. */ Morebits.QuickForm.getInputData = function(form) { const result = {}; for (let i = 0; i < form.elements.length; i++) { const field = form.elements[i]; if (field.disabled || !field.name || !field.type || field.type === 'submit' || field.type === 'button') { continue; } // Wixii ku jira kooxaha hoose (subgroups), quickform waxay ku darsataa magacyada walxaha // magaca kooxda waalidka oo ay ku xigto dhibic, meesha ka saar taas. const fieldNameNorm = field.name.slice(field.name.indexOf('.') + 1); switch (field.type) { case 'radio': if (field.checked) { result[fieldNameNorm] = field.value; } break; case 'checkbox': if (field.dataset.single) { result[fieldNameNorm] = field.checked; // boolean } else { result[fieldNameNorm] = result[fieldNameNorm] || []; if (field.checked) { result[fieldNameNorm].push(field.value); } } break; case 'select-multiple': result[fieldNameNorm] = $(field).val(); // field.value wax ma tarayo break; case 'text': // hoos ayay ugu dhacdaa case 'textarea': if (field.dataset.dyninput) { result[fieldNameNorm] = result[fieldNameNorm] || []; result[fieldNameNorm].push(field.value.trim()); } else { result[fieldNameNorm] = field.value.trim(); } break; default: // waxay noqon kartaa select-one, date, number, email, iwm if (field.value) { result[fieldNameNorm] = field.value; } break; } } return result; }; /** * Waxay soo celinaysaa dhammaan walxaha foomka ee wata magaca ama aqoonsiga goobta la bixiyay. * * @memberof Morebits.QuickForm * @param {HTMLFormElement} form * @param {string} fieldName - Magaca ama aqoonsiga goobaha. * @return {HTMLElement[]} - Safka walxaha foomka ee u dhigma. */ Morebits.QuickForm.getElements = function QuickFormGetElements(form, fieldName) { const $form = $(form); fieldName = $.escapeSelector(fieldName); // nadiifi gelinta let $elements = $form.find('[name="' + fieldName + '"]'); if ($elements.length > 0) { return $elements.toArray(); } $elements = $form.find('#' + fieldName); return $elements.toArray(); }; /** * Waxay baartaa safka walxaha ee sanduuqa hubinta ama badhanka raadiyaha ee wata sifo gaar ah oo ah * `value`, waxayna soo celinaysaa shayga ugu horreeya ee noocaas ah. Waxay soo celinaysaa null haddii aan la helin. * * @memberof Morebits.QuickForm * @param {HTMLInputElement[]} elementArray - Safka sanduuqa hubinta ama walxaha raadiyaha. * @param {string} value - Qiimaha la raadinayo. * @return {HTMLInputElement} */ Morebits.QuickForm.getCheckboxOrRadio = function QuickFormGetCheckboxOrRadio(elementArray, value) { const found = $.grep(elementArray, (el) => el.value === value); if (found.length > 0) { return found[0]; } return null; }; /** * Waxay soo celinaysaa &lt;div> ka kooban shayga foomka, ama shayga foomka laftiisa * Waxaa laga yaabaa inuusan u shaqayn sidii la filayay sanduuqyada hubinta ama raadiyaha. * * @memberof Morebits.QuickForm * @param {HTMLElement} element * @return {HTMLElement} */ Morebits.QuickForm.getElementContainer = function QuickFormGetElementContainer(element) { // div-yada, madaxyada iyo fieldsets-ka, weelku waa shayga laftiisa if (element instanceof HTMLFieldSetElement || element instanceof HTMLDivElement || element instanceof HTMLHeadingElement) { return element; } // kuwa kalena, kaliya soo celi node-ka waalidka ah return element.parentNode; }; /** * Waxay helaysaa shayga HTML ee ka kooban sumadda shayga foomka la bixiyay * (inta badan isticmaalka gudaha). * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {HTMLElement} */ Morebits.QuickForm.getElementLabelObject = function QuickFormGetElementLabelObject(element) { // badhamada, div-yada iyo madaxyada, sumaddu waxay saaran tahay shayga laftiisa if (element.type === 'button' || element.type === 'submit' || element instanceof HTMLDivElement || element instanceof HTMLHeadingElement) { return element; // fieldsets-ka, sumaddu waa shayga carruurta ah ee <legend> } else if (element instanceof HTMLFieldSetElement) { return element.getElementsByTagName('legend')[0]; // sanduuqyada qoraalka, sumaddu waa shayga walaasha ah ee <h5> } else if (element instanceof HTMLTextAreaElement) { return element.parentNode.getElementsByTagName('h5')[0]; } // kuwa kalena, sumaddu waa shayga walaasha ah ee <label> return element.parentNode.getElementsByTagName('label')[0]; }; /** * Waxay helaysaa qoraalka sumadda ee shayga. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {string} */ Morebits.QuickForm.getElementLabel = function QuickFormGetElementLabel(element) { const labelElement = Morebits.QuickForm.getElementLabelObject(element); if (!labelElement) { return null; } return labelElement.firstChild.textContent; }; /** * Waxay dejinaysaa sumadda shayga qoraalka la bixiyay. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @param {string} labelText * @return {boolean} True haddii ay guulaysatay, false haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.setElementLabel = function QuickFormSetElementLabel(element, labelText) { const labelElement = Morebits.QuickForm.getElementLabelObject(element); if (!labelElement) { return false; } labelElement.firstChild.textContent = labelText; return true; }; /** * Waxay kaydisaa sumadda hadda ee shayga, waxayna si ku-meel-gaar ah u dejinaysaa sumadda qoraalka la bixiyay. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @param {string} temporaryLabelText * @return {boolean} `true` haddii ay guulaysatay, `false` haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.overrideElementLabel = function QuickFormOverrideElementLabel(element, temporaryLabelText) { if (!element.hasAttribute('data-oldlabel')) { element.setAttribute('data-oldlabel', Morebits.QuickForm.getElementLabel(element)); } return Morebits.QuickForm.setElementLabel(element, temporaryLabelText); }; /** * Waxay soo celinaysaa sumadda ay kaydisay overrideElementLabel. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {boolean} True haddii ay guulaysatay, false haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.resetElementLabel = function QuickFormResetElementLabel(element) { if (element.hasAttribute('data-oldlabel')) { return Morebits.QuickForm.setElementLabel(element, element.getAttribute('data-oldlabel')); } return null; }; /** * Waxay soo bandhigaysaa ama qarisaa shay foom ah oo ay la socdaan sumaddiisa iyo tilmaam qalabkiisa. * * @memberof Morebits.QuickForm * @param {(HTMLElement|jQuery|string)} element - Shayga HTML/jQuery, ama xarigga xulashada jQuery. * @param {boolean} [visibility] - Ka bood tan si aad u beddesho muuqashada. */ Morebits.QuickForm.setElementVisibility = function QuickFormSetElementVisibility(element, visibility) { $(element).toggle(visibility); }; /** * Waxay soo bandhigaysaa ama qarisaa astaanta calaamadda su'aasha (taas oo soo bandhigaysa tilmaam qalabka) ee ku xigta shay foom ah. * * @memberof Morebits.QuickForm * @param {(HTMLElement|jQuery)} element * @param {boolean} [visibility] - Ka bood tan si aad u beddesho muuqashada. */ Morebits.QuickForm.setElementTooltipVisibility = function QuickFormSetElementTooltipVisibility(element, visibility) { $(Morebits.QuickForm.getElementContainer(element)).find('.morebits-tooltipButton').toggle(visibility); }; /** * @external HTMLFormElement */ /** * Hel walxaha la hubiyay ee foomka. * * @method external:HTMLFormElement.getChecked * @param {string} name - Hel hantida la hubiyay ee walxaha (tusaale ahaan sanduuqa hubinta * ama badhanka raadiyaha) oo wata magaca la bixiyay, ama dooro xulashooyinka leh selected * oo loo dejiyay true (ha isku dayin inaad isku darto select-yada iyo raadiyaha/sanduuqyada hubinta). * @param {string} [type] - Si ikhtiyaari ah u cayim midkood raadiyaha ama sanduuqa hubinta (waayo * dhacdada ah in labada sanduuq hubinta iyo badhamada raadiyuhu ay leeyihiin magac isku mid ah). * @return {string[]} - Waxa ku jira qiimayaasha walxaha leh magaca la bixiyay * hantida la hubiyay oo loo dejiyay true. */ HTMLFormElement.prototype.getChecked = function(name, type) { const elements = this.elements[name]; if (!elements) { return []; } const return_array = []; let i; if (elements instanceof HTMLSelectElement) { const options = elements.options; for (i = 0; i < options.length; ++i) { if (options[i].selected) { if (options[i].values) { return_array.push(options[i].values); } else { return_array.push(options[i].value); } } } } else if (elements instanceof HTMLInputElement) { if (type && elements.type !== type) { return []; } else if (elements.checked) { return [elements.value]; } } else { for (i = 0; i < elements.length; ++i) { if (elements[i].checked) { if (type && elements[i].type !== type) { continue; } if (elements[i].values) { return_array.push(elements[i].values); } else { return_array.push(elements[i].value); } } } } return return_array; }; /** * Waxay samaysaa sida {@link HTMLFormElement.getChecked|getChecked}, laakiin waxay wadataa walxaha aan la hubin. * * @method external:HTMLFormElement.getUnchecked * @param {string} name - Hel hantida la hubiyay ee walxaha (tusaale ahaan sanduuqa hubinta * ama badhanka raadiyaha) oo wata magaca la bixiyay, ama dooro xulashooyinka leh selected * oo loo dejiyay true (ha isku dayin inaad isku darto select-yada iyo raadiyaha/sanduuqyada hubinta). * @param {string} [type] - Si ikhtiyaari ah u cayim midkood raadiyaha ama sanduuqa hubinta (waayo * dhacdada ah in labada sanduuq hubinta iyo badhamada raadiyuhu ay leeyihiin magac isku mid ah). * @return {string[]} - Waxa ku jira qiimayaasha walxaha leh magaca la bixiyay * hantida la hubiyay oo loo dejiyay true. */ HTMLFormElement.prototype.getUnchecked = function(name, type) { const elements = this.elements[name]; if (!elements) { return []; } const return_array = []; let i; if (elements instanceof HTMLSelectElement) { const options = elements.options; for (i = 0; i < options.length; ++i) { if (!options[i].selected) { if (options[i].values) { return_array.push(options[i].values); } else { return_array.push(options[i].value); } } } } else if (elements instanceof HTMLInputElement) { if (type && elements.type !== type) { return []; } else if (!elements.checked) { return [elements.value]; } } else { for (i = 0; i < elements.length; ++i) { if (!elements[i].checked) { if (type && elements[i].type !== type) { continue; } if (elements[i].values) { return_array.push(elements[i].values); } else { return_array.push(elements[i].value); } } } } return return_array; }; /** * Qalab gacan ka geysta habaynta ciwaanada IP-ga. * * @namespace Morebits.ip * @memberof Morebits */ Morebits.ip = { /** * Waxay u beddeshaa ciwaanka IPv6 qaabka caadiga ah ee uu kaydiyo oo uu isticmaalo MediaWiki. * Turjumaadda JavaScript ee {@link https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/8eb6ac3e84ea3312d391ca96c12c49e3ad0753bb/includes/utils/IP.php#131|`IP::sanitizeIP()`} * shaqada ka timid maktabadda IPUtils. Ciwaanradu waa kuwo faahfaahsan, xarfaha waaweyn, * la caadiyeeyay, oo lagu ballaariyay 8 eray. * * @param {string} address - Ciwaanka IPv6, oo wata ama aan wadan CIDR. * @return {string} */ sanitizeIPv6: function(address) { address = address.trim(); if (address === '') { return null; } if (!mw.util.isIPv6Address(address, true)) { return address; // wax kale oo la sameeyo ma jiraan ciwaannada IPv4 ama kuwa aan ansax ahayn } // Meesha ka saar wax kasta oo bannaan, u beddel xarfaha waaweyn address = address.toUpperCase(); // Ballaari gaabinta eber-ka const abbrevPos = address.indexOf('::'); if (abbrevPos > -1) { // Waan ognahay in tani ay tahay IPv6 ansax ah. Hel tusmada ugu dambeysa ee // ciwaanka ka hor nambar kasta oo CIDR ah (tusaale "a:b:c::/24"). const CIDRStart = address.indexOf('/'); const addressEnd = CIDRStart !== -1 ? CIDRStart - 1 : address.length - 1; // Haddii '::' ay ku taal bilowga... let repeat, extra, pad; if (abbrevPos === 0) { repeat = '0:'; extra = address === '::' ? '0' : ''; // ciwaanka '::' pad = 9; // 7+2 (oo ay sabab u tahay '::') // Haddii '::' ay ku taal dhammaadka... } else if (abbrevPos === (addressEnd - 1)) { repeat = ':0'; extra = ''; pad = 9; // 7+2 (oo ay sabab u tahay '::') // Haddii '::' ay ku taal dhexda... } else { repeat = ':0'; extra = ':'; pad = 8; // 6+2 (oo ay sabab u tahay '::') } let replacement = repeat; pad -= address.split(':').length - 1; for (let i = 1; i < pad; i++) { replacement += repeat; } replacement += extra; address = address.replace('::', replacement); } // Ka saar eberrada hordhaca ah ee baloog kasta sida loo baahdo return address.replace(/(^|:)0+([0-9A-Fa-f]{1,4})/g, '$1$2'); }, /** * Go'aami haddii ciwaanka IP-ga la bixiyay uu yahay kala duwanaansho (range). Kaliya waxay ku xiraysaa * `mw.util.isIPAddress` iyada oo wadata iyo iyada oo aan wadan ikhtiyaarka `allowBlock`. * * @param {string} ip * @return {boolean} - True haddii la bixiyay kala duwanaansho ciwaan IP oo ansax ah, false haddii kale. */ isRange: function(ip) { return mw.util.isIPAddress(ip, true) && !mw.util.isIPAddress(ip); }, /** * Hubi in kala duwanaanshiyaha IP-ga uu ku jiro xadka CIDR. Inta badan waxay noqon kartaa mid faa'iido leh * iyada oo lala kaashanayo `wgRelevantUserName`. Xadka CIDR waxaa si adag loogu qeexay /16 * ee IPv4 iyo /32 ee IPv6. * * @return {boolean} - True ee kala duwanaanshiyaha ansaxa ah ee ku dhex jira xadka CIDR, * haddii kale false (kala duwanaanshiyaha ka baxsan xadka, hal IPs, aan ahayn IPs). */ validCIDR: function(ip) { if (Morebits.ip.isRange(ip)) { const subnet = parseInt(ip.match(/\/(\d{1,3})$/)[1], 10); if (subnet) { // Waa inay noqotaa mid xad-dhaaf ah if (mw.util.isIPv6Address(ip, true)) { if (subnet >= 32) { return true; } } else { if (subnet >= 16) { return true; } } } } return false; }, /** * Hel /64 subnet ee ciwaanka IPv6. * * @param {string} ipv6 - Ciwaanka IPv6, oo wata ama aan wadan subnet. * @return {boolean|string} - False haddii uusan ahayn IPv6 ama uu ka weyn yahay 64, * haddii kale ciwaanka /64 (ee la nadiifiyey). */ get64: function(ipv6) { if (!ipv6 || !mw.util.isIPv6Address(ipv6, true)) { return false; } const subnetMatch = ipv6.match(/\/(\d{1,3})$/); if (subnetMatch && parseInt(subnetMatch[1], 10) < 64) { return false; } ipv6 = Morebits.ip.sanitizeIPv6(ipv6); const ip_re = /^((?:[0-9A-F]{1,4}:){4})(?:[0-9A-F]{1,4}:){3}[0-9A-F]{1,4}(?:\/\d{1,3})?$/; // eslint-disable-next-line no-useless-concat return ipv6.replace(ip_re, '$1' + '0:0:0:0/64'); } }; /** * Shaqooyin caawiye ah si loo maamulo xargaha (strings). * * @namespace Morebits.string * @memberof Morebits */ Morebits.string = { /** * @param {string} str * @return {string} */ toUpperCaseFirstChar: function(str) { str = str.toString(); return str.slice(0, 1).toUpperCase() + str.slice(1); }, /** * @param {string} str * @return {string} */ toLowerCaseFirstChar: function(str) { str = str.toString(); return str.slice(0, 1).toLowerCase() + str.slice(1); }, /** * Waxay bixisaa safka xargaha hoose (substrings) ee `str` - ka bilaabmaya `start` iyo * ku dhammaanaya `end` - kaas oo aan ku jirin `skiplist`. Waxaa loogu talagalay in lagu isticmaalo * wikitext-ka leh qaababka (templates) ama xiriirinta. * * @param {string} str * @param {string} start * @param {string} end * @param {(string[]|string)} [skiplist] * @return {string[]} * @throws {Error} Haddii `start` iyo `end` xarguhu aysan ahayn dherer isku mid ah. * @throws {Error} Haddii `skiplist` uusan ahayn saf ama xarig */ splitWeightedByKeys: function(str, start, end, skiplist) { if (start.length !== end.length) { throw new Error('calaamadda bilowga iyo calaamadda dhammaadka waa inay ahaadaan dherer isku mid ah'); } let level = 0; let initial = null; const result = []; if (!Array.isArray(skiplist)) { if (skiplist === undefined) { skiplist = []; } else if (typeof skiplist === 'string') { skiplist = [skiplist]; } else { throw new Error('beegsiga skiplist ee aan khusayn'); } } for (let i = 0; i < str.length; ++i) { for (let j = 0; j < skiplist.length; ++j) { if (str.substr(i, skiplist[j].length) === skiplist[j]) { i += skiplist[j].length - 1; continue; } } if (str.substr(i, start.length) === start) { if (initial === null) { initial = i; } ++level; i += start.length - 1; } else if (str.substr(i, end.length) === end) { --level; i += end.length - 1; } if (!level && initial !== null) { result.push(str.substring(initial, i + 1)); initial = null; } } return result; }, /** * Waxay qaabaysaa "sababta" xorta ah (ee ka timid sanduuqa qoraalka) tirtiridda/qaababka kale * ee beddelka noqon doona, (tusaale PROD, XFD, RPP). * Waxay maamushaa `|` oo ka baxsan calaamadda nowiki. * Ikhtiyaar ahaan, waxay sidoo kale ku dartaa saxiix haddii uusan horay u jirin. * * @param {string} str * @param {boolean} [addSig] * @return {string} */ formatReasonText: function(str, addSig) { let reason = (str || '').toString().trim(); const unbinder = new Morebits.Unbinder(reason); // eslint-disable-next-line no-useless-concat unbinder.unbind('<no' + 'wiki>', '</no' + 'wiki>'); unbinder.content = unbinder.content.replace(/\|/g, '|'); reason = unbinder.rebind(); if (addSig) { const sig = '[[User:Isma4l|Isma4l]] ([[User talk:Isma4l|wadahadal]]) 16:53, 28 Oktoobar 2026 (UTC)', sigIndex = reason.lastIndexOf(sig); if (sigIndex === -1 || sigIndex !== reason.length - sig.length) { reason += ' ' + sig; } } return reason.trim(); }, /** * Waxay qaabaysaa "sabab" (ee ka timid sanduuqa qoraalka) si loogu daro log-ga meesha isticmaalaha (userspace). * Waxay ku beddeshaa xariiqyada cusub {{Pb}}, waxayna ku dartaa `#` dheeri ah kahor * walxaha liiska si loo helo qaabayn habboon. * * @param {string} str * @return {string} */ formatReasonForLog: function(str) { return str // maamul jabitaanka xariiqyada, kuwaas oo haddii kale jebin lahaa nambarka .replace(/\n+/g, '{{pb}}') // geli # dheeri ah hortaada ka hor walxaha liiska calaamadaysan ama la nambareeyay .replace(/^(#+)/mg, '#$1') .replace(/^(\*+)/mg, '#$1'); }, /** * Sida `String.prototype.replace()`, laakiin waxay ka baxsataa astaamaha dollar-ka ee * xarigga beddelka. Faa'iido leh marka xarigga beddelku yahay 4 * mid aan la cayimin, sida magaca isticmaalaha ama gelinta isticmaalaha ee xorta ah, oo ay ku jiri karaan * astaamaha dollar-ka. * * @param {string} string - Qoraalka lagu beddelayo. * @param {(string|RegExp)} pattern * @param {string} replacement * @return {string} */ safeReplace: function morebitsStringSafeReplace(string, pattern, replacement) { return string.replace(pattern, replacement.replace(/\$/g, '$$$$')); }, /** * Go'aami haddii dhicitaanka uu bixiyay isticmaalahu loo tixgelin doono mid * aan xad lahayn (infinite) MW. * * @see {@link https://phabricator.wikimedia.org/T68646} * * @param {string} expiry * @return {boolean} */ isInfinity: function morebitsStringIsInfinity(expiry) { return ['indefinite', 'infinity', 'infinite', 'never'].includes(expiry); }, /** * Waxay ka baxsataa xarig si loogu isticmaalo RegExp, iyada oo ku beddeshay meelaha bannaan iyo * hooseeyayaasha `[_ ]` maadaama inta badan ay yihiin kuwo isu eg. * * @param {string} text - Xarigga laga baxsanayo. * @return {string} - Qoraalka ka baxsaday. */ escapeRegExp: function(text) { return mw.util.escapeRegExp(text).replace(/ |_/g, '[_ ]'); } }; /** * Shaqooyin caawiye ah si loo maamulo safafka (arrays). * * @namespace Morebits.array * @memberof Morebits */ Morebits.array = { /** * Ka saar walxaha laba-laabantay (duplication) safka. * * @param {Array} arr * @return {Array} Nuqul ka mid ah safka oo laga saaray walxaha laba-laabantay. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ uniq: function(arr) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.uniq'); } return arr.filter((item, idx) => arr.indexOf(item) === idx); }, /** * Ka saar walxaha aan laba-laabnayn safka. * * @param {Array} arr * @return {Array} Nuqul ka mid ah safka oo ay ka saaran tahay tusaalaha ugu horreeya ee qiime kasta * oo la saaray; tusaalooyinka xiga ee qiimayaashaas (duplication) ayaa haraya. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ dups: function(arr) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.dups'); } return arr.filter((item, idx) => arr.indexOf(item) !== idx); }, /** * U qaybi saf safaf yar yar. * * @param {Array} arr * @param {number} size - Cabbirka xabbo kasta (marka laga reebo tan ugu dambeysa, oo noqon karta mid ka duwan). * @return {Array[]} Saf ka kooban safafka yar yar ee la jajabiyey. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ chunk: function(arr, size) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.chunk'); } if (typeof size !== 'number' || size <= 0) { // ku dhowaad suurtogal ma aha in la sameeyo wax :) return [arr]; // waxaan soo celinaa saf ka kooban safkan. } const numChunks = Math.ceil(arr.length / size); const result = new Array(numChunks); for (let i = 0; i < numChunks; i++) { result[i] = arr.slice(i * size, (i + 1) * size); } return result; } }; /** * Qalab kor u qaadaya menu-yada select2. Eeg twinklewarn, twinklexfd, * twinkleblock tusaalooyinka isticmaalka. * * @see {@link https://select2.org/} * * @namespace Morebits.select2 * @memberof Morebits * @requires jQuery.select2 */ Morebits.select2 = { matchers: { /** * Qalab waafajiye gaar ah oo haddii magaca optgroup uu waafaqo, dhammaan xulashooyinka kooxdaas * la tusi doono, sida jquery.chosen. */ optgroupFull: function(params, data) { const originalMatcher = $.fn.select2.defaults.defaults.matcher; const result = originalMatcher(params, data); if (result && params.term && data.text.toUpperCase().includes(params.term.toUpperCase())) { result.children = data.children; } return result; }, /** Qalab waafajiye gaar ah oo ka bilaabma bilowga erayada kaliya. */ wordBeginning: function(params, data) { const originalMatcher = $.fn.select2.defaults.defaults.matcher; const result = originalMatcher(params, data); if (!params.term || (result && new RegExp('\\b' + mw.util.escapeRegExp(params.term), 'i').test(result.text))) { return result; } return null; } }, /** Hoose ka xariiq qaybta la waafajiyay ee xulashooyinka. */ highlightSearchMatches: function(data) { const searchTerm = Morebits.select2SearchQuery; if (!searchTerm || data.loading) { return data.text; } const idx = data.text.toUpperCase().indexOf(searchTerm.toUpperCase()); if (idx < 0) { return data.text; } return $('<span>').append( data.text.slice(0, idx), $('<span>').css('text-decoration', 'underline').text(data.text.slice(idx, idx + searchTerm.length)), data.text.slice(idx + searchTerm.length) ); }, /** Dhexgal su'aasha inta ay dhacayso, si loogu isticmaalo highlightSearchMatches. */ queryInterceptor: function(params) { Morebits.select2SearchQuery = params && params.term; }, /** * Fur liiska hoos-u-dhaca oo billow raadinta marka `.select2-selection` uu leeyahay * diiradda (focus) oo furaha la riixo. * * @see {@link https://github.com/select2/select2/issues/3279#issuecomment-442524147} */ autoStart: function(ev) { if (ev.which < 48) { return; } let $target = $(ev.target).closest('.select2-container'); if (!$target.length) { return; } $target = $target.prev(); $target.select2('open'); const search = $target.data('select2').dropdown.$search || $target.data('select2').selection.$search; // Isticmaal DOM .focus() si aad uga gudubto dib-u-dhaca jQuery 3.6.0 (https://github.com/select2/select2/issues/5993) search[0].focus(); } }; /** * Si ku-meel-gaar ah u qari qayb ka mid ah xarigga inta aad ka shaqaynayso inta kale. * Waxaa isticmaala {@link Morebits.wikitext.Page#commentOutImage|Morebits.wikitext.Page.commentOutImage}. * * @memberof Morebits * @class * @param {string} string - Qoraalka bilowga ah ee la shaqaynayo. * @example var u = new Morebits.Unbinder('Hello world <!-- world --> world'); * u.unbind('<!--', '-->'); // qoraalka ku jira faallada wuu ahaanayaa sidii * u.content = u.content.replace(/world/g, 'earth'); * u.rebind(); // wuxuu bixiyaa 'Hello earth <!-- world --> earth' */ Morebits.Unbinder = function Unbinder(string) { if (typeof string !== 'string') { throw new Error('ma ahan xarig'); } /** Qoraalka la shaqaynayo. */ this.content = string; this.counter = 0; this.history = {}; this.prefix = '%UNIQ::' + Math.random() + '::'; this.postfix = '::UNIQ%'; }; Morebits.Unbinder.prototype = { /** * Qari goobta ay xireen `prefix` iyo `postfix` habaynta xarigga. * `prefix` iyo `postfix` waxaa loo isticmaali doonaa RegExp, markaas * walxaha u baahan in laga baxsado waa inay isticmaalaan `\\`. * * @param {string} prefix * @param {string} postfix * @throws {Error} Haddii midkood `prefix` ama `postfix` uu maqanyahay. */ unbind: function UnbinderUnbind(prefix, postfix) { if (!prefix || !postfix) { throw new Error('Labadaba prefix iyo postfix waa in la bixiyaa'); } const re = new RegExp(prefix + '([\\s\\S]*?)' + postfix, 'g'); this.content = this.content.replace(re, Morebits.Unbinder.getCallback(this)); }, /** * Soo celi qaybta qarsoon ee xarigga `content`. * * @return {string} Wax-soo-saarka la habeeyey. */ rebind: function UnbinderRebind() { let content = this.content; content.self = this; for (const current in this.history) { if (Object.prototype.hasOwnProperty.call(this.history, current)) { content = content.replace(current, this.history[current]); } } return content; }, prefix: null, // %UNIQ::0.5955981644938324:: postfix: null, // ::UNIQ% content: null, // string counter: null, // 0++ history: null // {} }; /** @memberof Morebits.Unbinder */ Morebits.Unbinder.getCallback = function UnbinderGetCallback(self) { return function UnbinderCallback(match) { const current = self.prefix + self.counter + self.postfix; self.history[current] = match; ++self.counter; return current; }; }; /* **************** Morebits.Date **************** */ /** * Abuur shay taariikh ah oo wata awoodaha habaynta ee la xoojiyay, a la * {@link https://momentjs.com/|moment.js}. Qaabka waqti-shaabadeedka MediaWiki sidoo kale waa * mid la aqbali karo, marka lagu daro wax walba oo ay aqbasho JS Date(). * * @memberof Morebits * @class */ Morebits.Date = class extends Date { constructor(...args) { // Hubi qaababka MediaWiki // Waa inuu noqdaa kan ugu horreeya maadaama firefox uu si khaldan u aqbalayo qaabka waqti-shaabadeedka, // iyada oo aan la haysan aagga wakhtiga (Sidoo kale eeg: #921, #936, #1174, #1187), iyo // xarigga 14-ka nambar ah ayaa loo tarjumi doonaa si ka duwan. if (args.length === 1) { const param = args[0]; if (/^\d{14}$/.test(param)) { // YYYYMMDDHHmmss const digitMatch = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(param); if (digitMatch) { // ..... sanadka ... bisha .. taariikhda ... saacada .... daqiiqada ..... ilbiriqsiga super(Date.UTC(digitMatch[1], digitMatch[2] - 1, digitMatch[3], digitMatch[4], digitMatch[5], digitMatch[6])); } else { super(...args); } } else if (typeof param === 'string') { // Waqti-shaabadeedka saxiixa Wikitext const dateParts = Morebits.l10n.signatureTimestampFormat(param); if (dateParts) { super(Date.UTC(...dateParts)); } else { super(...args); } } else { super(...args); } } else { super(...args); } if (!this.isValid()) { mw.log.warn('Billaabidda Morebits.Date ee aan ansax ahayn:', args); } } /** @return {boolean} */ isValid() { return !isNaN(this.getTime()); } /** * @param {(Date|Morebits.Date)} date * @return {boolean} */ isBefore(date) { return this.getTime() < date.getTime(); } /** * @param {(Date|Morebits.Date)} date * @return {boolean} */ isAfter(date) { return this.getTime() > date.getTime(); } /** @return {string} */ getUTCMonthName() { return Morebits.Date.localeData.months[this.getUTCMonth()]; } /** @return {string} */ getUTCMonthNameAbbrev() { return Morebits.Date.localeData.monthsShort[this.getUTCMonth()]; } /** @return {string} */ getMonthName() { return Morebits.Date.localeData.months[this.getMonth()]; } /** @return {string} */ getMonthNameAbbrev() { return Morebits.Date.localeData.monthsShort[this.getMonth()]; } /** @return {string} */ getUTCDayName() { return Morebits.Date.localeData.days[this.getUTCDay()]; } /** @return {string} */ getUTCDayNameAbbrev() { return Morebits.Date.localeData.daysShort[this.getUTCDay()]; } /** @return {string} */ getDayName() { return Morebits.Date.localeData.days[this.getDay()]; } /** @return {string} */ getDayNameAbbrev() { return Morebits.Date.localeData.daysShort[this.getDay()]; } /** * Ku dar tiro la bixiyay oo ah daqiiqado, saacado, maalmo, toddobaadyo, bilo, ama sano taariikhda. * Tani waxaa lagu sameeyaa halkii ay taallay (in-place). Shayga taariikhda ee la beddelay ayaa sidoo kale la soo celinayaa, taasoo u oggolaanaysa silsilad (chaining). * * @param {number} number - Waa inuu noqdaa nambar buuxa (integer). * @param {string} unit * @throws {Error} Haddii unug aan ansax ahayn ama aan la taageerin la bixiyo. * @return {Morebits.Date} */ add(number, unit) { let num = parseInt(number, 10); // caadiye if (isNaN(num)) { throw new Error('Nambar aan ansax ahayn "' + number + '" ayaa la bixiyay.'); } unit = unit.toLowerCase(); // caadiye const unitMap = Morebits.Date.unitMap; let unitNorm = unitMap[unit] || unitMap[unit + 's']; // si labada qaab ee kelidii ah iyo wadarta ah ay u shaqeeyaan if (unitNorm) { // Ma jiraan shaqooyin usbuuc oo ku dhex dhis an, markaa halkii aad ka dhisi lahayd getWeek/setWeek ee ISO, kaliya dhufo // Malaha looma isticmaali karo isbeddellada Julian->Gregorian, iwm. if (unitNorm === 'Week') { unitNorm = 'Date'; num *= 7; } this['set' + unitNorm](this['get' + unitNorm]() + num); return this; } throw new Error('Unug aan ansax ahayn "' + unit + '": Kaliya ' + Object.keys(unitMap).join(', ') + ' ayaa la oggol yahay.'); } /** * Ka jar tiro la bixiyay oo ah daqiiqado, saacado, maalmo, toddobaadyo, bilo, ama sano taariikhda. * Tani waxaa lagu sameeyaa halkii ay taallay (in-place). Shayga taariikhda ee la beddelay ayaa sidoo kale la soo celinayaa, taasoo u oggolaanaysa silsilad (chaining). * * @param {number} number - Waa inuu noqdaa nambar buuxa (integer). * @param {string} unit * @throws {Error} Haddii unug aan ansax ahayn ama aan la taageerin la bixiyo. * @return {Morebits.Date} */ subtract(number, unit) { return this.add(-number, unit); } /** * Qaabee taariikhda oo ka dhig xarig iyadoo loo eegayo xarigga qaabka la bixiyay. * Sintakiska beddelka waa qayb ka mid ah kan ku jira moment.js: * * | Sintakiska | Wax-soo-saarka | * |------------|-----------------| * | H | Saacadaha (24-saacadood) | * | HH | Saacadaha (24-saacadood, oo lagu buuxiyay 2 nambar) | * | h | Saacadaha (12-saacadood) | * | hh | Saacadaha (12-saacadood, oo lagu buuxiyay 2 nambar) | * | A | AM ama PM | * | m | Daqiiqadaha | * | mm | Daqiiqadaha (oo lagu buuxiyay 2 nambar) | * | s | Ilbiriqisyada | * | ss | Ilbiriqisyada (oo lagu buuxiyay 2 nambar) | * | SSS | Jajabka millisekunde, 3 nambar | * | d | Nambarka maalinta ee usbuuca (Sun=0) | * | ddd | Magaca maalinta oo gaaban | * | dddd | Magaca maalinta oo buuxa | * | D | Taariikhda | * | DD | Taariikhda (oo lagu buuxiyay 2 nambar) | * | M | Nambarka bisha (1-indexed) | * | MM | Nambarka bisha (1-indexed, oo lagu buuxiyay 2 nambar) | * | MMM | Magaca bisha oo gaaban | * | MMMM | Magaca bisha oo buuxa | * | Y | Sanadka | * | YY | Labada nambar ee ugu dambeeya sanadka (20 sanadka 2020, 42 sanadka 1942) | * | YYYY | Sanadka (la mid ah `Y`) | * * @param {string} formatstr - Qaabee taariikhda oo ka dhig xarig, adigoo isticmaalaya * sintakiska beddelka. Isticmaal `[` iyo `]` si aad uga baxsatid walxaha. Haddii aan la bixin, * waxay soo celin doontaa xarigga ISO-8601-formatted. * @param {(string|number)} [zone=system] - `system` (aagga wakhtiga caadiga ah ee daalacashada), * `utc`, ama cayim aag wakhti oo ah lambarka daqiiqadaha ee qaraabada la ah UTC. * @return {string} */ format(formatstr, zone) { if (!this.isValid()) { return 'Taariikh aan ansax ahayn'; // Soo saar runta, waxay ka fiican tahay "NaNNaNNan NaN:NaN" ama wixii la mid ah } let udate = this; // abuur shay taariikh cusub oo ka koobnaan doona taariikhda lagu soo bandhigayo wakhtiga nidaamka if (zone === 'utc') { udate = new Morebits.Date(this.getTime()).add(this.getTimezoneOffset(), 'minutes'); } else if (typeof zone === 'number') { // u beddel utc, ka dibna ku dar cilladda utc ee la bixiyay udate = new Morebits.Date(this.getTime()).add(this.getTimezoneOffset() + zone, 'minutes'); } // u deji ISOString haddii aysan jirin if (!formatstr) { return udate.toISOString(); } const pad = function(num, len) { len = len || 2; // Ilaa dhererka 00 + 1 return ('00' + num).toString().slice(0 - len); }; const h24 = udate.getHours(), m = udate.getMinutes(), s = udate.getSeconds(), ms = udate.getMilliseconds(); const D = udate.getDate(), M = udate.getMonth() + 1, Y = udate.getFullYear(); const h12 = h24 % 12 || 12, amOrPm = h24 >= 12 ? 'PM' : 'AM'; const replacementMap = { HH: pad(h24), H: h24, hh: pad(h12), h: h12, A: amOrPm, mm: pad(m), m: m, ss: pad(s), s: s, SSS: pad(ms, 3), dddd: udate.getDayName(), ddd: udate.getDayNameAbbrev(), d: udate.getDay(), DD: pad(D), D: D, MMMM: udate.getMonthName(), MMM: udate.getMonthNameAbbrev(), MM: pad(M), M: M, YYYY: Y, YY: pad(Y % 100), Y: Y }; const unbinder = new Morebits.Unbinder(formatstr); // ka baxsashada waxyaabaha u dhexeeya [...] unbinder.unbind('\\[', '\\]'); unbinder.content = unbinder.content.replace( /* Qoraallada Regex: * d(d{2,3})? wuxuu la mid yahay si sax ah 1, 3 ama 4 dhacdo oo ah 'd' ('dd' waxaa Loo tixgeliyaa inay tahay laba-laabashada 'd') * Y{1,2}(Y{2})? wuxuu la mid yahay si sax ah 1, 2 ama 4 dhacdo oo ah 'Y' */ /H{1,2}|h{1,2}|m{1,2}|s{1,2}|SSS|d(d{2,3})?|D{1,2}|M{1,4}|Y{1,2}(Y{2})?|A/g, (match) => replacementMap[match] ); return unbinder.rebind().replace(/\[(.*?)\]/g, '$1'); } /** * Waxay bixisaa xarig wakhti qaraabo ah oo akhriska ku fiican sida "Shalay 6:43 PM" ama "Khamiistii la soo dhaafay 11:45 AM". * Sida `calendar` ee moment.js, laakiin wata taageerada aagga wakhtiga. * * @param {(string|number)} [zone=system] - 'system' (aagga wakhtiga caadiga ah ee daalacashada), * 'utc' (ee UTC), ama cayim aag wakhti oo ah nambarka daqiiqadaha ka dambeeya UTC. * @return {string} */ calendar(zone) { // Ebar ka dhig saacadaha, daqiiqadaha, ilbiriqisyada iyo millisekundisyada - adigoo ilaalinaya taariikhda oo keliya; // hel farqiga. Xusuusnow in setHours() ay soo celinays驮 wax la mid ah getTime(). const dateDiff = (new Date().setHours(0, 0, 0, 0) - new Date(this).setHours(0, 0, 0, 0)) / 8.64e7; switch (true) { case dateDiff === 0: return this.format(Morebits.Date.localeData.relativeTimes.thisDay, zone); case dateDiff === 1: return this.format(Morebits.Date.localeData.relativeTimes.prevDay, zone); case dateDiff > 0 && dateDiff < 7: return this.format(Morebits.Date.localeData.relativeTimes.pastWeek, zone); case dateDiff === -1: return this.format(Morebits.Date.localeData.relativeTimes.nextDay, zone); case dateDiff < 0 && dateDiff > -7: return this.format(Morebits.Date.localeData.relativeTimes.thisWeek, zone); default: return this.format(Morebits.Date.localeData.relativeTimes.other, zone); } } /** * Hel tibaax joogto ah (regular expression) oo la mid ah cinwaannada qaybaha wikitext, sida * `==December 2019==` ama `=== Jan 2018 ===`. * * @return {RegExp} */ monthHeaderRegex() { return new RegExp('^(==+)\\s*(?:' + this.getUTCMonthName() + '|' + this.getUTCMonthNameAbbrev() + ')\\s+' + this.getUTCFullYear() + '\\s*\\1', 'mg'); } /** * Waxay abuurtaa cinwaan qayb wikitext ah oo wata bisha iyo sanadka. * * @param {number} [level=2] - Heerka cinwaanka. Gudbi 0 si aad u hesho qoraalka oo keliya * iyada oo aan lahayn calaamado wikitext ah (==). * @return {string} */ monthHeader(level) { // U deji 2, laakiin u oggolow 0 ama nambarada xarigga ah level = parseInt(level, 10); level = isNaN(level) ? 2 : level; const header = '='.repeat(level); const text = this.getUTCMonthName() + ' ' + this.getUTCFullYear(); if (header.length) { // cinwaan wikitext-format ah return header + ' ' + text + ' ' + header; } return text; // Qoraalka oo keliya } }; /** * Xargaha deegaanka ee habaynta taariikhda. * * @memberof Morebits.Date * @type {object.<string, string>} * @property {string[]} months * @property {string[]} monthsShort * @property {string[]} days * @property {string[]} daysShort * @property {object.<string, string>} relativeTimes * @private */ Morebits.Date.localeData = { // magacyada fariimaha halkan waxay u dhigmaan magacyada fariimaha MediaWiki months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], relativeTimes: { thisDay: '[Today at] h:mm A', prevDay: '[Yesterday at] h:mm A', nextDay: '[Tomorrow at] h:mm A', thisWeek: 'dddd [at] h:mm A', pastWeek: '[Last] dddd [at] h:mm A', other: 'YYYY-MM-DD' } }; /** * Khariidadee unugyada magacyada shaqada ee getter/setter, ee loogu talagalay hababka `add` iyo `subtract`. * * @memberof Morebits.Date * @type {object.<string, string>} * @property {string} seconds * @property {string} minutes * @property {string} hours * @property {string} days * @property {string} weeks * @property {string} months * @property {string} years */ Morebits.Date.unitMap = { seconds: 'Seconds', minutes: 'Minutes', hours: 'Hours', days: 'Date', weeks: 'Week', // Ma aha shaqo laakiin waxaa lagu maamulaa `add` iyada oo la adeegsanayo dhu-dhufasho xariif ah months: 'Month', years: 'FullYear' }; /* **************** Morebits.wiki **************** */ /** * Shayada kala duwan ee wax ka beddelka wiki iyo helitaanka API, oo ay ku jiraan * {@link Morebits.wiki.Api} iyo {@link Morebits.wiki.Page}. * * @namespace Morebits.wiki * @memberof Morebits */ Morebits.wiki = {}; /* **************** Morebits.wiki.actionCompleted **************** */ /** * @memberof Morebits.wiki * @type {number} */ Morebits.wiki.numberOfActionsLeft = 0; /** * @memberof Morebits.wiki * @type {number} */ Morebits.wiki.nbrOfCheckpointsLeft = 0; /** * Soo bandhig fariin iyo/ama u gudub bogga marka hawlaha la dhammeeyo. * * Wicitaan kasta oo loo sameeyo Morebits.wiki.Api.post() wuxuu keenaa dirista jawaab celin * asynchronous ah. Jawaab celin kastaa waxay iyaduna samayn kartaa wicitaan dheeri ah oo ku socda * Morebits.wiki.Api.post() si loo sii wado silsiladda habaynta. Gabagabada * jawaab-celinta ugu dambeysa ee silsiladda habaynta, suurtogal ma aha * in si fudud loogu noqdo qofkii wacay ee asalka ahaa sababtoo ah ma jiro xiriir wicitaan * oo dib ugu geynaya xaaladdii asalka ahayd. Halkaas waxaa lagu wacaa * Morebits.wiki.actionCompleted.event() si loo soo bandhigo natiijada isticmaalaha * iyo in la fuliyo leexinta bogga ikhtiyaariga ah. * * Go'aaminta goorta la wacayo Morebits.wiki.actionCompleted.event() waxaa * maamula doorsoomayaasha caalamiga ah Morebits.wiki.numberOfActionsLeft iyo * Morebits.wiki.nbrOfCheckpointsLeft. Morebits.wiki.numberOfActionsLeft waxaa la kordhiyaa * bilowga wicitaan kasta oo Morebits.wiki.Api ah waxaana laga dhimayaa * marka la dhammeeyo shaqada jawaab-celinta. Haddii shaqada jawaab-celintu * aysan abuurin shay cusub oo Morebits.wiki.Api ah ka hor inta aysan bixin, waa * tillaabada ugu dambeysa ee silsiladda habaynta waxaana la wici doonaa Morebits.wiki.actionCompleted.event(). * * Ikhtiyaar ahaan, kuwa waca waxay isticmaali karaan Morebits.wiki.addCheckpoint() si ay u muujiyaan * in habayntu aysan dhammaystirnayn gabagabada shaqada jawaab-celinta * ugu dambeysa. Tani waxaa loo isticmaalaa hawlaha xirmada (batch). Dhamaadka xirmada * waxaa lagu calaamadiyaa iyadoo la wacayo Morebits.wiki.removeCheckpoint(). * * @memberof Morebits.wiki */ Morebits.wiki.actionCompleted = function(self) { if (--Morebits.wiki.numberOfActionsLeft <= 0 && Morebits.wiki.nbrOfCheckpointsLeft <= 0) { Morebits.wiki.actionCompleted.event(self); } }; // Beddel falka la rabo /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.event = function() { if (Morebits.wiki.actionCompleted.notice) { Morebits.Status.actionCompleted(Morebits.wiki.actionCompleted.notice); } if (Morebits.wiki.actionCompleted.redirect) { // haddii uusan ahaan URL, ka dhig mid. Tusaale: Tani waxay ka jabtaa maqaallada 'http://', 'ftp://', iyo kuwa la mid ah. if (!(/^\w+:\/\//).test(Morebits.wiki.actionCompleted.redirect)) { Morebits.wiki.actionCompleted.redirect = mw.util.getUrl(Morebits.wiki.actionCompleted.redirect); if (Morebits.wiki.actionCompleted.followRedirect === false) { Morebits.wiki.actionCompleted.redirect += '?redirect=no'; } } window.setTimeout(() => { window.location = Morebits.wiki.actionCompleted.redirect; }, Morebits.wiki.actionCompleted.timeOut); } }; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.timeOut = typeof window.wpActionCompletedTimeOut === 'undefined' ? 5000 : window.wpActionCompletedTimeOut; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.redirect = null; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.notice = null; /** @memberof Morebits.wiki */ Morebits.wiki.addCheckpoint = function() { ++Morebits.wiki.nbrOfCheckpointsLeft; }; /** @memberof Morebits.wiki */ Morebits.wiki.removeCheckpoint = function() { if (--Morebits.wiki.nbrOfCheckpointsLeft <= 0 && Morebits.wiki.numberOfActionsLeft <= 0) { Morebits.wiki.actionCompleted.event(); } }; /* **************** Morebits.wiki.Api **************** */ /** * Si sahlan oo loola hadlo MediaWiki API. Waxay aqbashaa qaababka json ama xml * (caadiga ah); haddii json la doorto, waxay u degi doontaa si caadi ah `formatversion=2` * ilaa si kale loogu sheego. Sidoo kale, waxay ku khasbeysaa `errorformat` cusub, * iyada oo u degaysa `html` haddii aan la cayimin. `uselang` waxaa lagu khasbay luqadda * nuxurka ee wiki-ga. * * Koodka cusub, isticmaalka 3-da xuduudood ee ugu dambeeya waa in laga fogaadaa, halkaas * waxaa la isticmaalaa {@link Morebits.wiki.Api#setStatusElement|setStatusElement()} si loo xiro * shayga xaaladda (haddii loo baahdo) oo la isticmaalo `.then()` ama `.catch()` ee ballan-qaadka * uu soo celiyo `post()`, halkii laga cayimi lahaa jawaab-celinta `onSuccess` ama * `onFailure`. * * @memberof Morebits.wiki *@class * @param {string} currentAction - Falalka hadda jira (looga baahan yahay). * @param {Object} query - Weydiinta (looga baahan yahay). * @param {Function} [onSuccess] - Shaqada la wacayo marka codsigu guulaysto. * @param {Morebits.Status} [statusElement] - Shay Morebits.Status ah oo loo isticmaalo fariimaha xaaladda. * @param {Function} [onError] - Shaqada la wacayo haddii qalad dhaco. */ Morebits.wiki.Api = function(currentAction, query, onSuccess, statusElement, onError) { this.currentAction = currentAction; this.query = query; this.query.assert = 'user'; // Ku khasab qaababka qaladka cusub, iyada oo la doorbidayo html if (!query.errorformat || !['wikitext', 'plaintext'].includes(query.errorformat)) { this.query.errorformat = 'html'; } // Si cad u isticmaal luqadda nuxurka ee wiki-ga si loo yareeyo jahwareerka, // eeg #1179 wada xaajoodka this.query.uselang = 'content'; this.query.errorlang = 'uselang'; this.query.errorsuselocal = 1; this.onSuccess = onSuccess; this.onError = onError; if (statusElement) { this.setStatusElement(statusElement); } else { this.statelem = new Morebits.Status(currentAction); } // JSON waxaa lagu isticmaalaa dhammaan Morebits/Twinkle, laakiin xml wuxuu ahaadaa midka caadiga ah ee waafajinta dib u dhaca (backwards compatibility) if (!query.format) { this.query.format = 'xml'; } else if (query.format === 'json' && !query.formatversion) { this.query.formatversion = '2'; } else if (!['xml', 'json'].includes(query.format)) { this.statelem.error('Qaabka API aan ansax ahayn: waxaa la taageeraa oo keliya xml iyo json.'); } // Iska indhatir tags-ka weydiimaha iyo falalka aan la taageerin ee ugu badan, waxay soo saartaa digniino if (query.action && ['query', 'review', 'stabilize', 'watch'].includes(query.action)) { delete query.tags; } }; Morebits.wiki.Api.prototype = { currentAction: '', onSuccess: null, onError: null, parent: window, // isticmaal macnaha guud ee caalamiga ah haddii uusan jirin shay waalid ah query: null, response: null, responseXML: null, // isticmaalka `response` beddelkeeda; waxaa loo haystaa waafajinta dib u dhaca statelem: null, // magacan aan caadiga ahayn waxaa loo haystay waafajinta dib u dhaca statusText: null, // natiijada laga helay API-ga, inta badan "success" ama "error" errorCode: null, // koodka qaladka ee qoraalka gaaban, haddii ay jirto, sida ku xusan MediaWiki API errorText: null, // sharaxaadda qaladka oo buuxda, haddii ay jirto, badtokenRetry: false, // u deji true haddii tani ay tahay dib-u-dayis lagu sameeyay qalad badtoken ka dib /** * La soco shayga waalidka ee jawaab-celinta. * * @param {*} parent */ setParent: function(parent) { this.parent = parent; }, /** @param {Morebits.Status} statusElement */ setStatusElement: function(statusElement) { this.statelem = statusElement; this.statelem.status(this.currentAction); }, /** * Fuliy codsiga. * * @param {Object} callerAjaxParameters - Ha cayimin cabbir ilaa aad si dhab ah * u rabto inaad siiso jQuery cabbirro dheeri ah. * @return {jQuery.Promise} - Shay ballanqaad jQuery ah oo lagu xaliyay ama lagu diiday shayga api. */ post: function(callerAjaxParameters) { ++Morebits.wiki.numberOfActionsLeft; const queryString = $.map(this.query, (val, i) => { if (Array.isArray(val)) { return encodeURIComponent(i) + '=' + val.map(encodeURIComponent).join('|'); } else if (val !== undefined) { return encodeURIComponent(i) + '=' + encodeURIComponent(val); } }).join('&').replace(/^(.*?)(\btoken=[^&]*)&(.*)/, '$1$3&$2'); // token waa inuu noqdaa shayga ugu dambeeya ee xarigga weydiinta (bug TW-B-0013) const headers = { 'Api-User-Agent': morebitsWikiApiUserAgent }; if (this.query.action === 'parse') { // Sida uu qabo https://www.mediawiki.org/wiki/API:Etiquette headers['Promise-Non-Write-API-Action'] = 'true'; } const ajaxparams = $.extend({}, { context: this, type: this.query.action === 'query' ? 'GET' : 'POST', url: mw.util.wikiScript('api'), data: queryString, dataType: this.query.format, headers }, callerAjaxParameters); return $.ajax(ajaxparams).then( function onAPIsuccess(response, statusText) { this.statusText = statusText; this.response = this.responseXML = response; // Ku xaddid qaladka koowaad if (this.query.format === 'json') { this.errorCode = response.errors && response.errors[0].code; if (this.query.errorformat === 'html') { this.errorText = response.errors && response.errors[0].html; } else if (this.query.errorformat === 'wikitext' || this.query.errorformat === 'plaintext') { this.errorText = response.errors && response.errors[0].text; } } else { this.errorCode = $(response).find('errors error').eq(0).attr('code'); // Ku filan errorformats-ka html, wikitext, ama plaintext this.errorText = $(response).find('errors error').eq(0).text(); } if (typeof this.errorCode === 'string') { // API-du ma aysan jeclaysan waxa aan u sheegnay, tusaale ahaan bad edit token ama qalad abuurista bog return this.returnError(callerAjaxParameters); } // ku yeero jawaab-celinta guusha haddii mid la bixiyay if (this.onSuccess) { // u deji macnaha guud ee jawaab-celinta this.parent koodka cusub oo bixiy shayga API // sida doodda ugu horreysa ee jawaab-celinta (koodka dhaxalka ah) this.onSuccess.call(this.parent, this); } else { this.statelem.info('done'); } Morebits.wiki.actionCompleted(); return $.Deferred().resolveWith(this.parent, [this]); }, // kaliya shabakadda iyo khaladaadka server-ka ayaa gaara halkan - cabashooyinka API-ga laftiisa waxaa lagu qabtaa success() function onAPIfailure(jqXHR, statusText, errorThrown) { this.statusText = statusText; this.errorThrown = errorThrown; // inta badan waa aan la cayimin this.errorText = statusText + ' "' + jqXHR.statusText + '" ayaa dhacay markii lala xiriirayay API-ga.'; return this.returnError(); } ); }, returnError: function(callerAjaxParameters) { if (this.errorCode === 'badtoken' && !this.badtokenRetry) { this.statelem.warn('Calaamad (token) aan ansax ahayn. Helidda calaamad cusub iyo dib-u-dayis...'); this.badtokenRetry = true; // Hel CSRF token cusub oo dib u day. Haddii falka asalka ahi u baahdo nooc kale // oo ficil ah marka loo eego CSRF, waxaan samaynaynaa hal dib-u-dayis oo aan faa'iido lahayn ka hor intaanan bixin return Morebits.wiki.Api.getToken().then((token) => { this.query.token = token; return this.post(callerAjaxParameters); }); } this.statelem.error(this.errorText + ' (' + this.errorCode + ')'); // ku yeero jawaab-celinta guuldarrada haddii mid la bixiyay if (this.onError) { // u deji macnaha guud ee jawaab-celinta this.parent koodka cusub oo bixiy shayga API // sida doodda ugu horreysa ee jawaab-celinta koodka dhaxalka ah this.onError.call(this.parent, this); } // ha dhammaystirin falka si qaladku uu u sii ahaado mid muuqda return $.Deferred().rejectWith(this.parent, [this]); }, getStatusElement: function() { return this.statelem; }, getErrorCode: function() { return this.errorCode; }, getErrorText: function() { return this.errorText; }, getXML: function() { // waxaa loo haystaa waafajinta dib u dhaca, isticmaal getResponse() beddelkeeda return this.responseXML; }, getResponse: function() { return this.response; } }; /** * Soo qaado wikitext bog ka yimid. Kaydinta (caching) waa la hawlgeliyay iyadoo muddadu tahay 1 maalin. * * @param {string} title - Ciwaanka bogga * @return {Promise<string|null>} Waxay soo celinaysaa nuxurka bogga, ama null haddii uusan boggu jirin. */ Morebits.wiki.getCachedPage = function(title) { return new mw.Api({ userAgent: morebitsWikiApiUserAgent }).get({ action: 'query', prop: 'revisions', titles: title, rvprop: 'content', rvslots: '*', format: 'json', formatversion: '2', smaxage: '86400', // kaydi 1 maalin maxage: '86400', // kaydi 1 maalin uselang: 'content' }).then((data) => { const page = data.query.pages[0]; if (page.missing) { return null; } return page.revisions[0].slots.main.content; }); }; /** * Soo qaado JSON bog ka yimid. Kaydinta (caching) waa la hawlgeliyay iyadoo muddadu tahay 1 maalin. * * @param {string} title - Ciwaanka bogga * @return {Promise<string>} */ Morebits.wiki.getCachedJson = function(title) { return Morebits.wiki.getCachedPage(title).then((wikitext) => JSON.parse(wikitext)); }; var morebitsWikiApiUserAgent = 'morebits.js ([[w:WT:TW]])'; /** * Deji madaxa wakiilka isticmaalaha ee gaarka ah, kaas oo loo isticmaalo diiwaangelinta dhinaca server-ka. * Ogow in samaynta sidaas ay dejin doonto useragent-ka kasta `Morebits.wiki.Api` * habsocodka la fuliyo wixii ka dambeeya. * * @see {@link https://lists.wikimedia.org/pipermail/mediawiki-api-announce/2014-November/000075.html} * ku saabsan ogeysiiska asalka ah. * * @memberof Morebits.wiki.Api * @param {string} [ua=morebits.js ([[w:WT:TW]])] - Wakiilka isticmaalaha. Qiimaha caadiga ah * ee `morebits.js ([[w:WT:TW]])` waxaa lagu dari doonaa qiimo kasta oo la bixiyo. */ Morebits.wiki.Api.setApiUserAgent = function(ua) { morebitsWikiApiUserAgent = (ua ? ua + ' ' : '') + 'morebits.js ([[w:WT:TW]])'; }; /** * Hel CSRF token cusub marka la kulmo khaladaadka token-ka. * * @memberof Morebits.wiki.Api * @return {string} MediaWiki CSRF token. */ Morebits.wiki.Api.getToken = function() { const tokenApi = new Morebits.wiki.Api('Helidda token', { action: 'query', meta: 'tokens', type: 'csrf', format: 'json' }); return tokenApi.post().then((apiobj) => apiobj.response.query.tokens.csrftoken); }; /* **************** Morebits.wiki.Page **************** */ /** * Isticmaal MediaWiki API si aad u soo rarto bog oo ikhtiyaar ahaan ugu beddesho, u rarto, iwm. * * Kuwa waca looma oggola inay si toos ah u galaan sifooyinka fasalkan! * Helitaanka sifooyinka oo dhan waa iyada oo la marayo habka habboon ee get___() ama set___(). * * Kuwa waca waa inay dejiyaan {@link Morebits.wiki.actionCompleted.notice} iyo {@link Morebits.wiki.actionCompleted.redirect} * ka hor wicitaanka ugu horreeya ee {@link Morebits.wiki.Page.load()}. * * Mid kasta oo ka mid ah shaqooyinka jawaab-celinta wuxuu qaataa halbeeg (parameter) hal ah, kaas oo ah * tixraac ku socda shayga Morebits.wiki.Page ee diiwaangeliyay jawaab-celinta. * Shaqooyinka jawaab-celinta waxay ku yeeri karaan qaab kasta oo prototype ah ee Morebits.wiki.Page iyagoo adeegsanaya tixraacan. * * * Silsiladda wicitaanka ee hawlaha caadiga ah (jawaab-celinta isticmaalaha ugu dambeysa ee ikhtiyaariga ah lama tusi): * * - Wax ka beddel nuxurka hadda ee bogga (ma jiro khilaaf wax ka beddel): * `.load(userTextEditCallback) -> ctx.loadApi.post() -> * ctx.loadApi.post.success() -> ctx.fnLoadSuccess() -> userTextEditCallback() -> * .save() -> ctx.saveApi.post() -> ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * - Wax ka beddel nuxurka hadda ee bogga (oo wata khilaaf wax ka beddel): * `.load(userTextEditCallback) -> ctx.loadApi.post() -> * ctx.loadApi.post.success() -> ctx.fnLoadSuccess() -> userTextEditCallback() -> * .save() -> ctx.saveApi.post() -> ctx.loadApi.post.success() -> * ctx.fnSaveError() -> ctx.loadApi.post() -> ctx.loadApi.post.success() -> * ctx.fnLoadSuccess() -> userTextEditCallback() -> .save() -> * ctx.saveApi.post() -> ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * - Ku dar bog dhammaadkiisa (la mid ah prepend iyo newSection): * `.append() -> ctx.loadApi.post() -> ctx.loadApi.post.success() -> * ctx.fnLoadSuccess() -> ctx.fnAutoSave() -> .save() -> ctx.saveApi.post() -> * ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * Xusuusin: * 1. Dhammaan shaqooyinka ka dambeeya Morebits.wiki.Api.post() waxaa si asynchronous ah loogu yeeraa maktabadda jQuery AJAX. * 2. Silsiladda append/prepend/newSection waxaa loo gaabin karaa si yar, * laakiin waxay u baahan doontaa nuqulayn muhiim ah oo koodka ah faa'iido yar awgeed. * * @memberof Morebits.wiki * @class * @param {string} pageName - Magaca bogga, oo ay ka horreeyaan meesha magaca (haddii ay jirto). * Bogga hadda jira, isticmaal `mw.config.get('wgPageName')`. * @param {string|Morebits.Status} [status] - Xarig qeexaya falka la bilaabayo, * ama shay Morebits.Status ah */ Morebits.wiki.Page = function(pageName, status) { if (!status) { status = 'Furidda bogga "' + pageName + '"'; } /** * Doorsoomayaasha macnaha guud ee gaarka ah (Private context variables). * * Macnahan guud laguma arki karo dibadda, sidaas darteed dhammaan xogta halkan ku jirtaa * waa in la gaaraa iyada oo la marayo shaqooyinka getter iyo setter. * * @private */ const ctx = { // duurka dhabarka ee sifooyinka dadweynaha pageName: pageName, pageExists: false, editSummary: null, changeTags: null, testActions: null, // saf haddii ay jiraan falal ansax ah callbackParameters: null, statusElement: status instanceof Morebits.Status ? status : new Morebits.Status(status), // - wax ka beddel (edit) pageText: null, editMode: 'all', // save() waxay ku beddeshaa nuxurka buuxa ee bogga si caadi ah appendText: null, // lama isticmaali karo pageText tan sababtoo ah pageText waxaa lo baahan yahay in la raaco leexin prependText: null, // lama isticmaali karo pageText tan sababtoo ah pageText waxaa lo baahan yahay in la raaco leexin newSectionText: null, newSectionTitle: null, createOption: null, minorEdit: false, botEdit: false, pageSection: null, maxConflictRetries: 2, maxRetries: 2, followRedirect: false, followCrossNsRedirect: true, watchlistOption: 'nochange', watchlistExpiry: null, discussionToolsAutoSubscribe: null, creator: null, timestamp: null, // - dib u soo celis (revert) revertOldID: null, // - rari (move) moveDestination: null, moveTalkPage: false, moveSubpages: false, moveSuppressRedirect: false, // - ilaali (protect) protectEdit: null, protectMove: null, protectCreate: null, protectCascade: null, // - tirtir (delete) deleteTalkPage: false, // - ka soo celi tirtirka (undelete) undeleteTalkPage: false, // - raadinta abuurista (creation lookup) lookupNonRedirectCreator: false, // - deji (stabilize) (FlaggedRevs) flaggedRevs: null, // xaaladda gudaha pageLoaded: false, csrfToken: null, loadTime: null, lastEditTime: null, pageID: null, contentModel: null, revertCurID: null, revertUser: null, watched: false, fullyProtected: false, suppressProtectWarning: false, conflictRetries: 0, retries: 0, // jawaab-celinta (callbacks) onLoadSuccess: null, onLoadFailure: null, onSaveSuccess: null, onSaveFailure: null, onLookupCreationSuccess: null, onLookupCreationFailure: null, onMoveSuccess: null, onMoveFailure: null, onDeleteSuccess: null, onDeleteFailure: null, onUndeleteSuccess: null, onUndeleteFailure: null, onProtectSuccess: null, onProtectFailure: null, onStabilizeSuccess: null, onStabilizeFailure: null, // shayada gudaha loadQuery: null, loadApi: null, saveApi: null, lookupCreationApi: null, moveApi: null, moveProcessApi: null, patrolApi: null, patrolProcessApi: null, triageApi: null, triageProcessListApi: null, triageProcessApi: null, deleteApi: null, deleteProcessApi: null, undeleteApi: null, undeleteProcessApi: null, protectApi: null, protectProcessApi: null, stabilizeApi: null, stabilizeProcessApi: null }; const emptyFunction = function() { }; /** * Waxaa la soo rartaa qoraalka bogga. * * @param {Function} onSuccess - Shaqada jawaab-celinta taas oo loogu yeero marka raristu ay guulaysato. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka raristu guuldarraysato. */ this.load = function(onSuccess, onFailure) { ctx.onLoadSuccess = onSuccess; ctx.onLoadFailure = onFailure || emptyFunction; // Waa inuu awoodaa inuu sameeyo wax ka dib marka boggu soo baxo if (!onSuccess) { ctx.statusElement.error('Qalad gudaha ah: ma jiro onSuccess callback oo la bixiyay load()!'); ctx.onLoadFailure(this); return; } ctx.loadQuery = { action: 'query', prop: 'info|revisions', inprop: 'watched', intestactions: 'edit', // waa la balaarin karaa curtimestamp: '', meta: 'tokens', type: 'csrf', titles: ctx.pageName, format: 'json' // uma baahnayn rvlimit=1 sababtoo ah uma baahnayn rvstartid halkan waxaana soo laabta hal rev oo dhab ah si caadi ah }; if (ctx.editMode === 'all') { ctx.loadQuery.rvprop = 'content|timestamp'; // hel nuxurka bogga isla waqtigaas, haddii loo baahdo } else if (ctx.editMode === 'revert') { ctx.loadQuery.rvprop = 'timestamp'; ctx.loadQuery.rvlimit = 1; ctx.loadQuery.rvstartid = ctx.revertOldID; } if (ctx.followRedirect) { ctx.loadQuery.redirects = ''; // raac dhammaan leexinta } if (typeof ctx.pageSection === 'number') { ctx.loadQuery.rvsection = ctx.pageSection; } if (Morebits.userIsSysop) { ctx.loadQuery.inprop += '|protection'; } ctx.loadApi = new Morebits.wiki.Api('Soo qaadashada bogga...', ctx.loadQuery, fnLoadSuccess, ctx.statusElement, ctx.onLoadFailure); ctx.loadApi.setParent(this); ctx.loadApi.post(); }; /** * Kaydi qoraalka bogga Wikipedia. * Waa inaysan ka horrayn wicitaan lagu guulaystay oo ah `load()`. * * Digniin: Wicitaanka `save()` wuxuu keeni karaa wicitaanno dheeri ah oo ku socda * `load()` callback-yadii hore si looga soo kabsado khilaafaadka wax ka beddelka! Xaaladdan, * kuwa waca waa inay sameeyaan isla wax ka beddelka bogga cusub pageText iyo * dib ugu yeeraan `save()`. Dabeecaddan waxaa lagu joojin karaa * `setMaxConflictRetries(0)`. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka kaydintu ay guulaysato. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka kaydintu guuldarraysato. */ this.save = function(onSuccess, onFailure) { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; // miyaan heleynaa calaamadeena wax ka beddelka (edit token) mw.user.tokens? const canUseMwUserToken = fnCanUseMwUserToken('edit'); if (!ctx.pageLoaded && !canUseMwUserToken) { ctx.statusElement.error('Qalad gudaha ah: isku day inaad kaydiso bog aan la soo rarin!'); ctx.onSaveFailure(this); return; } if (!ctx.editSummary) { // habka qaybta cusub wuxuu oggolaadaa (sidoo kale dhiirrigeliyaa) isticmaalka // cinwaanka sida kooban ee wax ka beddelka, laakiin weydiinta waxaa u baahan // editSummary inay noqoto mid aan la cayimin ama '', ma aha null if (ctx.editMode === 'new' && ctx.newSectionTitle) { ctx.editSummary = ''; } else { ctx.statusElement.error('Qalad gudaha ah: kooban wax ka beddelka lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } } // waa inaysan dhicin haddii canUseMwUserToken === true if (ctx.fullyProtected && !ctx.suppressProtectWarning && !confirm( ctx.fullyProtected === 'infinity' ? 'Waxaad ku dhowdahay inaad wax ka beddesho bogga si buuxda loo ilaaliyo "' + ctx.pageName + '" (oo la ilaaliyo si aan xad lahayn). \n\nRiix OK si aad ugu sii wadato wax ka beddelka, ama Cancel si aad uga booddo wax ka beddelkan.' : 'Waxaad ku dhowdahay inaad wax ka beddesho bogga si buuxda loo ilaaliyo "' + ctx.pageName + '" (ilaalintu waxay dhacaysaa ' + new Morebits.Date(ctx.fullyProtected).calendar('utc') + ' (UTC)). \n\nRiix OK si aad ugu sii wadato wax ka beddelka, ama Cancel si aad uga booddo wax ka beddelkan.' ) ) { ctx.statusElement.error('Wax ka beddelka bogga si buuxda loo ilaaliyo waa la joojiyay.'); ctx.onSaveFailure(this); return; } ctx.retries = 0; const query = { action: 'edit', title: ctx.pageName, summary: ctx.editSummary, token: canUseMwUserToken ? mw.user.tokens.get('csrfToken') : ctx.csrfToken, watchlist: ctx.watchlistOption, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } if (typeof ctx.pageSection === 'number') { query.section = ctx.pageSection; } // Deji sifada wax ka beddelka yar (minor edit). Haddii sifooyinkan ay joogaan qiimo kasta, waxaa loo tarjumaa true if (ctx.minorEdit) { query.minor = true; } else { query.notminor = true; // ku qasab qaabeynta Twinkle inay ka gudubto dejinta doorbididda isticmaalaha ee "dhammaan wax ka beddelku waa kuwo yaryar" } // Deji sifada wax ka beddelka bot-ka. Haddii sifo tani ay joogto qiimo kasta, waxaa loo tarjumaa true if (ctx.botEdit) { query.bot = true; } if (ctx.discussionToolsAutoSubscribe !== null) { query.discussiontoolsautosubscribe = ctx.discussionToolsAutoSubscribe ? 'yes' : 'no'; } switch (ctx.editMode) { case 'append': if (ctx.appendText === null) { ctx.statusElement.error('Qalad gudaha ah: ku darista qoraalka lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.appendtext = ctx.appendText; // isticmaal qaabka aad ugu darto nuxurka bogga hadda break; case 'prepend': if (ctx.prependText === null) { ctx.statusElement.error('Qalad gudaha ah: qoraalka hordhaca ah lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.prependtext = ctx.prependText; // isticmaal qaabka aad ugu horreysiiso nuxurka bogga hadda break; case 'new': if (!ctx.newSectionText) { // API-du ma oggolaqto qoraal qayb cusub oo madhan ctx.statusElement.error('Qalad gudaha ah: qoraalka qaybta cusub lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.section = 'new'; query.text = ctx.newSectionText; // ku dar qayb cusub nuxurka bogga hadda query.sectiontitle = ctx.newSectionTitle || ctx.editSummary; // waxaa sameeya API, laakiin qiimayaasha aan ahayn '' waxaa loola dhaqmi lahaa sida qoraal break; case 'revert': query.undo = ctx.revertCurID; query.undoafter = ctx.revertOldID; if (ctx.lastEditTime) { query.basetimestamp = ctx.lastEditTime; // hubi in bogga aan la beddelin tan iyo markii la soo raray } query.starttimestamp = ctx.loadTime; // hubi in bogga aan la tirtirin tan iyo markii la soo raray (ha dib u abuurin waxyaabaha xun) break; default: // 'all' query.text = ctx.pageText; // ku beddel nuxurka buuxa ee bogga if (ctx.lastEditTime) { query.basetimestamp = ctx.lastEditTime; // hubi in bogga aan la beddelin tan iyo markii la soo raray } query.starttimestamp = ctx.loadTime; // hubi in bogga aan la tirtirin tan iyo markii la soo raray (ha dib u abuurin waxyaabaha xun) break; } if (['recreate', 'createonly', 'nocreate'].includes(ctx.createOption)) { query[ctx.createOption] = ''; } if (canUseMwUserToken && ctx.followRedirect) { query.redirect = true; } ctx.saveApi = new Morebits.wiki.Api('Kaydinta bogga...', query, fnSaveSuccess, ctx.statusElement, fnSaveError); ctx.saveApi.setParent(this); ctx.saveApi.post(); }; /** * Ku dar qoraalka lagu bixiyay `setAppendText()` dhamaadka bogga. * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada (watchlist expiry) la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.append = function(onSuccess, onFailure) { ctx.editMode = 'append'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** * Ku dar qoraalka lagu bixiyay `setPrependText()` bilowga bogga. * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.prepend = function(onSuccess, onFailure) { ctx.editMode = 'prepend'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** * Abuur qayb cusub oo wata qoraalka ay bixisay `setNewSectionText()` * iyo cinwaanka qaybta ee ka yimid `setNewSectionTitle()`. * Haddii `editSummary` la bixiyo, taas ayaa la isticmaali doonaa beddelka cinwaanka otomaatiga ah ee "->Title (new section". * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.newSection = function(onSuccess, onFailure) { ctx.editMode = 'new'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** @return {string} Magaca bogga la rarray, oo ay ku jirto meesha magaca (namespace) */ this.getPageName = function() { return ctx.pageName; }; /** @return {string} Qoraalka bogga ka dib load() guulaystay */ this.getPageText = function() { return ctx.pageText; }; /** @param {string} pageText - Qoraalka bogga ee la cusboonaysiiyay kaas oo la kaydin doono marka `save()` la yeero */ this.setPageText = function(pageText) { ctx.editMode = 'all'; ctx.pageText = pageText; }; /** @param {string} appendText - Qoraal lagu dari doono dhammaadka bogga marka `append()` la yeero */ this.setAppendText = function(appendText) { ctx.editMode = 'append'; ctx.appendText = appendText; }; /** @param {string} prependText - Qoraal lagu horreysiin doono bogga marka `prepend()` la yeero */ this.setPrependText = function(prependText) { ctx.editMode = 'prepend'; ctx.prependText = prependText; }; /** @param {string} newSectionText - Qoraal lagu dari doono qayb cusub oo bogga ah marka `newSection()` la yeero */ this.setNewSectionText = function(newSectionText) { ctx.editMode = 'new'; ctx.newSectionText = newSectionText; }; /** * @param {string} newSectionTitle - Cinwaanka qaybta cusub ee la abuuray marka `newSection()` la yeero * Haddii uu maqanyahay, `ctx.editSummary` ayaa la isticmaali doonaa. Dhibaatooyin ayaa dhici kara haddii template la beddelay la isticmaalo. */ this.setNewSectionTitle = function(newSectionTitle) { ctx.editMode = 'new'; ctx.newSectionTitle = newSectionTitle; }; // Sifooyinka la xiriira wax ka beddelka (Edit-related setter methods): /** * Deji kooban wax ka beddelka (edit summary) kaas oo la isticmaali doono marka `save()` la yeero. * Looma baahna haddii editMode uu yahay 'new' oo newSectionTitle la bixiyo. * * @param {string} summary */ this.setEditSummary = function(summary) { ctx.editSummary = summary; }; /** * Deji calaamadaha (tags) caadiga ah ee lagu dabaqayo falka API. * Tiro ka mid ah falalka ma taageeraan, kuwa ugu caansan waa watch, review, * iyo stabilize ({@link https://phabricator.wikimedia.org/T247721|T247721}). * * @param {string|string[]} tags - Xarig ama saf calaamado ah. */ this.setChangeTags = function(tags) { ctx.changeTags = tags; }; /** * @param {string} [createOption=null] - Wuxuu qaadan karaa afartan qiime: * - recreate: abuur bogga haddii uusan jirin, ama wax ka beddel haddii uu jiro. * - createonly: abuur bogga haddii uusan jirin, laakiin soo celi qalad haddii uu hore u jiray. * - nocreate: ha abuurin bogga, kaliya wax ka beddel haddii uu hore u jiray. * - `null`: abuur bogga haddii uusan jirin, ilaa laga tirtiray intii u dhaxaysay raridda bogga iyo kaydinta wax ka beddelka (caadiga ah). */ this.setCreateOption = function(createOption) { ctx.createOption = createOption; }; /** @param {boolean} minorEdit - Deji true si aad ugu calaamadiso wax ka beddelka mid yar. */ this.setMinorEdit = function(minorEdit) { ctx.minorEdit = minorEdit; }; /** @param {boolean} botEdit - Deji true si aad ugu calaamadiso wax ka beddelka mid bot ah */ this.setBotEdit = function(botEdit) { ctx.botEdit = botEdit; }; /** * @param {number} pageSection - Nambar buuxa (integer) oo qeexaya lambarka qaybta si loo rarto ama loo kaydiyo. * Haddii loo dejiyo `null`, bogga oo dhan ayaa la soo celin doonaa. */ this.setPageSection = function(pageSection) { ctx.pageSection = pageSection; }; /** * @param {number} maxConflictRetries - Tirada dib-u-dayisyada ee khaladaadka kaydinta ee ku lug leh khilaaf wax ka beddel ama * luminta token-ka. Caadiga ah: 2. */ this.setMaxConflictRetries = function(maxConflictRetries) { ctx.maxConflictRetries = maxConflictRetries; }; /** * @param {number} maxRetries - Tirada dib-u-dayisyada ee khaladaadka kaydinta ee aan ku lug lahayn khilaaf wax ka beddel ama * luminta token-ka. Caadiga ah: 2. */ this.setMaxRetries = function(maxRetries) { ctx.maxRetries = maxRetries; }; /** * Deji haddii iyo sida loo daawado bogga, oo ay ku jirto dejinta dhicitaanka (expiry). * * @param {boolean|string|Morebits.Date|Date} [watchlistOption=false] - * Asal ahaan isku-dhafka xulashooyinka MW API iyo Twinkley ee la heli karo ka hor dhicitaanka: * - `true`|`'yes'`|`'watch'`: bogga waxaa lagu darayaa liiska daawashada ee isticmaalaha * marka falka la yeero. Waxay u degeysaa si caadi ah daawasho aan xad lahayn ilaa `watchlistExpiry` la bixiyo. * - `false`|`'no'`|`'nochange'`: xaaladda daawashada bogga (oo ay ku jirto dhicitaanka) lama beddeli doono. * - `'default'`|`'preferences'`: xaaladda daawashada bogga waxaa loo dejin doonaa * iyadoo lagu saleynayo dejinta doorbididda isticmaalaha marka falka la yeero. Waxay u degeysaa si caadi ah daawasho aan xad lahayn ilaa `watchlistExpiry` la bixiyo. * - `'unwatch'`: si cad uga saar daawashada bogga. * - `string` ama `number` kasta oo kale, ama shay `Morebits.Date` ama `Date`: * daaw bogga ilaa wakhtiga la cayimay, adigoo u laabanaya `watchlistExpiry` haddii la bixiyo. * @param {string|number|Morebits.Date|Date} [watchlistExpiry=infinity] - * Xarig ama nambar taariikh la mid ah, ama shay taariikh. Haddii uu yahay xarig ama nambar, * wuxuu noqon karaa qaraabo (2 toddobaad) ama si kale taariikh la mid ah (tusaale MA AHA "baradho"): * ISO 8601: 2038-01-09T03:14:07Z * MediaWiki: 20380109031407 * UNIX: 2147483647 * SQL: 2038-01-09 03:14:07 * Wuxuu kaloo noqon karaa `infinity` ama sida infinity (infinite, indefinite, iyo never). * Sidoo kale eeg {@link https://phabricator.wikimedia.org/source/mediawiki-libs-Timestamp/browse/master/src/ConvertibleTimestamp.php;4e53b859a9580c55958078f46dd4f3a44d0fcaa0$57-109?as=source&blame=off} */ this.setWatchlist = function(watchlistOption, watchlistExpiry) { if (watchlistOption instanceof Morebits.Date || watchlistOption instanceof Date) { watchlistOption = watchlistOption.toISOString(); } if (typeof watchlistExpiry === 'undefined') { watchlistExpiry = 'infinity'; } else if (watchlistExpiry instanceof Morebits.Date || watchlistExpiry instanceof Date) { watchlistExpiry = watchlistExpiry.toISOString(); } switch (watchlistOption) { case 'nochange': case 'no': case false: case undefined: ctx.watchlistOption = 'nochange'; // MW API waxay oggolaataa in la beddelo dhicitaanka iyada oo aan la beddelin (sida "nochange" ay u tixraacayso xaaladda binary), // laakiin iyadoo tan loo haysto null waxay si caadi ah u noqon doontaa dhicitaan kasta oo jira, waxay xaqiijinaysaa inaysan jirin wax "isbeddel ah." ctx.watchlistExpiry = null; break; case 'unwatch': // dhicitaanku muhiim ma ahan ctx.watchlistOption = 'unwatch'; break; case 'preferences': case 'default': ctx.watchlistOption = 'preferences'; // API-du waxay oggolaataa dhicitaan halkan, laakiin ma jiro xitaa (T265716) // wax doorbidid ah oo ku saabsan dhicitaanka, markaa wax yar bay ka madhan tahay macnaha guud. ctx.watchlistExpiry = watchlistExpiry; break; case 'watch': case 'yes': case true: ctx.watchlistOption = 'watch'; ctx.watchlistExpiry = watchlistExpiry; break; default: // Ma aha mid "caadi ah" laakiin wuxuu qabtaa "xarig kasta oo kale" ctx.watchlistOption = 'watch'; ctx.watchlistExpiry = watchlistOption; break; } }; /** * Deji dhicitaanka liiska daawashada (watchlist expiry). setWatchlist waxay inta badan tan u maamuli kartaa * iyada oo keligeed ah, markaa tani waxay halkan u taallaa inta badan dhammaystiran iyo waafajinta * xulashooyinka buuxa. * * @param {string|number|Morebits.Date|Date} [watchlistExpiry=infinity] - * Xarig ama nambar taariikh la mid ah, ama shay taariikh. Haddii uu yahay xarig ama nambar, * wuxuu noqon karaa qaraabo (2 toddobaad) ama si kale taariikh la mid ah (tusaale MA AHA "baradho"): * ISO 8601: 2038-01-09T03:14:07Z * MediaWiki: 20380109031407 * UNIX: 2147483647 * SQL: 2038-01-09 03:14:07 * Wuxuu kaloo noqon karaa `infinity` ama sida infinity (infinite, indefinite, iyo never). * Sidoo kale eeg {@link https://phabricator.wikimedia.org/source/mediawiki-libs-Timestamp/browse/master/src/ConvertibleTimestamp.php;4e53b859a9580c55958078f46dd4f3a44d0fcaa0$57-109?as=source&blame=off} */ this.setWatchlistExpiry = function(watchlistExpiry) { if (typeof watchlistExpiry === 'undefined') { watchlistExpiry = 'infinity'; } else if (watchlistExpiry instanceof Morebits.Date || watchlistExpiry instanceof Date) { watchlistExpiry = watchlistExpiry.toISOString(); } ctx.watchlistExpiry = watchlistExpiry; }; /** * Haddii aad wax ka beddelayso bog wadahadal (talk page), deji haddii aad is-diiwaangelinayso nooc kasta oo * fariin wadahadal ah oo uu abuuray wax ka beddelku. * * @param {boolean} subscribe */ this.setDiscussionToolsAutoSubscribe = function(subscribe) { ctx.discussionToolsAutoSubscribe = subscribe; }; /** * @param {boolean} [followRedirect=false] - * - `true`: ugu badnaan hal leexin ayaa la raaci doonaa. Xaaladda * leexin, fariin ayaa loo bandhigayaa isticmaalaha waxaana bartilmaameedka * leexinta laga soo qaadan karaa getPageName(). * - `false`: (caadiga ah) pageName-ka la codsaday waxaa loo isticmaali doonaa iyada oo aan loo eegin leexin kasta. * @param {boolean} [followCrossNsRedirect=true] - Lama khuseeyo haddii `followRedirect` aan loo dejin true. * - `true`: (caadiga ah) raac leexinta xitaa haddii ay tahay leexin u dhexaysa meelaha magaca (cross-namespace redirect) * - `false`: ha raacin leexinta haddii ay tahay meel u dhexaysa magacyada, wax ka beddel leexinta lafteeda. */ this.setFollowRedirect = function(followRedirect, followCrossNsRedirect) { if (ctx.pageLoaded) { ctx.statusElement.error('Qalad gudaha ah: ma beddeli karo dejinta leexinta ka dib markii bogga la rarray!'); return; } ctx.followRedirect = followRedirect; ctx.followCrossNsRedirect = typeof followCrossNsRedirect !== 'undefined' ? followCrossNsRedirect : ctx.followCrossNsRedirect; }; // shaqada sifooyinka raadinta abuurista (lookup-creation setter function) /** * @param {boolean} flag - Haddii loo dejiyo true, qoraaga iyo wakhti-shaabadeedka * nooca ugu horreeya ee aan leexinta ahayn ee bogga ayaa la soo qaadayaa. * * Digniin: * 1. Haddii aysan jirin dib-u-eegisyo ka mid ah 50-ka ugu horreeya oo ah 5 * kuwo aan leexin ahayn, ama haddii ay jiraan dib-u-eegisyo ka yar 50 oo dhammaantood ay yihiin * leexino, abuuriskii asalka ahaa waa la soo qaadayaa. * 2. Dib-u-eegisyada uusan isticmaalahu xaq u lahayn inuu galo * (revdeled/suppressed) waxaa loola dhaqmi doonaa sidii kuwo aan leexin ahayn. * 3. Waa in aan la isticmaalin marka boggu leeyahay contentmodel aan wikitext ahayn * sida Modulespace Lua ama user JavaScript/CSS. */ this.setLookupNonRedirectCreator = function(flag) { ctx.lookupNonRedirectCreator = flag; }; // Sifooyinka la xiriira raridda (Move-related setter functions) /** @param {string} destination */ this.setMoveDestination = function(destination) { ctx.moveDestination = destination; }; /** @param {boolean} flag */ this.setMoveTalkPage = function(flag) { ctx.moveTalkPage = !!flag; }; /** @param {boolean} flag */ this.setMoveSubpages = function(flag) { ctx.moveSubpages = !!flag; }; /** @param {boolean} flag */ this.setMoveSuppressRedirect = function(flag) { ctx.moveSuppressRedirect = !!flag; }; // Sifooyinka la xiriira ilaalinta (Protect-related setter functions) /** * @param {string} level - Xaqqa looga baahan yahay falka gaarka ah * tusaale ahaan autoconfirmed, sysop, templateeditor, extendedconfirmed * (enWiki oo keliya). * @param {string} [expiry=infinity] */ this.setEditProtection = function(level, expiry) { ctx.protectEdit = { level: level, expiry: expiry || 'infinity' }; }; this.setMoveProtection = function(level, expiry) { ctx.protectMove = { level: level, expiry: expiry || 'infinity' }; }; this.setCreateProtection = function(level, expiry) { ctx.protectCreate = { level: level, expiry: expiry || 'infinity' }; }; this.setCascadingProtection = function(flag) { ctx.protectCascade = !!flag; }; this.suppressProtectWarning = function() { ctx.suppressProtectWarning = true; }; // Sifooyinka la xiriira tirtiridda (Delete-related setter) /** @param {boolean} flag */ this.setDeleteTalkPage = function(flag) { ctx.deleteTalkPage = !!flag; }; // Sifooyinka la xiriira ka soo celinta tirtirka (Undelete-related setter) /** @param {boolean} flag */ this.setUndeleteTalkPage = function(flag) { ctx.undeleteTalkPage = !!flag; }; // Sifooyinka la xiriira dib u soo celinta (Revert-related getters/setters): this.setOldID = function(oldID) { ctx.revertOldID = oldID; }; /** @return {string} Aqoonsiga dib-u-eegiska hadda ee bogga (current revision ID) */ this.getCurrentID = function() { return ctx.revertCurID; }; /** @return {string} Tafatiraha ugu dambeeya ee bogga */ this.getRevisionUser = function() { return ctx.revertUser; }; /** @return {string} Waqti-shaabadeedka ISO 8601 ee uu boggu ugu dambeeyay ee la beddelay. */ this.getLastEditTime = function() { return ctx.lastEditTime; }; // Sifooyinka kale (Miscellaneous getters/setters): /** * Qeex shay loogu isticmaalo shaqada jawaab-celinta. * * `callbackParameters` waxaa loogu talagalay isticmaalaha waca keliya. Halbeegyada * waxay u oggolaanayaan qofka waca inuu u gudbiyo macnaha saxda ah ee jawaab-celintiisa * shaqada. Kuwa waca waa inay xaqiijiyaan in wixii isbeddel ah ee ku yimaada * shayga callbackParameters ee gudaha jawaab-celinta `load()` ay weli u oggolaanayaan * dib-u-gelitaan sax ah oo ku socda jawaab-celinta `load()` haddii khilaaf wax ka beddel * la ogaado marka la yeerayo `save()`. * * @param {Object} callbackParameters */ this.setCallbackParameters = function(callbackParameters) { ctx.callbackParameters = callbackParameters; }; /** * @return {Object} - Shayga hore loogu dejiyay `setCallbackParameters()`. */ this.getCallbackParameters = function() { return ctx.callbackParameters; }; /** * @param {Morebits.Status} statusElement */ this.setStatusElement = function(statusElement) { ctx.statusElement = statusElement; }; /** * @return {Morebits.Status} Shayga xaaladda ee abuuray dhisaha (constructor). */ this.getStatusElement = function() { return ctx.statusElement; }; /** * @param {string} level - Xaqqa looga baahan yahay wax ka beddelka si uusan ugu baahan * dib-u-eegis. Xulashooyinka suurtogalka ah: none, autoconfirmed, review (ma aha enWiki). * @param {string} [expiry=infinity] */ this.setFlaggedRevs = function(level, expiry) { ctx.flaggedRevs = { level: level, expiry: expiry || 'infinity' }; }; /** * @return {boolean} True haddii boggu uu ka jiray wiki-ga markii ugu dambeysay ee la rarray. */ this.exists = function() { return ctx.pageExists; }; /** * @return {string} Aqoonsiga bogga ee bogga la rarray. 0 haddii uusan boggu jirin. */ this.getPageID = function() { return ctx.pageID; }; /** * @return {string} - Qaabka nuxurka ee bogga (Content model). Qiimayaasha suurtogalka ah * waxaa ka mid ah (laakiin waxaa laga yaabaa inaysan ku xaddidnayn): `wikitext`, `javascript`, * `css`, `json`, `Scribunto`, `sanitized-css`, `MassMessageListContent`. * Sidoo kale waxaa lagu heli karaa iyada oo la marayo `mw.config.get('wgPageContentModel')`. */ this.getContentModel = function() { return ctx.contentModel; }; /** * @return {boolean|string} - Xaaladda daawashada ee bogga. Boolean * ilaa laga daawanayo si ku-meel-gaar ah, xaaladdaas oo kale waxay soo celinaysaa xarigga dhicitaanka. */ this.getWatched = function() { return ctx.watched; }; /** * @return {string} Waqti-shaabadeedka ISO 8601 ee uu boggu ugu dambeeyay ee la rarray. */ this.getLoadTime = function() { return ctx.loadTime; }; /** * @return {string} Qoraaga abuuray bogga ka dib `lookupCreation()`. */ this.getCreator = function() { return ctx.creator; }; /** * @return {string} Waqti-shaabadeedka ISOString ee abuurista bogga ka dib `lookupCreation()`. */ this.getCreationTimestamp = function() { return ctx.timestamp; }; /** @return {boolean} haddii aad wax ka beddeli karto bogga iyo in kale */ this.canEdit = function() { return !!ctx.testActions && ctx.testActions.includes('edit'); }; /** * Soo qaado magaca isticmaalaha ee abuuray bogga iyo sidoo kale * wakhti-shaabadeedka abuurista. Magaca isticmaalaha waxaa lagu soo qaadan karaa iyadoo la adeegsanayo * shaqada `getCreator()`; wakhti-shaabadeedka waxaa lagu soo qaadan karaa iyadoo la adeegsanayo * shaqada `getCreationTimestamp()`. * Bishii Juun 2019 wuxuu aaggu aaqoon u lahaa `lookupCreator()`. * * @param {Function} onSuccess - Shaqada jawaab-celinta ee la wacayo marka 5 * magaca isticmaalaha iyo wakhti-shaabadeedka laga helo gudaha jawaab-celinta. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee la wacayo marka * raadintu guuldarraysato */ this.lookupCreation = function(onSuccess, onFailure) { ctx.onLookupCreationSuccess = onSuccess; ctx.onLookupCreationFailure = onFailure || emptyFunction; if (!onSuccess) { ctx.statusElement.error('Qalad gudaha ah: ma jiro onSuccess callback oo la bixiyay lookupCreation()!'); ctx.onLookupCreationFailure(this); return; } const query = { action: 'query', prop: 'revisions', titles: ctx.pageName, rvlimit: 1, rvprop: 'user|timestamp', rvdir: 'newer', format: 'json' }; // Kaliya qaabka nuxurka wikitext ayaa si lagu kalsoonaan karo u maamuli kara // rvsection, kuwa kalena waxay soo celiyaan qalad marka lala lammaaniyo // nuxurka rvprop. Sidoo kale, moodooyinka aan wikitext ahayn ma fahmaan // fikradda #REDIRECT, markaa waa in aynaan isku dayin // xallinta leexinta ee fnLookupCreationSuccess if (ctx.lookupNonRedirectCreator) { query.rvsection = 0; query.rvprop += '|content'; } if (ctx.followRedirect) { query.redirects = ''; // raac dhammaan leexinta } ctx.lookupCreationApi = new Morebits.wiki.Api('Soo qaadashada macluumaadka abuurista bogga', query, fnLookupCreationSuccess, ctx.statusElement, ctx.onLookupCreationFailure); ctx.lookupCreationApi.setParent(this); ctx.lookupCreationApi.post(); }; /** * Dib ugu celi bogga `revertOldID` ee ay dejisay `setOldID`. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.revert = function(onSuccess, onFailure) { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; if (!ctx.revertOldID) { ctx.statusElement.error('Qalad gudaha ah: aqoonsiga dib-u-eegiska ee dib loogu noqonayo lama dejin ka hor dib u celinta!'); ctx.onSaveFailure(this); return; } ctx.editMode = 'revert'; this.load(fnAutoSave, ctx.onSaveFailure); }; /** * Rari bog cinwaan kale. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.move = function(onSuccess, onFailure) { ctx.onMoveSuccess = onSuccess; ctx.onMoveFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'move', ctx.onMoveFailure)) { return; // jooji } if (!ctx.moveDestination) { ctx.statusElement.error('Qalad gudaha ah: magaca bogga bartilmaameedka lama dejin ka hor raridda!'); ctx.onMoveFailure(this); return; } if (fnCanUseMwUserToken('move')) { fnProcessMove.call(this, this); } else { const query = fnNeedTokenInfoQuery('move'); ctx.moveApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessMove, ctx.statusElement, ctx.onMoveFailure); ctx.moveApi.setParent(this); ctx.moveApi.post(); } }; /** * Calaamadee bogga in la ilaalo (patrolled), iyadoo la adeegsanayo `rcid` (haddii la heli karo) ama `revid`. * * Ilaalinta sidaas oo kale uma baahna inay ku tiirsanaato raridda bogga * la su'aalayo; si fudud gudbinta revid ee API-ga waa ku filan tahay, markaa xaaladahaas * kaliya adeegsiga {@link Morebits.wiki.Api} ayaa laga yaabaa inay roon tahay. * * Ma jiro maamul qalad ah maadaama aynaan dhab ahaantii u daneeyneyn khaladaadka. */ this.patrol = function() { if (!Morebits.userIsSysop && !Morebits.userIsInGroup('patroller')) { return; } // Haddii xiriiriye uu jiro, uma baahnid inaad hubiso in la ilaaliyay if ($('.patrollink').length) { const patrolhref = $('.patrollink a').attr('href'); ctx.rcid = mw.util.getParamValue('rcid', patrolhref); fnProcessPatrol(this, this); } else { const patrolQuery = { action: 'query', prop: 'info', meta: 'tokens', type: 'patrol', // illaa inta aan waydiinayno, waxaa laga yaabaa inay sidoo kale helaan token list: 'recentchanges', // hubi haddii boggu uusan lahayn ilaalino titles: ctx.pageName, rcprop: 'patrolled', rctitle: ctx.pageName, rclimit: 1, format: 'json' }; ctx.patrolApi = new Morebits.wiki.Api('soo qaadashada token...', patrolQuery, fnProcessPatrol); ctx.patrolApi.setParent(this); ctx.patrolApi.post(); } }; /** * Calaamadee bogga in dib-u-eegis lagu sameeyay kordhinta PageTriage. * * Wuxuu, dabeecad ahaan, u calaamadin doonaa in la ilaaliyay sidoo kale. Wuxuu u laabanayaa * ilaalinta haddii uusan ku jirin meel magac ku habboon. * * Si dabiici ah ugu ma tiirsana raridda bogga su'aasha ku jira; si fudud * gudbinta `pageid` ee API-ga waa ku filan tahay, markaa xaaladahaas oo keliya * adeegsiga {@link Morebits.wiki.Api} ayaa laga yaabaa inay roon tahay. * * Wuxuu marka hore hubin doonaa haddii boggu saf ku jiro iyada oo loo marayo * {@link Morebits.wiki.Page~fnProcessTriageList|fnProcessTriageList}. * * Ma jiro maamul qalad ah maadaama aynaan dhab ahaantii u daneeyneyn khaladaadka. * * @see {@link https://www.mediawiki.org/wiki/Extension:PageTriage} Waxaa loogu yeeraa "review" on-wiki. */ this.triage = function() { // U laabo ilaalinta haddii uusan ahayn meel magac triage oo ansax ah if (!mw.config.get('pageTriageNamespaces').includes(new mw.Title(ctx.pageName).getNamespaceId())) { this.patrol(); } else { if (!Morebits.userIsSysop && !Morebits.userIsInGroup('patroller')) { return; } // Haddii aad joogto bogga su'aasha ku jira, uma baahnid inaad u waydiiso aqoonsiga bogga (page ID) if (new mw.Title(Morebits.pageNameNorm).getPrefixedText() === new mw.Title(ctx.pageName).getPrefixedText()) { ctx.pageID = mw.config.get('wgArticleId'); fnProcessTriageList(this, this); } else { const query = fnNeedTokenInfoQuery('triage'); ctx.triageApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessTriageList); ctx.triageApi.setParent(this); ctx.triageApi.post(); } } }; // |delete| waa eray la keydiyay dhadhanka qaarkood ee JS /** * Tirtir bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.deletePage = function(onSuccess, onFailure) { ctx.onDeleteSuccess = onSuccess; ctx.onDeleteFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'delete', ctx.onDeleteFailure)) { return; // jooji } if (fnCanUseMwUserToken('delete')) { fnProcessDelete.call(this, this); } else { const query = fnNeedTokenInfoQuery('delete'); ctx.deleteApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessDelete, ctx.statusElement, ctx.onDeleteFailure); ctx.deleteApi.setParent(this); ctx.deleteApi.post(); } }; /** * Ka soo celi tirtirka bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.undeletePage = function(onSuccess, onFailure) { ctx.onUndeleteSuccess = onSuccess; ctx.onUndeleteFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'undelete', ctx.onUndeleteFailure)) { return; // jooji } if (fnCanUseMwUserToken('undelete')) { fnProcessUndelete.call(this, this); } else { const query = fnNeedTokenInfoQuery('undelete'); ctx.undeleteApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessUndelete, ctx.statusElement, ctx.onUndeleteFailure); ctx.undeleteApi.setParent(this); ctx.undeleteApi.post(); } }; /** * Ilaali bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.protect = function(onSuccess, onFailure) { ctx.onProtectSuccess = onSuccess; ctx.onProtectFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'protect', ctx.onProtectFailure)) { return; // jooji } if (!ctx.protectEdit && !ctx.protectMove && !ctx.protectCreate) { ctx.statusElement.error('Qalad gudaha ah: waa inaad dejisaa ilaalinta wax ka beddelka iyo/ama raridda iyo/ama abuurista ka hor inta aadan wicin protect()!'); ctx.onProtectFailure(this); return; } // sababtoo ah habka uu MW API u tarjumayo heerarka ilaalinta // (absolute, ee ma aha differential), waxaan had iyo jeer u baahanahay inaan codsanno // heerarka ilaalinta ee server-ka const query = fnNeedTokenInfoQuery('protect'); ctx.protectApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessProtect, ctx.statusElement, ctx.onProtectFailure); ctx.protectApi.setParent(this); ctx.protectApi.post(); }; /** * Dabaq dejinta ilaalinta FlaggedRevs. Kaliya waxay ka shaqeysaa wiki-yada halkaas oo * kordhintu ay ka rakiban tahay (`$wgFlaggedRevsProtection = true` * tusaale ahaan halkaas oo dejinta FlaggedRevs ay ka muuqato tab-ka "protect"). * * @see {@link https://www.mediawiki.org/wiki/Extension:FlaggedRevs} * Waxaa loogu yeeraa "pending changes" on-wiki. * * @param {Function} [onSuccess] * @param {Function} [onFailure] */ this.stabilize = function(onSuccess, onFailure) { ctx.onStabilizeSuccess = onSuccess; ctx.onStabilizeFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'FlaggedRevs', ctx.onStabilizeFailure)) { return; // jooji } if (!ctx.flaggedRevs) { ctx.statusElement.error('Qalad gudaha ah: waa inaad dejisaa flaggedRevs ka hor inta aadan wicin stabilize()!'); ctx.onStabilizeFailure(this); return; } if (fnCanUseMwUserToken('stabilize')) { fnProcessStabilize.call(this, this); } else { const query = fnNeedTokenInfoQuery('stabilize'); ctx.stabilizeApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessStabilize, ctx.statusElement, ctx.onStabilizeFailure); ctx.stabilizeApi.setParent(this); ctx.stabilizeApi.post(); } }; /* * Shaqooyinka xubnaha gaarka ah (Private member functions) * Kuwani laguma soo bandhigo dibadda */ /** * Go'aami haddii aan badbaadin karno wicitaan API ah adigoo isticmaalaya csrf token * ee lagu soo diray HTML-ka bogga, ama haddii aan u baahan flah2pkbe0ckg0ipyo7tnqbhoqf98fo 311231 311230 2026-10-28T17:48:08Z Isma4l 41797 311231 javascript text/javascript // <nowiki> /** * Maktabad ka buuxda faa'iidooyin badan oo loogu talagalay qoraallada isticmaalaha ee wiki-yada MediaWiki, oo ay ku jirto Wikipedia. * * Qodobbada muhiimka ah waxaa ka mid ah: * - {@link Morebits.wiki.Api} - samee wicitaano ku socda MediaWiki API * - {@link Morebits.wiki.Page} - wax ka beddel bogagga wiki-ga (wax ka beddel, dib u soo celis, tirtir, iwm.) * - {@link Morebits.Date} - habaynta shayga taariikhda oo la xoojiyay, oo ah nooc ka mid ah moment.js oo fudud * - {@link Morebits.QuickForm} - soo saar foomamka HTML ee degdegga ah inta lagu jiro duulimaadka * - {@link Morebits.SimpleWindow} - soo saar daaqadaha wadahadalka iyo moodalka * - {@link Morebits.Status} - bandhigaha fariinta xaaladda ee adag, oo ay isticmaalaan fasallada Morebits.wiki * - {@link Morebits.wikitext} - qalab loogu talagalay la tacaalidda wikitext-ka * - {@link Morebits.string} - qalab loogu talagalay maamulidda xargaha (strings) * - {@link Morebits.array} - qalab loogu talagalay maamulidda safafka (arrays) * - {@link Morebits.ip} - qalab gacan ka geysta habaynta ciwaanada IP-ga * * Tiirarka ku xiran (Dependencies): * - Wax walba waxay ku tiirsan yihiin jQuery. Laakiin wiki-yada badankoodu waa inay tan bixiyaan si caadi ah. * - {@link Morebits.QuickForm}, {@link Morebits.SimpleWindow}, iyo {@link Morebits.Status} waxay ku tiirsan yihiin faylka "morebits.css" ee qaabaynkooda. * - Si aad u abuurto qalab ku salaysan morebits.js, isticmaal sintakiskan ku jira MediaWiki:Gadgets-definition: * - `*GadgetName[ResourceLoader|dependencies=mediawiki.user,mediawiki.util,mediawiki.Title]|morebits.js|morebits.css|GadgetName.js` * - Haddii kale, waxaad qaabayn kartaa morebits.js oo ah qalab qarsan oo ku jira MediaWiki:Gadgets-definition: * - `*morebits[ResourceLoader|dependencies=mediawiki.user,mediawiki.util,mediawiki.Title|hidden]|morebits.js|morebits.css` * ka dibna culeys ext.gadget.morebits sida mid ka mid ah tiirarka ku xiran ee qalabka cusub. * * Dhammaan waxyaabaha halkan ku jira waxay ka shaqeeyaan dhammaan daalacashada ay MediaWiki u feydo taageerada JavaScript. * * Maktabaddan waxaa ilaaliya ilaaliyaasha Twinkle. * Wixii su'aalo ah, talooyin, caawinaad, iwm., aad [Wikipedia talk:Twinkle on English Wikipedia](http://en.wikipedia.org/wiki/WT:TW). * Isha horumarinta ugu dambeysa waxaa laga helayaa {@link https://github.com/wikimedia-gadgets/twinkle/blob/master/src/morebits.js|GitHub}. * * @namespace Morebits */ (function() { /** @lends Morebits */ const Morebits = {}; window.Morebits = Morebits; // u oggolow helitaanka caalamiga ah /** * Habaynta gaarka ah ee Wiki ee Morebits */ Morebits.l10n = { /** * Magacyada maxalliga ah ee ereyada sixirka "redirect". * Hubi adigoo isticmaalaya api.php?action=query&format=json&meta=siteinfo&formatversion=2&siprop=magicwords */ redirectTagAliases: ['#REDIRECT'], /** * Waxay qaadataa xargo dood ahaan waxayna hubisaa inay tahay waqti-shaabadeed (timestamp) iyo inkale * Haddii aysan ahayn, waxay soo celineysaa null. Haddii ay tahay, waxay soo celinaysaa saf tirooyin ah * oo qaab ah [year, month, date, hour, minute, second] * taas oo loo gudbin karo Date.UTC() * * @param {string} str * @return {number[] | null} */ signatureTimestampFormat: function(str) { // HH:mm, DD Month YYYY (UTC) const rgx = /(\d{2}):(\d{2}), (\d{1,2}) (\w+) (\d{4}) \(UTC\)/; const match = rgx.exec(str); if (!match) { return null; } const month = Morebits.Date.localeData.months.indexOf(match[4]); if (month === -1) { return null; } // ..... sanadka ... bisha .. taariikhda ... saacada .... daqiiqada return [match[5], month, match[3], match[1], match[2]]; } }; /** * Shaqo caawiye fudud si loo arko kooxaha uu isticmaalahu ka tirsanaan karo. * * @param {string} group - tusaale `sysop`, `extendedconfirmed`, iwm. * @return {boolean} */ Morebits.userIsInGroup = function(group) { return mw.config.get('wgUserGroups').includes(group); }; /** * Wuxuu si adag u qeexayaa in isticmaalaha uu yahay sysop, kaas oo la isticmaalo marar badan. * * @type {boolean} */ Morebits.userIsSysop = Morebits.userIsInGroup('sysop'); /** * Waxay go'aaminaysaa in bogga hadda jira uu yahay leexin (redirect) ama leexin jilicsan. Wuxuu ku guuldareystaa * inuu ogaado leexinta jilicsan ee bogagga wax ka beddelka, taariikhda, iwm. Wuxuu isku dayi doonaa inuu * ogaado Module:RfD, oo wata dhibco isku mid ah oo guuldarro ah. * * @return {boolean} */ Morebits.isPageRedirect = function() { return !!(mw.config.get('wgIsRedirect') || document.getElementById('softredirect') || $('.box-RfD').length); }; /** * Wuxuu kaydiyaa nooc caadi ah (hooseeyayaasha oo loo beddelay meel bannaan) ee * doorsoomaha `wgPageName`. * * @type {string} */ Morebits.pageNameNorm = mw.config.get('wgPageName').replace(/_/g, ' '); /** * Abuur xargo loogu isticmaalo regex oo la jaanqaadaysa magaca bogga. Wuxuu xisaabtanka ku darayaa * xarfaha hore ee waaweyn, hooseeyayaasha oo ah meelo bannaan, iyo astaamaha gaarka ah * ee la baxsado. Sidoo kale eeg {@link Morebits.namespaceRegex}. * * @param {string} pageName - Magaca bogga oo aan lahayn meesha magaca (namespace). * @return {string} - Magaca bogga `Foo bar`, wuxuu soo celinayaa xarigga `[Ff]oo[_ ]bar`. */ Morebits.pageNameRegex = function(pageName) { if (pageName === '') { return ''; } const firstChar = pageName[0], remainder = Morebits.string.escapeRegExp(pageName.slice(1)); if (mw.Title.phpCharToUpper(firstChar) !== firstChar.toLowerCase()) { return '[' + mw.Title.phpCharToUpper(firstChar) + firstChar.toLowerCase() + ']' + remainder; } return Morebits.string.escapeRegExp(firstChar) + remainder; }; /** * Waxay u beddeshaa xarig ama safka gunti-abuurayaasha DOM (DOM nodes) qayb HTML ah. * Sintakiska xiriirinta wiki (`[[...]]`) waxaa loo beddelaa saldhig HTML ah. * Waxaa lagu isticmaalo Morebits.QuickForm iyo Morebits.Status * * @internal * @param {string|Node|(string|Node)[]} input * @return {DocumentFragment} */ Morebits.createHtml = function(input) { const fragment = document.createDocumentFragment(); if (!input) { return fragment; } if (!Array.isArray(input)) { input = [input]; } for (let i = 0; i < input.length; ++i) { if (input[i] instanceof Node) { fragment.appendChild(input[i]); } else { $.parseHTML(Morebits.createHtml.renderWikilinks(input[i])).forEach((node) => { fragment.appendChild(node); }); } } return fragment; }; /** * Waxay u beddeshaa xiriirinta wiki tags-ka saldhigga HTML. * * @param {string} text * @return {string} */ Morebits.createHtml.renderWikilinks = function(text) { const ub = new Morebits.Unbinder(text); // Ha u beddelin xiriirinta wiki ee gudaha calaamadaha koodka maadaama loo isticmaalo soo bandhigidda koodka wiki ub.unbind('<code>', '</code>'); ub.content = ub.content.replace( /\[\[:?(?:([^|\]]+?)\|)?([^\]|]+?)\]\]/g, (_, target, text) => { if (!target) { target = text; } return '<a target="_blank" href="' + mw.util.getUrl(target) + '" title="' + target.replace(/"/g, '&#34;') + '">' + text + '</a>'; }); return ub.rebind(); }; /** * Abuur xarig loogu isticmaalo regex ee ku habboon dhammaan magacyada meelaha (aliases), iyadoon loo eegin * xarfaha waaweyn iyo hooseeyayaasha/meelaha bannaan. Ma ku jirto xarafka hore ee ikhtiyaariga ah * ee `:`, laakiin haddii ay jiraan wax ka badan hal shay, wuxuu ku duubaa liiska koox * aan qabsasho lahayn. Tani waxay ka dhigan tahay inaad samayn karto `Morebits.namespaceRegex([4]) + * ':' + Morebits.pageNameRegex('Twinkle')` si aad u waafajiso bog buuxa. Wuxuu isticmaalaa * {@link Morebits.pageNameRegex}. * * @param {number[]} namespaces - Safka nambarada meelaha (namespaces). Nambarada aan la isticmaalin/ansaxnayn * ee meelaha waxaa si aamusan loo tuuraa. * @example * // waxay soo celinaysaa '(?:[Ff][Ii][Ll][Ee]|[Ii][Mm][Aa][Gg][Ee])' * Morebits.namespaceRegex([6]) * @return {string} - Xarig ku habboon Regex oo ah dhammaan magacyada meelaha. */ Morebits.namespaceRegex = function(namespaces) { if (!Array.isArray(namespaces)) { namespaces = [namespaces]; } const aliases = []; let regex; $.each(mw.config.get('wgNamespaceIds'), (name, number) => { if (namespaces.includes(number)) { // Meelaha magacyadu gabi ahaanba waa kuwo aan u janjeerin xarfaha waaweyn iyo hooseeyayaasha, // waxaana xarigga regex uu yahay mid faa'iido badan / la jaanqaadi kara marka loo eego shayga RegExp, // markaas annaguna waxaan aqbalnay xaraf kasta kiis kasta oo warqad ah. aliases.push(name.split('').map((char) => Morebits.pageNameRegex(char)).join('')); } }); switch (aliases.length) { case 0: regex = ''; break; case 1: regex = aliases[0]; break; default: regex = '(?:' + aliases.join('|') + ')'; break; } return regex; }; /* **************** Morebits.QuickForm **************** */ /** * Abuuritaanka foomam fudud oo heer sare ah iyada oo aan la helin codayn gaar ah oo badan. * * @namespace Morebits.QuickForm * @memberof Morebits * @class * @param {event} event - Shaqada la fulinayo marka foomka la gudbiyo. * @param {string} [eventType=submit] - Nooca dhacdada. */ Morebits.QuickForm = function QuickForm(event, eventType) { this.root = new Morebits.QuickForm.Element({ type: 'form', event: event, eventType: eventType }); }; /** * Waxay soo bandhigeysaa wax soo saarka HTML ee quickForm. * * @memberof Morebits.QuickForm * @return {HTMLElement} */ Morebits.QuickForm.prototype.render = function QuickFormRender() { const ret = this.root.render(); ret.names = {}; return ret; }; /** * Ku dar shay foomka. * * @memberof Morebits.QuickForm * @param {(object|Morebits.QuickForm.Element)} data - Shayga quickform, ama shayga uu ku dhisanyahay * shayga quickform. * @return {Morebits.QuickForm.Element} - Sida shayga loo gudbiyay shaqada. */ Morebits.QuickForm.prototype.append = function QuickFormAppend(data) { return this.root.append(data); }; /** * Abuur shay cusub oo loogu talagalay foomka. * * Tusmada noocyada Morebits.QuickForm.Element: * - Sifooyinka caalamiga ah: id, className, style, tooltip, extra, $data, adminonly * - `select`: Sanduuqa isku-dhafka (sidoo kale loo yaqaan drop-down). * - Sifooyinka: name, label, multiple, size, list, event, disabled * - `option`: Shay loogu talagalay sanduuqa isku-dhafka. * - Sifooyinka: value, label, selected, disabled * - `optgroup`: Koox ka kooban "option"yo. * - Sifooyinka: label, list * - `field`: Goob beer (sidoo kale loo yaqaan group box). * - Sifooyinka: name, label, disabled * - `checkbox`: Calaamadda hubinta (checkbox). Waa in la isticmaalo cabbirka "list". * - Sifooyinka: name, list, event * - Sifooyinka (gudaha list): name, label, value, checked, disabled, event, subgroup * - `radio`: Badhanka raadiyaha. Waa in la isticmaalo cabbirka "list". * - Sifooyinka: name, list, event * - Sifooyinka (gudaha list): name, label, value, checked, disabled, event, subgroup * - `input`: Sanduuqa gelinta qoraalka. * - Sifooyinka: name, label, value, size, placeholder, maxlength, disabled, required, readonly, event * - `number`: Sanduuqa gelinta nambarka. * - Sifooyinka: Wax walba oo uu `input` qoraalku leeyahay, iyo sidoo kale: min, max, step, list * - `dyninput`: Qayb ka mid ah sanduuqyada qoraalka oo wata badhamada "Remove" iyo badhanka "Add". * - Sifooyinka: name, label, min, max, inputs, sublabel, value, size, maxlength, event * - `hidden`: Goob foom oo aan la arki karin. * - Sifooyinka: name, value * - `header`: Madaxa heerka 5aad. * - Sifooyinka: label * - `div`: Shay meel-hayte guud ah ama sumad. * - Sifooyinka: name, label * - `submit`: Badhanka gudbinta. Morebits.SimpleWindow waxay kuwan u raraysaa hooseeyaasha wadahadalka. * - Sifooyinka: name, label, disabled * - `button`: Badhan guud. * - Sifooyinka: name, label, disabled, event * - `textarea`: Sanduuq qoraal oo weyn oo safaf badan leh. * - Sifooyinka: name, label, value, cols, rows, disabled, required, readonly * - `fragment`: Shay DocumentFragment ah. * - Ma laha sifooyin, mana laha sifooyin caalami ah marka laga reebo adminonly. * Waxaa jira xoogaa kala duwanaansho ah oo ku saabsan sida noocyadu u maamulaan sifooyinka `label`: * - `div`, `select`, `field`, `checkbox`/`radio`, `input`, `textarea`, `header`, iyo `dyninput` waxay aqbali karaan safar shay ah, * waxaana walxaha sumaddu noqon karaan `Element`. * - `option`, `optgroup`, `_dyninput_cell`, `submit`, iyo `button` waxay aqbalaan hal xarig oo keliya. * * @memberof Morebits.QuickForm * @class * @param {Object} data - Shayag matalaya shayga quickform. Waa inuu *eexayaa mid ka mid ah noocyada la heli karo ee ka yimid tusmada sare, iyo sidoo kale sifooyin kasta * ee khuseeya oo la heli karo. * @example new Morebits.QuickForm.Element({ * name: 'target', * type: 'input', * label: 'Your target:', * tooltip: 'Enter your target. Required.', * required: true * }); */ Morebits.QuickForm.Element = function QuickFormElement(data) { this.data = data; this.childs = []; }; /** * @memberof Morebits.QuickForm.Element * @type {number} */ Morebits.QuickForm.Element.id = 0; /** * Wuxuu ku darayaa shay shayga hadda jira. * * @memberof Morebits.QuickForm.Element * @param {Morebits.QuickForm.Element} data - Shay quickForm ah ama shayga loo baahan yahay si * loo abuuro shayga quickForm. * @return {Morebits.QuickForm.Element} Shayga la mid ah ee la soo gudbiyay. */ Morebits.QuickForm.Element.prototype.append = function QuickFormElementAppend(data) { let child; if (data instanceof Morebits.QuickForm.Element) { child = data; } else { child = new Morebits.QuickForm.Element(data); } this.childs.push(child); return child; }; /** * Waxay soo bandhigeysaa wax soo saarka HTML ee shayga quickForm. Tan waa in la waco * iyada oo aan la marin xuduudo: `form.render()`. * * @memberof Morebits.QuickForm.Element * @return {HTMLElement} */ Morebits.QuickForm.Element.prototype.render = function QuickFormElementRender(internal_subgroup_id) { const currentNode = this.compute(this.data, internal_subgroup_id); for (let i = 0; i < this.childs.length; ++i) { // ha u gudbin internal_subgroup_id wicitaannada soo noqnoqoshada (recursive) currentNode[1].appendChild(this.childs[i].render()); } return currentNode[0]; }; /** @memberof Morebits.QuickForm.Element */ Morebits.QuickForm.Element.prototype.compute = function QuickFormElementCompute(data, in_id) { let node; let childContainer = null; let label; const id = (in_id ? in_id + '_' : '') + 'node_' + Morebits.QuickForm.Element.id++; if (data.adminonly && !Morebits.userIsSysop) { // hargab hack alpha data.type = 'hidden'; } let i, current, subnode; switch (data.type) { case 'form': node = document.createElement('form'); node.className = 'quickform'; node.setAttribute('action', 'javascript:void(0);'); if (data.event) { node.addEventListener(data.eventType || 'submit', data.event, false); } break; case 'fragment': node = document.createDocumentFragment(); // jajabyadu ma yeelan karaan sifooyin kasta, markaa si toos ah u soo celi return [node, node]; // Mararka qaarkood Twinkle waxay isticmaashaa "select" xulashooyin raadin oo qurux badan. Tan waxaa xoojinaya maktabadda dhinac saddexaad ee "select2". Ku shaqee adigoo abuuraya shay Morebits "select", ka dibna wac `$('select[name=sub_group]').select2({});` ama wax la mid ah dhamaadka koodkaaga ugu weyn. case 'select': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('label')); label.setAttribute('for', id); label.appendChild(Morebits.createHtml(data.label)); label.style.marginRight = '3px'; } var select = node.appendChild(document.createElement('select')); if (data.event) { select.addEventListener('change', data.event, false); } if (data.multiple) { select.setAttribute('multiple', 'multiple'); } if (data.size) { select.setAttribute('size', data.size); } if (data.disabled) { select.setAttribute('disabled', 'disabled'); } select.setAttribute('name', data.name); if (data.list) { for (i = 0; i < data.list.length; ++i) { current = data.list[i]; if (current.list) { current.type = 'optgroup'; } else { current.type = 'option'; } subnode = this.compute(current); select.appendChild(subnode[0]); } } childContainer = select; break; case 'option': node = document.createElement('option'); node.values = data.value; node.setAttribute('value', data.value); if (data.selected) { node.setAttribute('selected', 'selected'); } if (data.disabled) { node.setAttribute('disabled', 'disabled'); } node.setAttribute('label', data.label); node.appendChild(document.createTextNode(data.label)); break; case 'optgroup': node = document.createElement('optgroup'); node.setAttribute('label', data.label); if (data.list) { for (i = 0; i < data.list.length; ++i) { current = data.list[i]; current.type = 'option'; // waa inay noqdaan options halkan subnode = this.compute(current); node.appendChild(subnode[0]); } } break; case 'field': node = document.createElement('fieldset'); label = node.appendChild(document.createElement('legend')); label.appendChild(Morebits.createHtml(data.label)); if (data.name) { node.setAttribute('name', data.name); } if (data.disabled) { node.setAttribute('disabled', 'disabled'); } break; case 'checkbox': case 'radio': node = document.createElement('div'); if (data.list) { for (i = 0; i < data.list.length; ++i) { const cur_id = id + '_' + i; current = data.list[i]; var cur_div; if (current.type === 'header') { // inline hack cur_div = node.appendChild(document.createElement('h6')); cur_div.appendChild(document.createTextNode(current.label)); if (current.tooltip) { Morebits.QuickForm.Element.generateTooltip(cur_div, current); } continue; } cur_div = node.appendChild(document.createElement('div')); subnode = cur_div.appendChild(document.createElement('input')); subnode.values = current.value; subnode.setAttribute('value', current.value); subnode.setAttribute('type', data.type); subnode.setAttribute('id', cur_id); subnode.setAttribute('name', current.name || data.name); // Haddii magaca la bixiyo sanduuqa hubinta shaqsi ahaaneed, ku dar xog-hal (data-single) // sifo taas oo muujinaysa inaysan qayb ka ahayn liiska sanduuqyada hubinta ee leh // magac isku mid ah. Waxaa lagu isticmaalaagetInputData() if (current.name) { subnode.setAttribute('data-single', 'data-single'); } if (current.checked) { subnode.setAttribute('checked', 'checked'); } if (current.disabled) { subnode.setAttribute('disabled', 'disabled'); } label = cur_div.appendChild(document.createElement('label')); label.appendChild(Morebits.createHtml(current.label)); label.setAttribute('for', cur_id); if (current.tooltip) { Morebits.QuickForm.Element.generateTooltip(label, current); } // qaababku waxay galaan sumadda, macno ma samaynayso in la habeeyo checkbox/radio if (current.style) { label.setAttribute('style', current.style); } var event; if (current.subgroup) { let tmpgroup = current.subgroup; if (!Array.isArray(tmpgroup)) { tmpgroup = [tmpgroup]; } var subgroupRaw = new Morebits.QuickForm.Element({ type: 'div', id: id + '_' + i + '_subgroup' }); $.each(tmpgroup, (idx, el) => { const newEl = $.extend({}, el); if (!newEl.type) { newEl.type = data.type; } newEl.name = (current.name || data.name) + '.' + newEl.name; subgroupRaw.append(newEl); }); const subgroup = subgroupRaw.render(cur_id); subgroup.className = 'quickformSubgroup'; subnode.subgroup = subgroup; subnode.shown = false; event = function(e) { if (e.target.checked) { e.target.parentNode.appendChild(e.target.subgroup); if (e.target.type === 'radio') { const name = e.target.name; if (e.target.form.names[name] !== undefined) { e.target.form.names[name].parentNode.removeChild(e.target.form.names[name].subgroup); } e.target.form.names[name] = e.target; } } else { e.target.parentNode.removeChild(e.target.subgroup); } }; subnode.addEventListener('change', event, true); if (current.checked) { subnode.parentNode.appendChild(subgroup); } } else if (data.type === 'radio') { event = function(e) { if (e.target.checked) { const name = e.target.name; if (e.target.form.names[name] !== undefined) { e.target.form.names[name].parentNode.removeChild(e.target.form.names[name].subgroup); } delete e.target.form.names[name]; } }; subnode.addEventListener('change', event, true); } // ku dar dhacdada isticmaalayaasha ugu dambayn, si ay ula falgeli karto kooxda hoose (subgroup) if (data.event) { subnode.addEventListener('change', data.event, false); } else if (current.event) { subnode.addEventListener('change', current.event, true); } } } if (data.shiftClickSupport && data.type === 'checkbox') { Morebits.checkboxShiftClickSupport(Morebits.QuickForm.getElements(node, data.name)); } break; // gelintu waa nooc qoraal ah, markaa nambarka halkan wuxuu ka dhaxlaa waxyaabihii la mid ahaa case 'number': case 'input': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('label')); label.appendChild(Morebits.createHtml(data.label)); label.setAttribute('for', data.id || id); label.style.marginRight = '3px'; } subnode = node.appendChild(document.createElement('input')); subnode.setAttribute('name', data.name); if (data.type === 'input') { subnode.setAttribute('type', 'text'); } else { subnode.setAttribute('type', 'number'); ['min', 'max', 'step', 'list'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, data[att]); } }); } ['value', 'size', 'placeholder', 'maxlength'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, data[att]); } }); ['disabled', 'required', 'readonly'].forEach((att) => { if (data[att]) { subnode.setAttribute(att, att); } }); if (data.event) { subnode.addEventListener('input', data.event, false); } childContainer = subnode; break; case 'dyninput': var min = data.min || 1; var max = data.max || Infinity; node = document.createElement('div'); label = node.appendChild(document.createElement('h5')); label.appendChild(Morebits.createHtml(data.label)); var listNode = node.appendChild(document.createElement('div')); var more = this.compute({ type: 'button', label: 'more', disabled: min >= max, event: function(e) { const new_node = new Morebits.QuickForm.Element(e.target.sublist); e.target.area.appendChild(new_node.render()); if (++e.target.counter >= e.target.max) { e.target.setAttribute('disabled', 'disabled'); } e.stopPropagation(); } }); node.appendChild(more[0]); var moreButton = more[1]; var sublist = { type: '_dyninput_row', remove: false, maxlength: data.maxlength, event: data.event, inputs: data.inputs || [{ // waafajinta (compatibility) label: data.sublabel || data.label, name: data.name, value: data.value, size: data.size }] }; for (i = 0; i < min; ++i) { const elem = new Morebits.QuickForm.Element(sublist); listNode.appendChild(elem.render()); } sublist.remove = true; sublist.morebutton = moreButton; sublist.listnode = listNode; moreButton.sublist = sublist; moreButton.area = listNode; moreButton.max = max - min; moreButton.counter = 0; break; case '_dyninput_row': // Gaar ah (Private) node = document.createElement('div'); data.inputs.forEach((subdata) => { const cell = new Morebits.QuickForm.Element($.extend(subdata, { type: '_dyninput_cell' })); node.appendChild(cell.render()); }); if (data.remove) { const remove = this.compute({ type: 'button', label: 'remove', event: function(e) { const list = e.target.listnode; const node = e.target.inputnode; const more = e.target.morebutton; list.removeChild(node); --more.counter; more.removeAttribute('disabled'); e.stopPropagation(); } }); node.appendChild(remove[0]); const removeButton = remove[1]; removeButton.inputnode = node; removeButton.listnode = data.listnode; removeButton.morebutton = data.morebutton; } break; case '_dyninput_cell': // Gaar ah (Private), la mid ah gelinta caadiga ah node = document.createElement('span'); if (data.label) { label = node.appendChild(document.createElement('label')); label.appendChild(document.createTextNode(data.label)); label.setAttribute('for', id + '_input'); label.style.marginRight = '3px'; } subnode = node.appendChild(document.createElement('input')); subnode.setAttribute('id', id + '_input'); if (data.value) { subnode.setAttribute('value', data.value); } subnode.setAttribute('name', data.name); subnode.setAttribute('type', 'text'); subnode.setAttribute('data-dyninput', 'data-dyninput'); if (data.size) { subnode.setAttribute('size', data.size); } if (data.maxlength) { subnode.setAttribute('maxlength', data.maxlength); } if (data.required) { subnode.setAttribute('required', 'required'); } if (data.disabled) { subnode.setAttribute('required', 'disabled'); } if (data.event) { subnode.addEventListener('input', data.event, false); } node.style.marginRight = '3px'; break; case 'hidden': node = document.createElement('input'); node.setAttribute('type', 'hidden'); node.values = data.value; node.setAttribute('value', data.value); node.setAttribute('name', data.name); break; case 'header': node = document.createElement('h5'); node.appendChild(Morebits.createHtml(data.label)); break; case 'div': node = document.createElement('div'); if (data.name) { node.setAttribute('name', data.name); } if (data.label) { const result = document.createElement('span'); result.className = 'quickformDescription'; result.appendChild(Morebits.createHtml(data.label)); node.appendChild(result); } break; case 'submit': node = document.createElement('span'); childContainer = node.appendChild(document.createElement('input')); childContainer.setAttribute('type', 'submit'); if (data.label) { childContainer.setAttribute('value', data.label); } childContainer.setAttribute('name', data.name || 'submit'); if (data.disabled) { childContainer.setAttribute('disabled', 'disabled'); } break; case 'button': node = document.createElement('span'); childContainer = node.appendChild(document.createElement('input')); childContainer.setAttribute('type', 'button'); if (data.label) { childContainer.setAttribute('value', data.label); } childContainer.setAttribute('name', data.name); if (data.disabled) { childContainer.setAttribute('disabled', 'disabled'); } if (data.event) { childContainer.addEventListener('click', data.event, false); } break; case 'textarea': node = document.createElement('div'); node.setAttribute('id', 'div_' + id); if (data.label) { label = node.appendChild(document.createElement('h5')); const labelElement = document.createElement('label'); labelElement.appendChild(Morebits.createHtml(data.label)); labelElement.setAttribute('for', data.id || id); label.appendChild(labelElement); } subnode = node.appendChild(document.createElement('textarea')); subnode.setAttribute('name', data.name); if (data.cols) { subnode.setAttribute('cols', data.cols); } if (data.rows) { subnode.setAttribute('rows', data.rows); } if (data.disabled) { subnode.setAttribute('disabled', 'disabled'); } if (data.required) { subnode.setAttribute('required', 'required'); } if (data.readonly) { subnode.setAttribute('readonly', 'readonly'); } if (data.value) { subnode.value = data.value; } childContainer = subnode; break; default: throw new Error('Morebits.QuickForm: unknown element type ' + data.type.toString()); } if (!childContainer) { childContainer = node; } if (data.tooltip) { Morebits.QuickForm.Element.generateTooltip(label || node, data); } if (data.extra) { childContainer.extra = data.extra; } if (data.$data) { $(childContainer).data(data.$data); } if (data.style) { childContainer.setAttribute('style', data.style); } if (data.className) { childContainer.className = childContainer.className ? childContainer.className + ' ' + data.className : data.className; } childContainer.setAttribute('id', data.id || id); return [node, childContainer]; }; Morebits.QuickForm.$tooltip = null; /** * Abuur tilmaam qalab (tooltip). * * @memberof Morebits.QuickForm.Element * @param {HTMLElement} node - Shayga HTML ee agtiisa lagu abuurayo tilmaam qalab. * @param {Object} data - Xogta qaabaynta ee la xiriirta tilmaam qalab. */ Morebits.QuickForm.Element.generateTooltip = function QuickFormElementGenerateTooltip(node, data) { if (!Morebits.QuickForm.$tooltip) { Morebits.QuickForm.$tooltip = $('<div>') .attr('id', 'morebits-ui-tooltip') .attr('role', 'tooltip') .addClass('morebits-ui-tooltip') .appendTo('body'); } const $tooltip = Morebits.QuickForm.$tooltip; const $button = $('<span>') .addClass('morebits-tooltipButton') .text('?') .appendTo(node); $button.on('mouseenter', () => { $tooltip.html(data.tooltip).addClass('visible'); const buttonRect = $button[0].getBoundingClientRect(); const tooltipRect = $tooltip[0].getBoundingClientRect(); const topOffset = buttonRect.bottom + tooltipRect.height < window.innerHeight ? buttonRect.bottom : // Waxay ku habboon tahay xagga sare ee calaamadda su'aasha - geli halkaas Math.max(0, buttonRect.top - tooltipRect.height); // Haddii kale, geli xagga hoose ee calaamadda su'aasha const leftOffset = buttonRect.right + tooltipRect.width < window.innerWidth ? buttonRect.right : // Waxay ku habboon tahay xagga midig ee calaamadda su'aasha - geli halkaas Math.max(0, buttonRect.left - tooltipRect.width); // Haddii kale, geli xagga bidix ee calaamadda su'aasha $tooltip.css('top', window.scrollY + topOffset); $tooltip.css('left', window.scrollX + leftOffset); }).on('mouseleave', () => { $tooltip.removeClass('visible'); }); }; // Hababka qaar ee caawiya ee lagu maamulo quickForms ka dib abuuritaankooda: // (Midkoodna ugama shaqeeyo noocyada goobaha "dyninput" hadda) /** * Waxay soo celinaysaa shay ka kooban dhammaan xogta foomka ee buuxda ee uu geliyay isticmaalahu, iyada oo furayaasha * shaygu ay yihiin magacyada shayga foomka. Goobaha la joojiyay waa la iska indhatiri doonaa, laakiin ma aha goobaha qarsoon. * * @memberof Morebits.QuickForm * @param {HTMLFormElement} form * @return {Object} Iyadoo magacyada goobaha ay yihiin furayaal, xogta gelintuna ay tahay qiimayaal. */ Morebits.QuickForm.getInputData = function(form) { const result = {}; for (let i = 0; i < form.elements.length; i++) { const field = form.elements[i]; if (field.disabled || !field.name || !field.type || field.type === 'submit' || field.type === 'button') { continue; } // Wixii ku jira kooxaha hoose (subgroups), quickform waxay ku darsataa magacyada walxaha // magaca kooxda waalidka oo ay ku xigto dhibic, meesha ka saar taas. const fieldNameNorm = field.name.slice(field.name.indexOf('.') + 1); switch (field.type) { case 'radio': if (field.checked) { result[fieldNameNorm] = field.value; } break; case 'checkbox': if (field.dataset.single) { result[fieldNameNorm] = field.checked; // boolean } else { result[fieldNameNorm] = result[fieldNameNorm] || []; if (field.checked) { result[fieldNameNorm].push(field.value); } } break; case 'select-multiple': result[fieldNameNorm] = $(field).val(); // field.value wax ma tarayo break; case 'text': // hoos ayay ugu dhacdaa case 'textarea': if (field.dataset.dyninput) { result[fieldNameNorm] = result[fieldNameNorm] || []; result[fieldNameNorm].push(field.value.trim()); } else { result[fieldNameNorm] = field.value.trim(); } break; default: // waxay noqon kartaa select-one, date, number, email, iwm if (field.value) { result[fieldNameNorm] = field.value; } break; } } return result; }; /** * Waxay soo celinaysaa dhammaan walxaha foomka ee wata magaca ama aqoonsiga goobta la bixiyay. * * @memberof Morebits.QuickForm * @param {HTMLFormElement} form * @param {string} fieldName - Magaca ama aqoonsiga goobaha. * @return {HTMLElement[]} - Safka walxaha foomka ee u dhigma. */ Morebits.QuickForm.getElements = function QuickFormGetElements(form, fieldName) { const $form = $(form); fieldName = $.escapeSelector(fieldName); // nadiifi gelinta let $elements = $form.find('[name="' + fieldName + '"]'); if ($elements.length > 0) { return $elements.toArray(); } $elements = $form.find('#' + fieldName); return $elements.toArray(); }; /** * Waxay baartaa safka walxaha ee sanduuqa hubinta ama badhanka raadiyaha ee wata sifo gaar ah oo ah * `value`, waxayna soo celinaysaa shayga ugu horreeya ee noocaas ah. Waxay soo celinaysaa null haddii aan la helin. * * @memberof Morebits.QuickForm * @param {HTMLInputElement[]} elementArray - Safka sanduuqa hubinta ama walxaha raadiyaha. * @param {string} value - Qiimaha la raadinayo. * @return {HTMLInputElement} */ Morebits.QuickForm.getCheckboxOrRadio = function QuickFormGetCheckboxOrRadio(elementArray, value) { const found = $.grep(elementArray, (el) => el.value === value); if (found.length > 0) { return found[0]; } return null; }; /** * Waxay soo celinaysaa &lt;div> ka kooban shayga foomka, ama shayga foomka laftiisa * Waxaa laga yaabaa inuusan u shaqayn sidii la filayay sanduuqyada hubinta ama raadiyaha. * * @memberof Morebits.QuickForm * @param {HTMLElement} element * @return {HTMLElement} */ Morebits.QuickForm.getElementContainer = function QuickFormGetElementContainer(element) { // div-yada, madaxyada iyo fieldsets-ka, weelku waa shayga laftiisa if (element instanceof HTMLFieldSetElement || element instanceof HTMLDivElement || element instanceof HTMLHeadingElement) { return element; } // kuwa kalena, kaliya soo celi node-ka waalidka ah return element.parentNode; }; /** * Waxay helaysaa shayga HTML ee ka kooban sumadda shayga foomka la bixiyay * (inta badan isticmaalka gudaha). * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {HTMLElement} */ Morebits.QuickForm.getElementLabelObject = function QuickFormGetElementLabelObject(element) { // badhamada, div-yada iyo madaxyada, sumaddu waxay saaran tahay shayga laftiisa if (element.type === 'button' || element.type === 'submit' || element instanceof HTMLDivElement || element instanceof HTMLHeadingElement) { return element; // fieldsets-ka, sumaddu waa shayga carruurta ah ee <legend> } else if (element instanceof HTMLFieldSetElement) { return element.getElementsByTagName('legend')[0]; // sanduuqyada qoraalka, sumaddu waa shayga walaasha ah ee <h5> } else if (element instanceof HTMLTextAreaElement) { return element.parentNode.getElementsByTagName('h5')[0]; } // kuwa kalena, sumaddu waa shayga walaasha ah ee <label> return element.parentNode.getElementsByTagName('label')[0]; }; /** * Waxay helaysaa qoraalka sumadda ee shayga. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {string} */ Morebits.QuickForm.getElementLabel = function QuickFormGetElementLabel(element) { const labelElement = Morebits.QuickForm.getElementLabelObject(element); if (!labelElement) { return null; } return labelElement.firstChild.textContent; }; /** * Waxay dejinaysaa sumadda shayga qoraalka la bixiyay. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @param {string} labelText * @return {boolean} True haddii ay guulaysatay, false haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.setElementLabel = function QuickFormSetElementLabel(element, labelText) { const labelElement = Morebits.QuickForm.getElementLabelObject(element); if (!labelElement) { return false; } labelElement.firstChild.textContent = labelText; return true; }; /** * Waxay kaydisaa sumadda hadda ee shayga, waxayna si ku-meel-gaar ah u dejinaysaa sumadda qoraalka la bixiyay. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @param {string} temporaryLabelText * @return {boolean} `true` haddii ay guulaysatay, `false` haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.overrideElementLabel = function QuickFormOverrideElementLabel(element, temporaryLabelText) { if (!element.hasAttribute('data-oldlabel')) { element.setAttribute('data-oldlabel', Morebits.QuickForm.getElementLabel(element)); } return Morebits.QuickForm.setElementLabel(element, temporaryLabelText); }; /** * Waxay soo celinaysaa sumadda ay kaydisay overrideElementLabel. * * @memberof Morebits.QuickForm * @param {(HTMLElement|Morebits.QuickForm.Element)} element * @return {boolean} True haddii ay guulaysatay, false haddii shayga sumaddu aanu jirin. */ Morebits.QuickForm.resetElementLabel = function QuickFormResetElementLabel(element) { if (element.hasAttribute('data-oldlabel')) { return Morebits.QuickForm.setElementLabel(element, element.getAttribute('data-oldlabel')); } return null; }; /** * Waxay soo bandhigaysaa ama qarisaa shay foom ah oo ay la socdaan sumaddiisa iyo tilmaam qalabkiisa. * * @memberof Morebits.QuickForm * @param {(HTMLElement|jQuery|string)} element - Shayga HTML/jQuery, ama xarigga xulashada jQuery. * @param {boolean} [visibility] - Ka bood tan si aad u beddesho muuqashada. */ Morebits.QuickForm.setElementVisibility = function QuickFormSetElementVisibility(element, visibility) { $(element).toggle(visibility); }; /** * Waxay soo bandhigaysaa ama qarisaa astaanta calaamadda su'aasha (taas oo soo bandhigaysa tilmaam qalabka) ee ku xigta shay foom ah. * * @memberof Morebits.QuickForm * @param {(HTMLElement|jQuery)} element * @param {boolean} [visibility] - Ka bood tan si aad u beddesho muuqashada. */ Morebits.QuickForm.setElementTooltipVisibility = function QuickFormSetElementTooltipVisibility(element, visibility) { $(Morebits.QuickForm.getElementContainer(element)).find('.morebits-tooltipButton').toggle(visibility); }; /** * @external HTMLFormElement */ /** * Hel walxaha la hubiyay ee foomka. * * @method external:HTMLFormElement.getChecked * @param {string} name - Hel hantida la hubiyay ee walxaha (tusaale ahaan sanduuqa hubinta * ama badhanka raadiyaha) oo wata magaca la bixiyay, ama dooro xulashooyinka leh selected * oo loo dejiyay true (ha isku dayin inaad isku darto select-yada iyo raadiyaha/sanduuqyada hubinta). * @param {string} [type] - Si ikhtiyaari ah u cayim midkood raadiyaha ama sanduuqa hubinta (waayo * dhacdada ah in labada sanduuq hubinta iyo badhamada raadiyuhu ay leeyihiin magac isku mid ah). * @return {string[]} - Waxa ku jira qiimayaasha walxaha leh magaca la bixiyay * hantida la hubiyay oo loo dejiyay true. */ HTMLFormElement.prototype.getChecked = function(name, type) { const elements = this.elements[name]; if (!elements) { return []; } const return_array = []; let i; if (elements instanceof HTMLSelectElement) { const options = elements.options; for (i = 0; i < options.length; ++i) { if (options[i].selected) { if (options[i].values) { return_array.push(options[i].values); } else { return_array.push(options[i].value); } } } } else if (elements instanceof HTMLInputElement) { if (type && elements.type !== type) { return []; } else if (elements.checked) { return [elements.value]; } } else { for (i = 0; i < elements.length; ++i) { if (elements[i].checked) { if (type && elements[i].type !== type) { continue; } if (elements[i].values) { return_array.push(elements[i].values); } else { return_array.push(elements[i].value); } } } } return return_array; }; /** * Waxay samaysaa sida {@link HTMLFormElement.getChecked|getChecked}, laakiin waxay wadataa walxaha aan la hubin. * * @method external:HTMLFormElement.getUnchecked * @param {string} name - Hel hantida la hubiyay ee walxaha (tusaale ahaan sanduuqa hubinta * ama badhanka raadiyaha) oo wata magaca la bixiyay, ama dooro xulashooyinka leh selected * oo loo dejiyay true (ha isku dayin inaad isku darto select-yada iyo raadiyaha/sanduuqyada hubinta). * @param {string} [type] - Si ikhtiyaari ah u cayim midkood raadiyaha ama sanduuqa hubinta (waayo * dhacdada ah in labada sanduuq hubinta iyo badhamada raadiyuhu ay leeyihiin magac isku mid ah). * @return {string[]} - Waxa ku jira qiimayaasha walxaha leh magaca la bixiyay * hantida la hubiyay oo loo dejiyay true. */ HTMLFormElement.prototype.getUnchecked = function(name, type) { const elements = this.elements[name]; if (!elements) { return []; } const return_array = []; let i; if (elements instanceof HTMLSelectElement) { const options = elements.options; for (i = 0; i < options.length; ++i) { if (!options[i].selected) { if (options[i].values) { return_array.push(options[i].values); } else { return_array.push(options[i].value); } } } } else if (elements instanceof HTMLInputElement) { if (type && elements.type !== type) { return []; } else if (!elements.checked) { return [elements.value]; } } else { for (i = 0; i < elements.length; ++i) { if (!elements[i].checked) { if (type && elements[i].type !== type) { continue; } if (elements[i].values) { return_array.push(elements[i].values); } else { return_array.push(elements[i].value); } } } } return return_array; }; /** * Qalab gacan ka geysta habaynta ciwaanada IP-ga. * * @namespace Morebits.ip * @memberof Morebits */ Morebits.ip = { /** * Waxay u beddeshaa ciwaanka IPv6 qaabka caadiga ah ee uu kaydiyo oo uu isticmaalo MediaWiki. * Turjumaadda JavaScript ee {@link https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/8eb6ac3e84ea3312d391ca96c12c49e3ad0753bb/includes/utils/IP.php#131|`IP::sanitizeIP()`} * shaqada ka timid maktabadda IPUtils. Ciwaanradu waa kuwo faahfaahsan, xarfaha waaweyn, * la caadiyeeyay, oo lagu ballaariyay 8 eray. * * @param {string} address - Ciwaanka IPv6, oo wata ama aan wadan CIDR. * @return {string} */ sanitizeIPv6: function(address) { address = address.trim(); if (address === '') { return null; } if (!mw.util.isIPv6Address(address, true)) { return address; // wax kale oo la sameeyo ma jiraan ciwaannada IPv4 ama kuwa aan ansax ahayn } // Meesha ka saar wax kasta oo bannaan, u beddel xarfaha waaweyn address = address.toUpperCase(); // Ballaari gaabinta eber-ka const abbrevPos = address.indexOf('::'); if (abbrevPos > -1) { // Waan ognahay in tani ay tahay IPv6 ansax ah. Hel tusmada ugu dambeysa ee // ciwaanka ka hor nambar kasta oo CIDR ah (tusaale "a:b:c::/24"). const CIDRStart = address.indexOf('/'); const addressEnd = CIDRStart !== -1 ? CIDRStart - 1 : address.length - 1; // Haddii '::' ay ku taal bilowga... let repeat, extra, pad; if (abbrevPos === 0) { repeat = '0:'; extra = address === '::' ? '0' : ''; // ciwaanka '::' pad = 9; // 7+2 (oo ay sabab u tahay '::') // Haddii '::' ay ku taal dhammaadka... } else if (abbrevPos === (addressEnd - 1)) { repeat = ':0'; extra = ''; pad = 9; // 7+2 (oo ay sabab u tahay '::') // Haddii '::' ay ku taal dhexda... } else { repeat = ':0'; extra = ':'; pad = 8; // 6+2 (oo ay sabab u tahay '::') } let replacement = repeat; pad -= address.split(':').length - 1; for (let i = 1; i < pad; i++) { replacement += repeat; } replacement += extra; address = address.replace('::', replacement); } // Ka saar eberrada hordhaca ah ee baloog kasta sida loo baahdo return address.replace(/(^|:)0+([0-9A-Fa-f]{1,4})/g, '$1$2'); }, /** * Go'aami haddii ciwaanka IP-ga la bixiyay uu yahay kala duwanaansho (range). Kaliya waxay ku xiraysaa * `mw.util.isIPAddress` iyada oo wadata iyo iyada oo aan wadan ikhtiyaarka `allowBlock`. * * @param {string} ip * @return {boolean} - True haddii la bixiyay kala duwanaansho ciwaan IP oo ansax ah, false haddii kale. */ isRange: function(ip) { return mw.util.isIPAddress(ip, true) && !mw.util.isIPAddress(ip); }, /** * Hubi in kala duwanaanshiyaha IP-ga uu ku jiro xadka CIDR. Inta badan waxay noqon kartaa mid faa'iido leh * iyada oo lala kaashanayo `wgRelevantUserName`. Xadka CIDR waxaa si adag loogu qeexay /16 * ee IPv4 iyo /32 ee IPv6. * * @return {boolean} - True ee kala duwanaanshiyaha ansaxa ah ee ku dhex jira xadka CIDR, * haddii kale false (kala duwanaanshiyaha ka baxsan xadka, hal IPs, aan ahayn IPs). */ validCIDR: function(ip) { if (Morebits.ip.isRange(ip)) { const subnet = parseInt(ip.match(/\/(\d{1,3})$/)[1], 10); if (subnet) { // Waa inay noqotaa mid xad-dhaaf ah if (mw.util.isIPv6Address(ip, true)) { if (subnet >= 32) { return true; } } else { if (subnet >= 16) { return true; } } } } return false; }, /** * Hel /64 subnet ee ciwaanka IPv6. * * @param {string} ipv6 - Ciwaanka IPv6, oo wata ama aan wadan subnet. * @return {boolean|string} - False haddii uusan ahayn IPv6 ama uu ka weyn yahay 64, * haddii kale ciwaanka /64 (ee la nadiifiyey). */ get64: function(ipv6) { if (!ipv6 || !mw.util.isIPv6Address(ipv6, true)) { return false; } const subnetMatch = ipv6.match(/\/(\d{1,3})$/); if (subnetMatch && parseInt(subnetMatch[1], 10) < 64) { return false; } ipv6 = Morebits.ip.sanitizeIPv6(ipv6); const ip_re = /^((?:[0-9A-F]{1,4}:){4})(?:[0-9A-F]{1,4}:){3}[0-9A-F]{1,4}(?:\/\d{1,3})?$/; // eslint-disable-next-line no-useless-concat return ipv6.replace(ip_re, '$1' + '0:0:0:0/64'); } }; /** * Shaqooyin caawiye ah si loo maamulo xargaha (strings). * * @namespace Morebits.string * @memberof Morebits */ Morebits.string = { /** * @param {string} str * @return {string} */ toUpperCaseFirstChar: function(str) { str = str.toString(); return str.slice(0, 1).toUpperCase() + str.slice(1); }, /** * @param {string} str * @return {string} */ toLowerCaseFirstChar: function(str) { str = str.toString(); return str.slice(0, 1).toLowerCase() + str.slice(1); }, /** * Waxay bixisaa safka xargaha hoose (substrings) ee `str` - ka bilaabmaya `start` iyo * ku dhammaanaya `end` - kaas oo aan ku jirin `skiplist`. Waxaa loogu talagalay in lagu isticmaalo * wikitext-ka leh qaababka (templates) ama xiriirinta. * * @param {string} str * @param {string} start * @param {string} end * @param {(string[]|string)} [skiplist] * @return {string[]} * @throws {Error} Haddii `start` iyo `end` xarguhu aysan ahayn dherer isku mid ah. * @throws {Error} Haddii `skiplist` uusan ahayn saf ama xarig */ splitWeightedByKeys: function(str, start, end, skiplist) { if (start.length !== end.length) { throw new Error('calaamadda bilowga iyo calaamadda dhammaadka waa inay ahaadaan dherer isku mid ah'); } let level = 0; let initial = null; const result = []; if (!Array.isArray(skiplist)) { if (skiplist === undefined) { skiplist = []; } else if (typeof skiplist === 'string') { skiplist = [skiplist]; } else { throw new Error('beegsiga skiplist ee aan khusayn'); } } for (let i = 0; i < str.length; ++i) { for (let j = 0; j < skiplist.length; ++j) { if (str.substr(i, skiplist[j].length) === skiplist[j]) { i += skiplist[j].length - 1; continue; } } if (str.substr(i, start.length) === start) { if (initial === null) { initial = i; } ++level; i += start.length - 1; } else if (str.substr(i, end.length) === end) { --level; i += end.length - 1; } if (!level && initial !== null) { result.push(str.substring(initial, i + 1)); initial = null; } } return result; }, /** * Waxay qaabaysaa "sababta" xorta ah (ee ka timid sanduuqa qoraalka) tirtiridda/qaababka kale * ee beddelka noqon doona, (tusaale PROD, XFD, RPP). * Waxay maamushaa `|` oo ka baxsan calaamadda nowiki. * Ikhtiyaar ahaan, waxay sidoo kale ku dartaa saxiix haddii uusan horay u jirin. * * @param {string} str * @param {boolean} [addSig] * @return {string} */ formatReasonText: function(str, addSig) { let reason = (str || '').toString().trim(); const unbinder = new Morebits.Unbinder(reason); // eslint-disable-next-line no-useless-concat unbinder.unbind('<no' + 'wiki>', '</no' + 'wiki>'); unbinder.content = unbinder.content.replace(/\|/g, '|'); reason = unbinder.rebind(); if (addSig) { const sig = '[[User:Isma4l|Isma4l]] ([[User talk:Isma4l|wadahadal]]) 16:53, 28 Oktoobar 2026 (UTC)', sigIndex = reason.lastIndexOf(sig); if (sigIndex === -1 || sigIndex !== reason.length - sig.length) { reason += ' ' + sig; } } return reason.trim(); }, /** * Waxay qaabaysaa "sabab" (ee ka timid sanduuqa qoraalka) si loogu daro log-ga meesha isticmaalaha (userspace). * Waxay ku beddeshaa xariiqyada cusub {{Pb}}, waxayna ku dartaa `#` dheeri ah kahor * walxaha liiska si loo helo qaabayn habboon. * * @param {string} str * @return {string} */ formatReasonForLog: function(str) { return str // maamul jabitaanka xariiqyada, kuwaas oo haddii kale jebin lahaa nambarka .replace(/\n+/g, '{{pb}}') // geli # dheeri ah hortaada ka hor walxaha liiska calaamadaysan ama la nambareeyay .replace(/^(#+)/mg, '#$1') .replace(/^(\*+)/mg, '#$1'); }, /** * Sida `String.prototype.replace()`, laakiin waxay ka baxsataa astaamaha dollar-ka ee * xarigga beddelka. Faa'iido leh marka xarigga beddelku yahay 4 * mid aan la cayimin, sida magaca isticmaalaha ama gelinta isticmaalaha ee xorta ah, oo ay ku jiri karaan * astaamaha dollar-ka. * * @param {string} string - Qoraalka lagu beddelayo. * @param {(string|RegExp)} pattern * @param {string} replacement * @return {string} */ safeReplace: function morebitsStringSafeReplace(string, pattern, replacement) { return string.replace(pattern, replacement.replace(/\$/g, '$$$$')); }, /** * Go'aami haddii dhicitaanka uu bixiyay isticmaalahu loo tixgelin doono mid * aan xad lahayn (infinite) MW. * * @see {@link https://phabricator.wikimedia.org/T68646} * * @param {string} expiry * @return {boolean} */ isInfinity: function morebitsStringIsInfinity(expiry) { return ['indefinite', 'infinity', 'infinite', 'never'].includes(expiry); }, /** * Waxay ka baxsataa xarig si loogu isticmaalo RegExp, iyada oo ku beddeshay meelaha bannaan iyo * hooseeyayaasha `[_ ]` maadaama inta badan ay yihiin kuwo isu eg. * * @param {string} text - Xarigga laga baxsanayo. * @return {string} - Qoraalka ka baxsaday. */ escapeRegExp: function(text) { return mw.util.escapeRegExp(text).replace(/ |_/g, '[_ ]'); } }; /** * Shaqooyin caawiye ah si loo maamulo safafka (arrays). * * @namespace Morebits.array * @memberof Morebits */ Morebits.array = { /** * Ka saar walxaha laba-laabantay (duplication) safka. * * @param {Array} arr * @return {Array} Nuqul ka mid ah safka oo laga saaray walxaha laba-laabantay. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ uniq: function(arr) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.uniq'); } return arr.filter((item, idx) => arr.indexOf(item) === idx); }, /** * Ka saar walxaha aan laba-laabnayn safka. * * @param {Array} arr * @return {Array} Nuqul ka mid ah safka oo ay ka saaran tahay tusaalaha ugu horreeya ee qiime kasta * oo la saaray; tusaalooyinka xiga ee qiimayaashaas (duplication) ayaa haraya. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ dups: function(arr) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.dups'); } return arr.filter((item, idx) => arr.indexOf(item) !== idx); }, /** * U qaybi saf safaf yar yar. * * @param {Array} arr * @param {number} size - Cabbirka xabbo kasta (marka laga reebo tan ugu dambeysa, oo noqon karta mid ka duwan). * @return {Array[]} Saf ka kooban safafka yar yar ee la jajabiyey. * @throws {Error} Marka la bixiyo shay aan ahayn saf. */ chunk: function(arr, size) { if (!Array.isArray(arr)) { throw new Error('Shay aan ahayn saf ayaa la gudbiyay Morebits.array.chunk'); } if (typeof size !== 'number' || size <= 0) { // ku dhowaad suurtogal ma aha in la sameeyo wax :) return [arr]; // waxaan soo celinaa saf ka kooban safkan. } const numChunks = Math.ceil(arr.length / size); const result = new Array(numChunks); for (let i = 0; i < numChunks; i++) { result[i] = arr.slice(i * size, (i + 1) * size); } return result; } }; /** * Qalab kor u qaadaya menu-yada select2. Eeg twinklewarn, twinklexfd, * twinkleblock tusaalooyinka isticmaalka. * * @see {@link https://select2.org/} * * @namespace Morebits.select2 * @memberof Morebits * @requires jQuery.select2 */ Morebits.select2 = { matchers: { /** * Qalab waafajiye gaar ah oo haddii magaca optgroup uu waafaqo, dhammaan xulashooyinka kooxdaas * la tusi doono, sida jquery.chosen. */ optgroupFull: function(params, data) { const originalMatcher = $.fn.select2.defaults.defaults.matcher; const result = originalMatcher(params, data); if (result && params.term && data.text.toUpperCase().includes(params.term.toUpperCase())) { result.children = data.children; } return result; }, /** Qalab waafajiye gaar ah oo ka bilaabma bilowga erayada kaliya. */ wordBeginning: function(params, data) { const originalMatcher = $.fn.select2.defaults.defaults.matcher; const result = originalMatcher(params, data); if (!params.term || (result && new RegExp('\\b' + mw.util.escapeRegExp(params.term), 'i').test(result.text))) { return result; } return null; } }, /** Hoose ka xariiq qaybta la waafajiyay ee xulashooyinka. */ highlightSearchMatches: function(data) { const searchTerm = Morebits.select2SearchQuery; if (!searchTerm || data.loading) { return data.text; } const idx = data.text.toUpperCase().indexOf(searchTerm.toUpperCase()); if (idx < 0) { return data.text; } return $('<span>').append( data.text.slice(0, idx), $('<span>').css('text-decoration', 'underline').text(data.text.slice(idx, idx + searchTerm.length)), data.text.slice(idx + searchTerm.length) ); }, /** Dhexgal su'aasha inta ay dhacayso, si loogu isticmaalo highlightSearchMatches. */ queryInterceptor: function(params) { Morebits.select2SearchQuery = params && params.term; }, /** * Fur liiska hoos-u-dhaca oo billow raadinta marka `.select2-selection` uu leeyahay * diiradda (focus) oo furaha la riixo. * * @see {@link https://github.com/select2/select2/issues/3279#issuecomment-442524147} */ autoStart: function(ev) { if (ev.which < 48) { return; } let $target = $(ev.target).closest('.select2-container'); if (!$target.length) { return; } $target = $target.prev(); $target.select2('open'); const search = $target.data('select2').dropdown.$search || $target.data('select2').selection.$search; // Isticmaal DOM .focus() si aad uga gudubto dib-u-dhaca jQuery 3.6.0 (https://github.com/select2/select2/issues/5993) search[0].focus(); } }; /** * Si ku-meel-gaar ah u qari qayb ka mid ah xarigga inta aad ka shaqaynayso inta kale. * Waxaa isticmaala {@link Morebits.wikitext.Page#commentOutImage|Morebits.wikitext.Page.commentOutImage}. * * @memberof Morebits * @class * @param {string} string - Qoraalka bilowga ah ee la shaqaynayo. * @example var u = new Morebits.Unbinder('Hello world <!-- world --> world'); * u.unbind('<!--', '-->'); // qoraalka ku jira faallada wuu ahaanayaa sidii * u.content = u.content.replace(/world/g, 'earth'); * u.rebind(); // wuxuu bixiyaa 'Hello earth <!-- world --> earth' */ Morebits.Unbinder = function Unbinder(string) { if (typeof string !== 'string') { throw new Error('ma ahan xarig'); } /** Qoraalka la shaqaynayo. */ this.content = string; this.counter = 0; this.history = {}; this.prefix = '%UNIQ::' + Math.random() + '::'; this.postfix = '::UNIQ%'; }; Morebits.Unbinder.prototype = { /** * Qari goobta ay xireen `prefix` iyo `postfix` habaynta xarigga. * `prefix` iyo `postfix` waxaa loo isticmaali doonaa RegExp, markaas * walxaha u baahan in laga baxsado waa inay isticmaalaan `\\`. * * @param {string} prefix * @param {string} postfix * @throws {Error} Haddii midkood `prefix` ama `postfix` uu maqanyahay. */ unbind: function UnbinderUnbind(prefix, postfix) { if (!prefix || !postfix) { throw new Error('Labadaba prefix iyo postfix waa in la bixiyaa'); } const re = new RegExp(prefix + '([\\s\\S]*?)' + postfix, 'g'); this.content = this.content.replace(re, Morebits.Unbinder.getCallback(this)); }, /** * Soo celi qaybta qarsoon ee xarigga `content`. * * @return {string} Wax-soo-saarka la habeeyey. */ rebind: function UnbinderRebind() { let content = this.content; content.self = this; for (const current in this.history) { if (Object.prototype.hasOwnProperty.call(this.history, current)) { content = content.replace(current, this.history[current]); } } return content; }, prefix: null, // %UNIQ::0.5955981644938324:: postfix: null, // ::UNIQ% content: null, // string counter: null, // 0++ history: null // {} }; /** @memberof Morebits.Unbinder */ Morebits.Unbinder.getCallback = function UnbinderGetCallback(self) { return function UnbinderCallback(match) { const current = self.prefix + self.counter + self.postfix; self.history[current] = match; ++self.counter; return current; }; }; /* **************** Morebits.Date **************** */ /** * Abuur shay taariikh ah oo wata awoodaha habaynta ee la xoojiyay, a la * {@link https://momentjs.com/|moment.js}. Qaabka waqti-shaabadeedka MediaWiki sidoo kale waa * mid la aqbali karo, marka lagu daro wax walba oo ay aqbasho JS Date(). * * @memberof Morebits * @class */ Morebits.Date = class extends Date { constructor(...args) { // Hubi qaababka MediaWiki // Waa inuu noqdaa kan ugu horreeya maadaama firefox uu si khaldan u aqbalayo qaabka waqti-shaabadeedka, // iyada oo aan la haysan aagga wakhtiga (Sidoo kale eeg: #921, #936, #1174, #1187), iyo // xarigga 14-ka nambar ah ayaa loo tarjumi doonaa si ka duwan. if (args.length === 1) { const param = args[0]; if (/^\d{14}$/.test(param)) { // YYYYMMDDHHmmss const digitMatch = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/.exec(param); if (digitMatch) { // ..... sanadka ... bisha .. taariikhda ... saacada .... daqiiqada ..... ilbiriqsiga super(Date.UTC(digitMatch[1], digitMatch[2] - 1, digitMatch[3], digitMatch[4], digitMatch[5], digitMatch[6])); } else { super(...args); } } else if (typeof param === 'string') { // Waqti-shaabadeedka saxiixa Wikitext const dateParts = Morebits.l10n.signatureTimestampFormat(param); if (dateParts) { super(Date.UTC(...dateParts)); } else { super(...args); } } else { super(...args); } } else { super(...args); } if (!this.isValid()) { mw.log.warn('Billaabidda Morebits.Date ee aan ansax ahayn:', args); } } /** @return {boolean} */ isValid() { return !isNaN(this.getTime()); } /** * @param {(Date|Morebits.Date)} date * @return {boolean} */ isBefore(date) { return this.getTime() < date.getTime(); } /** * @param {(Date|Morebits.Date)} date * @return {boolean} */ isAfter(date) { return this.getTime() > date.getTime(); } /** @return {string} */ getUTCMonthName() { return Morebits.Date.localeData.months[this.getUTCMonth()]; } /** @return {string} */ getUTCMonthNameAbbrev() { return Morebits.Date.localeData.monthsShort[this.getUTCMonth()]; } /** @return {string} */ getMonthName() { return Morebits.Date.localeData.months[this.getMonth()]; } /** @return {string} */ getMonthNameAbbrev() { return Morebits.Date.localeData.monthsShort[this.getMonth()]; } /** @return {string} */ getUTCDayName() { return Morebits.Date.localeData.days[this.getUTCDay()]; } /** @return {string} */ getUTCDayNameAbbrev() { return Morebits.Date.localeData.daysShort[this.getUTCDay()]; } /** @return {string} */ getDayName() { return Morebits.Date.localeData.days[this.getDay()]; } /** @return {string} */ getDayNameAbbrev() { return Morebits.Date.localeData.daysShort[this.getDay()]; } /** * Ku dar tiro la bixiyay oo ah daqiiqado, saacado, maalmo, toddobaadyo, bilo, ama sano taariikhda. * Tani waxaa lagu sameeyaa halkii ay taallay (in-place). Shayga taariikhda ee la beddelay ayaa sidoo kale la soo celinayaa, taasoo u oggolaanaysa silsilad (chaining). * * @param {number} number - Waa inuu noqdaa nambar buuxa (integer). * @param {string} unit * @throws {Error} Haddii unug aan ansax ahayn ama aan la taageerin la bixiyo. * @return {Morebits.Date} */ add(number, unit) { let num = parseInt(number, 10); // caadiye if (isNaN(num)) { throw new Error('Nambar aan ansax ahayn "' + number + '" ayaa la bixiyay.'); } unit = unit.toLowerCase(); // caadiye const unitMap = Morebits.Date.unitMap; let unitNorm = unitMap[unit] || unitMap[unit + 's']; // si labada qaab ee kelidii ah iyo wadarta ah ay u shaqeeyaan if (unitNorm) { // Ma jiraan shaqooyin usbuuc oo ku dhex dhis an, markaa halkii aad ka dhisi lahayd getWeek/setWeek ee ISO, kaliya dhufo // Malaha looma isticmaali karo isbeddellada Julian->Gregorian, iwm. if (unitNorm === 'Week') { unitNorm = 'Date'; num *= 7; } this['set' + unitNorm](this['get' + unitNorm]() + num); return this; } throw new Error('Unug aan ansax ahayn "' + unit + '": Kaliya ' + Object.keys(unitMap).join(', ') + ' ayaa la oggol yahay.'); } /** * Ka jar tiro la bixiyay oo ah daqiiqado, saacado, maalmo, toddobaadyo, bilo, ama sano taariikhda. * Tani waxaa lagu sameeyaa halkii ay taallay (in-place). Shayga taariikhda ee la beddelay ayaa sidoo kale la soo celinayaa, taasoo u oggolaanaysa silsilad (chaining). * * @param {number} number - Waa inuu noqdaa nambar buuxa (integer). * @param {string} unit * @throws {Error} Haddii unug aan ansax ahayn ama aan la taageerin la bixiyo. * @return {Morebits.Date} */ subtract(number, unit) { return this.add(-number, unit); } /** * Qaabee taariikhda oo ka dhig xarig iyadoo loo eegayo xarigga qaabka la bixiyay. * Sintakiska beddelka waa qayb ka mid ah kan ku jira moment.js: * * | Sintakiska | Wax-soo-saarka | * |------------|-----------------| * | H | Saacadaha (24-saacadood) | * | HH | Saacadaha (24-saacadood, oo lagu buuxiyay 2 nambar) | * | h | Saacadaha (12-saacadood) | * | hh | Saacadaha (12-saacadood, oo lagu buuxiyay 2 nambar) | * | A | AM ama PM | * | m | Daqiiqadaha | * | mm | Daqiiqadaha (oo lagu buuxiyay 2 nambar) | * | s | Ilbiriqisyada | * | ss | Ilbiriqisyada (oo lagu buuxiyay 2 nambar) | * | SSS | Jajabka millisekunde, 3 nambar | * | d | Nambarka maalinta ee usbuuca (Sun=0) | * | ddd | Magaca maalinta oo gaaban | * | dddd | Magaca maalinta oo buuxa | * | D | Taariikhda | * | DD | Taariikhda (oo lagu buuxiyay 2 nambar) | * | M | Nambarka bisha (1-indexed) | * | MM | Nambarka bisha (1-indexed, oo lagu buuxiyay 2 nambar) | * | MMM | Magaca bisha oo gaaban | * | MMMM | Magaca bisha oo buuxa | * | Y | Sanadka | * | YY | Labada nambar ee ugu dambeeya sanadka (20 sanadka 2020, 42 sanadka 1942) | * | YYYY | Sanadka (la mid ah `Y`) | * * @param {string} formatstr - Qaabee taariikhda oo ka dhig xarig, adigoo isticmaalaya * sintakiska beddelka. Isticmaal `[` iyo `]` si aad uga baxsatid walxaha. Haddii aan la bixin, * waxay soo celin doontaa xarigga ISO-8601-formatted. * @param {(string|number)} [zone=system] - `system` (aagga wakhtiga caadiga ah ee daalacashada), * `utc`, ama cayim aag wakhti oo ah lambarka daqiiqadaha ee qaraabada la ah UTC. * @return {string} */ format(formatstr, zone) { if (!this.isValid()) { return 'Taariikh aan ansax ahayn'; // Soo saar runta, waxay ka fiican tahay "NaNNaNNan NaN:NaN" ama wixii la mid ah } let udate = this; // abuur shay taariikh cusub oo ka koobnaan doona taariikhda lagu soo bandhigayo wakhtiga nidaamka if (zone === 'utc') { udate = new Morebits.Date(this.getTime()).add(this.getTimezoneOffset(), 'minutes'); } else if (typeof zone === 'number') { // u beddel utc, ka dibna ku dar cilladda utc ee la bixiyay udate = new Morebits.Date(this.getTime()).add(this.getTimezoneOffset() + zone, 'minutes'); } // u deji ISOString haddii aysan jirin if (!formatstr) { return udate.toISOString(); } const pad = function(num, len) { len = len || 2; // Ilaa dhererka 00 + 1 return ('00' + num).toString().slice(0 - len); }; const h24 = udate.getHours(), m = udate.getMinutes(), s = udate.getSeconds(), ms = udate.getMilliseconds(); const D = udate.getDate(), M = udate.getMonth() + 1, Y = udate.getFullYear(); const h12 = h24 % 12 || 12, amOrPm = h24 >= 12 ? 'PM' : 'AM'; const replacementMap = { HH: pad(h24), H: h24, hh: pad(h12), h: h12, A: amOrPm, mm: pad(m), m: m, ss: pad(s), s: s, SSS: pad(ms, 3), dddd: udate.getDayName(), ddd: udate.getDayNameAbbrev(), d: udate.getDay(), DD: pad(D), D: D, MMMM: udate.getMonthName(), MMM: udate.getMonthNameAbbrev(), MM: pad(M), M: M, YYYY: Y, YY: pad(Y % 100), Y: Y }; const unbinder = new Morebits.Unbinder(formatstr); // ka baxsashada waxyaabaha u dhexeeya [...] unbinder.unbind('\\[', '\\]'); unbinder.content = unbinder.content.replace( /* Qoraallada Regex: * d(d{2,3})? wuxuu la mid yahay si sax ah 1, 3 ama 4 dhacdo oo ah 'd' ('dd' waxaa Loo tixgeliyaa inay tahay laba-laabashada 'd') * Y{1,2}(Y{2})? wuxuu la mid yahay si sax ah 1, 2 ama 4 dhacdo oo ah 'Y' */ /H{1,2}|h{1,2}|m{1,2}|s{1,2}|SSS|d(d{2,3})?|D{1,2}|M{1,4}|Y{1,2}(Y{2})?|A/g, (match) => replacementMap[match] ); return unbinder.rebind().replace(/\[(.*?)\]/g, '$1'); } /** * Waxay bixisaa xarig wakhti qaraabo ah oo akhriska ku fiican sida "Shalay 6:43 PM" ama "Khamiistii la soo dhaafay 11:45 AM". * Sida `calendar` ee moment.js, laakiin wata taageerada aagga wakhtiga. * * @param {(string|number)} [zone=system] - 'system' (aagga wakhtiga caadiga ah ee daalacashada), * 'utc' (ee UTC), ama cayim aag wakhti oo ah nambarka daqiiqadaha ka dambeeya UTC. * @return {string} */ calendar(zone) { // Ebar ka dhig saacadaha, daqiiqadaha, ilbiriqisyada iyo millisekundisyada - adigoo ilaalinaya taariikhda oo keliya; // hel farqiga. Xusuusnow in setHours() ay soo celinays驮 wax la mid ah getTime(). const dateDiff = (new Date().setHours(0, 0, 0, 0) - new Date(this).setHours(0, 0, 0, 0)) / 8.64e7; switch (true) { case dateDiff === 0: return this.format(Morebits.Date.localeData.relativeTimes.thisDay, zone); case dateDiff === 1: return this.format(Morebits.Date.localeData.relativeTimes.prevDay, zone); case dateDiff > 0 && dateDiff < 7: return this.format(Morebits.Date.localeData.relativeTimes.pastWeek, zone); case dateDiff === -1: return this.format(Morebits.Date.localeData.relativeTimes.nextDay, zone); case dateDiff < 0 && dateDiff > -7: return this.format(Morebits.Date.localeData.relativeTimes.thisWeek, zone); default: return this.format(Morebits.Date.localeData.relativeTimes.other, zone); } } /** * Hel tibaax joogto ah (regular expression) oo la mid ah cinwaannada qaybaha wikitext, sida * `==December 2019==` ama `=== Jan 2018 ===`. * * @return {RegExp} */ monthHeaderRegex() { return new RegExp('^(==+)\\s*(?:' + this.getUTCMonthName() + '|' + this.getUTCMonthNameAbbrev() + ')\\s+' + this.getUTCFullYear() + '\\s*\\1', 'mg'); } /** * Waxay abuurtaa cinwaan qayb wikitext ah oo wata bisha iyo sanadka. * * @param {number} [level=2] - Heerka cinwaanka. Gudbi 0 si aad u hesho qoraalka oo keliya * iyada oo aan lahayn calaamado wikitext ah (==). * @return {string} */ monthHeader(level) { // U deji 2, laakiin u oggolow 0 ama nambarada xarigga ah level = parseInt(level, 10); level = isNaN(level) ? 2 : level; const header = '='.repeat(level); const text = this.getUTCMonthName() + ' ' + this.getUTCFullYear(); if (header.length) { // cinwaan wikitext-format ah return header + ' ' + text + ' ' + header; } return text; // Qoraalka oo keliya } }; /** * Xargaha deegaanka ee habaynta taariikhda. * * @memberof Morebits.Date * @type {object.<string, string>} * @property {string[]} months * @property {string[]} monthsShort * @property {string[]} days * @property {string[]} daysShort * @property {object.<string, string>} relativeTimes * @private */ Morebits.Date.localeData = { // magacyada fariimaha halkan waxay u dhigmaan magacyada fariimaha MediaWiki months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], relativeTimes: { thisDay: '[Today at] h:mm A', prevDay: '[Yesterday at] h:mm A', nextDay: '[Tomorrow at] h:mm A', thisWeek: 'dddd [at] h:mm A', pastWeek: '[Last] dddd [at] h:mm A', other: 'YYYY-MM-DD' } }; /** * Khariidadee unugyada magacyada shaqada ee getter/setter, ee loogu talagalay hababka `add` iyo `subtract`. * * @memberof Morebits.Date * @type {object.<string, string>} * @property {string} seconds * @property {string} minutes * @property {string} hours * @property {string} days * @property {string} weeks * @property {string} months * @property {string} years */ Morebits.Date.unitMap = { seconds: 'Seconds', minutes: 'Minutes', hours: 'Hours', days: 'Date', weeks: 'Week', // Ma aha shaqo laakiin waxaa lagu maamulaa `add` iyada oo la adeegsanayo dhu-dhufasho xariif ah months: 'Month', years: 'FullYear' }; /* **************** Morebits.wiki **************** */ /** * Shayada kala duwan ee wax ka beddelka wiki iyo helitaanka API, oo ay ku jiraan * {@link Morebits.wiki.Api} iyo {@link Morebits.wiki.Page}. * * @namespace Morebits.wiki * @memberof Morebits */ Morebits.wiki = {}; /* **************** Morebits.wiki.actionCompleted **************** */ /** * @memberof Morebits.wiki * @type {number} */ Morebits.wiki.numberOfActionsLeft = 0; /** * @memberof Morebits.wiki * @type {number} */ Morebits.wiki.nbrOfCheckpointsLeft = 0; /** * Soo bandhig fariin iyo/ama u gudub bogga marka hawlaha la dhammeeyo. * * Wicitaan kasta oo loo sameeyo Morebits.wiki.Api.post() wuxuu keenaa dirista jawaab celin * asynchronous ah. Jawaab celin kastaa waxay iyaduna samayn kartaa wicitaan dheeri ah oo ku socda * Morebits.wiki.Api.post() si loo sii wado silsiladda habaynta. Gabagabada * jawaab-celinta ugu dambeysa ee silsiladda habaynta, suurtogal ma aha * in si fudud loogu noqdo qofkii wacay ee asalka ahaa sababtoo ah ma jiro xiriir wicitaan * oo dib ugu geynaya xaaladdii asalka ahayd. Halkaas waxaa lagu wacaa * Morebits.wiki.actionCompleted.event() si loo soo bandhigo natiijada isticmaalaha * iyo in la fuliyo leexinta bogga ikhtiyaariga ah. * * Go'aaminta goorta la wacayo Morebits.wiki.actionCompleted.event() waxaa * maamula doorsoomayaasha caalamiga ah Morebits.wiki.numberOfActionsLeft iyo * Morebits.wiki.nbrOfCheckpointsLeft. Morebits.wiki.numberOfActionsLeft waxaa la kordhiyaa * bilowga wicitaan kasta oo Morebits.wiki.Api ah waxaana laga dhimayaa * marka la dhammeeyo shaqada jawaab-celinta. Haddii shaqada jawaab-celintu * aysan abuurin shay cusub oo Morebits.wiki.Api ah ka hor inta aysan bixin, waa * tillaabada ugu dambeysa ee silsiladda habaynta waxaana la wici doonaa Morebits.wiki.actionCompleted.event(). * * Ikhtiyaar ahaan, kuwa waca waxay isticmaali karaan Morebits.wiki.addCheckpoint() si ay u muujiyaan * in habayntu aysan dhammaystirnayn gabagabada shaqada jawaab-celinta * ugu dambeysa. Tani waxaa loo isticmaalaa hawlaha xirmada (batch). Dhamaadka xirmada * waxaa lagu calaamadiyaa iyadoo la wacayo Morebits.wiki.removeCheckpoint(). * * @memberof Morebits.wiki */ Morebits.wiki.actionCompleted = function(self) { if (--Morebits.wiki.numberOfActionsLeft <= 0 && Morebits.wiki.nbrOfCheckpointsLeft <= 0) { Morebits.wiki.actionCompleted.event(self); } }; // Beddel falka la rabo /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.event = function() { if (Morebits.wiki.actionCompleted.notice) { Morebits.Status.actionCompleted(Morebits.wiki.actionCompleted.notice); } if (Morebits.wiki.actionCompleted.redirect) { // haddii uusan ahaan URL, ka dhig mid. Tusaale: Tani waxay ka jabtaa maqaallada 'http://', 'ftp://', iyo kuwa la mid ah. if (!(/^\w+:\/\//).test(Morebits.wiki.actionCompleted.redirect)) { Morebits.wiki.actionCompleted.redirect = mw.util.getUrl(Morebits.wiki.actionCompleted.redirect); if (Morebits.wiki.actionCompleted.followRedirect === false) { Morebits.wiki.actionCompleted.redirect += '?redirect=no'; } } window.setTimeout(() => { window.location = Morebits.wiki.actionCompleted.redirect; }, Morebits.wiki.actionCompleted.timeOut); } }; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.timeOut = typeof window.wpActionCompletedTimeOut === 'undefined' ? 5000 : window.wpActionCompletedTimeOut; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.redirect = null; /** @memberof Morebits.wiki */ Morebits.wiki.actionCompleted.notice = null; /** @memberof Morebits.wiki */ Morebits.wiki.addCheckpoint = function() { ++Morebits.wiki.nbrOfCheckpointsLeft; }; /** @memberof Morebits.wiki */ Morebits.wiki.removeCheckpoint = function() { if (--Morebits.wiki.nbrOfCheckpointsLeft <= 0 && Morebits.wiki.numberOfActionsLeft <= 0) { Morebits.wiki.actionCompleted.event(); } }; /* **************** Morebits.wiki.Api **************** */ /** * Si sahlan oo loola hadlo MediaWiki API. Waxay aqbashaa qaababka json ama xml * (caadiga ah); haddii json la doorto, waxay u degi doontaa si caadi ah `formatversion=2` * ilaa si kale loogu sheego. Sidoo kale, waxay ku khasbeysaa `errorformat` cusub, * iyada oo u degaysa `html` haddii aan la cayimin. `uselang` waxaa lagu khasbay luqadda * nuxurka ee wiki-ga. * * Koodka cusub, isticmaalka 3-da xuduudood ee ugu dambeeya waa in laga fogaadaa, halkaas * waxaa la isticmaalaa {@link Morebits.wiki.Api#setStatusElement|setStatusElement()} si loo xiro * shayga xaaladda (haddii loo baahdo) oo la isticmaalo `.then()` ama `.catch()` ee ballan-qaadka * uu soo celiyo `post()`, halkii laga cayimi lahaa jawaab-celinta `onSuccess` ama * `onFailure`. * * @memberof Morebits.wiki *@class * @param {string} currentAction - Falalka hadda jira (looga baahan yahay). * @param {Object} query - Weydiinta (looga baahan yahay). * @param {Function} [onSuccess] - Shaqada la wacayo marka codsigu guulaysto. * @param {Morebits.Status} [statusElement] - Shay Morebits.Status ah oo loo isticmaalo fariimaha xaaladda. * @param {Function} [onError] - Shaqada la wacayo haddii qalad dhaco. */ Morebits.wiki.Api = function(currentAction, query, onSuccess, statusElement, onError) { this.currentAction = currentAction; this.query = query; this.query.assert = 'user'; // Ku khasab qaababka qaladka cusub, iyada oo la doorbidayo html if (!query.errorformat || !['wikitext', 'plaintext'].includes(query.errorformat)) { this.query.errorformat = 'html'; } // Si cad u isticmaal luqadda nuxurka ee wiki-ga si loo yareeyo jahwareerka, // eeg #1179 wada xaajoodka this.query.uselang = 'content'; this.query.errorlang = 'uselang'; this.query.errorsuselocal = 1; this.onSuccess = onSuccess; this.onError = onError; if (statusElement) { this.setStatusElement(statusElement); } else { this.statelem = new Morebits.Status(currentAction); } // JSON waxaa lagu isticmaalaa dhammaan Morebits/Twinkle, laakiin xml wuxuu ahaadaa midka caadiga ah ee waafajinta dib u dhaca (backwards compatibility) if (!query.format) { this.query.format = 'xml'; } else if (query.format === 'json' && !query.formatversion) { this.query.formatversion = '2'; } else if (!['xml', 'json'].includes(query.format)) { this.statelem.error('Qaabka API aan ansax ahayn: waxaa la taageeraa oo keliya xml iyo json.'); } // Iska indhatir tags-ka weydiimaha iyo falalka aan la taageerin ee ugu badan, waxay soo saartaa digniino if (query.action && ['query', 'review', 'stabilize', 'watch'].includes(query.action)) { delete query.tags; } }; Morebits.wiki.Api.prototype = { currentAction: '', onSuccess: null, onError: null, parent: window, // isticmaal macnaha guud ee caalamiga ah haddii uusan jirin shay waalid ah query: null, response: null, responseXML: null, // isticmaalka `response` beddelkeeda; waxaa loo haystaa waafajinta dib u dhaca statelem: null, // magacan aan caadiga ahayn waxaa loo haystay waafajinta dib u dhaca statusText: null, // natiijada laga helay API-ga, inta badan "success" ama "error" errorCode: null, // koodka qaladka ee qoraalka gaaban, haddii ay jirto, sida ku xusan MediaWiki API errorText: null, // sharaxaadda qaladka oo buuxda, haddii ay jirto, badtokenRetry: false, // u deji true haddii tani ay tahay dib-u-dayis lagu sameeyay qalad badtoken ka dib /** * La soco shayga waalidka ee jawaab-celinta. * * @param {*} parent */ setParent: function(parent) { this.parent = parent; }, /** @param {Morebits.Status} statusElement */ setStatusElement: function(statusElement) { this.statelem = statusElement; this.statelem.status(this.currentAction); }, /** * Fuliy codsiga. * * @param {Object} callerAjaxParameters - Ha cayimin cabbir ilaa aad si dhab ah * u rabto inaad siiso jQuery cabbirro dheeri ah. * @return {jQuery.Promise} - Shay ballanqaad jQuery ah oo lagu xaliyay ama lagu diiday shayga api. */ post: function(callerAjaxParameters) { ++Morebits.wiki.numberOfActionsLeft; const queryString = $.map(this.query, (val, i) => { if (Array.isArray(val)) { return encodeURIComponent(i) + '=' + val.map(encodeURIComponent).join('|'); } else if (val !== undefined) { return encodeURIComponent(i) + '=' + encodeURIComponent(val); } }).join('&').replace(/^(.*?)(\btoken=[^&]*)&(.*)/, '$1$3&$2'); // token waa inuu noqdaa shayga ugu dambeeya ee xarigga weydiinta (bug TW-B-0013) const headers = { 'Api-User-Agent': morebitsWikiApiUserAgent }; if (this.query.action === 'parse') { // Sida uu qabo https://www.mediawiki.org/wiki/API:Etiquette headers['Promise-Non-Write-API-Action'] = 'true'; } const ajaxparams = $.extend({}, { context: this, type: this.query.action === 'query' ? 'GET' : 'POST', url: mw.util.wikiScript('api'), data: queryString, dataType: this.query.format, headers }, callerAjaxParameters); return $.ajax(ajaxparams).then( function onAPIsuccess(response, statusText) { this.statusText = statusText; this.response = this.responseXML = response; // Ku xaddid qaladka koowaad if (this.query.format === 'json') { this.errorCode = response.errors && response.errors[0].code; if (this.query.errorformat === 'html') { this.errorText = response.errors && response.errors[0].html; } else if (this.query.errorformat === 'wikitext' || this.query.errorformat === 'plaintext') { this.errorText = response.errors && response.errors[0].text; } } else { this.errorCode = $(response).find('errors error').eq(0).attr('code'); // Ku filan errorformats-ka html, wikitext, ama plaintext this.errorText = $(response).find('errors error').eq(0).text(); } if (typeof this.errorCode === 'string') { // API-du ma aysan jeclaysan waxa aan u sheegnay, tusaale ahaan bad edit token ama qalad abuurista bog return this.returnError(callerAjaxParameters); } // ku yeero jawaab-celinta guusha haddii mid la bixiyay if (this.onSuccess) { // u deji macnaha guud ee jawaab-celinta this.parent koodka cusub oo bixiy shayga API // sida doodda ugu horreysa ee jawaab-celinta (koodka dhaxalka ah) this.onSuccess.call(this.parent, this); } else { this.statelem.info('done'); } Morebits.wiki.actionCompleted(); return $.Deferred().resolveWith(this.parent, [this]); }, // kaliya shabakadda iyo khaladaadka server-ka ayaa gaara halkan - cabashooyinka API-ga laftiisa waxaa lagu qabtaa success() function onAPIfailure(jqXHR, statusText, errorThrown) { this.statusText = statusText; this.errorThrown = errorThrown; // inta badan waa aan la cayimin this.errorText = statusText + ' "' + jqXHR.statusText + '" ayaa dhacay markii lala xiriirayay API-ga.'; return this.returnError(); } ); }, returnError: function(callerAjaxParameters) { if (this.errorCode === 'badtoken' && !this.badtokenRetry) { this.statelem.warn('Calaamad (token) aan ansax ahayn. Helidda calaamad cusub iyo dib-u-dayis...'); this.badtokenRetry = true; // Hel CSRF token cusub oo dib u day. Haddii falka asalka ahi u baahdo nooc kale // oo ficil ah marka loo eego CSRF, waxaan samaynaynaa hal dib-u-dayis oo aan faa'iido lahayn ka hor intaanan bixin return Morebits.wiki.Api.getToken().then((token) => { this.query.token = token; return this.post(callerAjaxParameters); }); } this.statelem.error(this.errorText + ' (' + this.errorCode + ')'); // ku yeero jawaab-celinta guuldarrada haddii mid la bixiyay if (this.onError) { // u deji macnaha guud ee jawaab-celinta this.parent koodka cusub oo bixiy shayga API // sida doodda ugu horreysa ee jawaab-celinta koodka dhaxalka ah this.onError.call(this.parent, this); } // ha dhammaystirin falka si qaladku uu u sii ahaado mid muuqda return $.Deferred().rejectWith(this.parent, [this]); }, getStatusElement: function() { return this.statelem; }, getErrorCode: function() { return this.errorCode; }, getErrorText: function() { return this.errorText; }, getXML: function() { // waxaa loo haystaa waafajinta dib u dhaca, isticmaal getResponse() beddelkeeda return this.responseXML; }, getResponse: function() { return this.response; } }; /** * Soo qaado wikitext bog ka yimid. Kaydinta (caching) waa la hawlgeliyay iyadoo muddadu tahay 1 maalin. * * @param {string} title - Ciwaanka bogga * @return {Promise<string|null>} Waxay soo celinaysaa nuxurka bogga, ama null haddii uusan boggu jirin. */ Morebits.wiki.getCachedPage = function(title) { return new mw.Api({ userAgent: morebitsWikiApiUserAgent }).get({ action: 'query', prop: 'revisions', titles: title, rvprop: 'content', rvslots: '*', format: 'json', formatversion: '2', smaxage: '86400', // kaydi 1 maalin maxage: '86400', // kaydi 1 maalin uselang: 'content' }).then((data) => { const page = data.query.pages[0]; if (page.missing) { return null; } return page.revisions[0].slots.main.content; }); }; /** * Soo qaado JSON bog ka yimid. Kaydinta (caching) waa la hawlgeliyay iyadoo muddadu tahay 1 maalin. * * @param {string} title - Ciwaanka bogga * @return {Promise<string>} */ Morebits.wiki.getCachedJson = function(title) { return Morebits.wiki.getCachedPage(title).then((wikitext) => JSON.parse(wikitext)); }; var morebitsWikiApiUserAgent = 'morebits.js ([[w:WT:TW]])'; /** * Deji madaxa wakiilka isticmaalaha ee gaarka ah, kaas oo loo isticmaalo diiwaangelinta dhinaca server-ka. * Ogow in samaynta sidaas ay dejin doonto useragent-ka kasta `Morebits.wiki.Api` * habsocodka la fuliyo wixii ka dambeeya. * * @see {@link https://lists.wikimedia.org/pipermail/mediawiki-api-announce/2014-November/000075.html} * ku saabsan ogeysiiska asalka ah. * * @memberof Morebits.wiki.Api * @param {string} [ua=morebits.js ([[w:WT:TW]])] - Wakiilka isticmaalaha. Qiimaha caadiga ah * ee `morebits.js ([[w:WT:TW]])` waxaa lagu dari doonaa qiimo kasta oo la bixiyo. */ Morebits.wiki.Api.setApiUserAgent = function(ua) { morebitsWikiApiUserAgent = (ua ? ua + ' ' : '') + 'morebits.js ([[w:WT:TW]])'; }; /** * Hel CSRF token cusub marka la kulmo khaladaadka token-ka. * * @memberof Morebits.wiki.Api * @return {string} MediaWiki CSRF token. */ Morebits.wiki.Api.getToken = function() { const tokenApi = new Morebits.wiki.Api('Helidda token', { action: 'query', meta: 'tokens', type: 'csrf', format: 'json' }); return tokenApi.post().then((apiobj) => apiobj.response.query.tokens.csrftoken); }; /* **************** Morebits.wiki.Page **************** */ /** * Isticmaal MediaWiki API si aad u soo rarto bog oo ikhtiyaar ahaan ugu beddesho, u rarto, iwm. * * Kuwa waca looma oggola inay si toos ah u galaan sifooyinka fasalkan! * Helitaanka sifooyinka oo dhan waa iyada oo la marayo habka habboon ee get___() ama set___(). * * Kuwa waca waa inay dejiyaan {@link Morebits.wiki.actionCompleted.notice} iyo {@link Morebits.wiki.actionCompleted.redirect} * ka hor wicitaanka ugu horreeya ee {@link Morebits.wiki.Page.load()}. * * Mid kasta oo ka mid ah shaqooyinka jawaab-celinta wuxuu qaataa halbeeg (parameter) hal ah, kaas oo ah * tixraac ku socda shayga Morebits.wiki.Page ee diiwaangeliyay jawaab-celinta. * Shaqooyinka jawaab-celinta waxay ku yeeri karaan qaab kasta oo prototype ah ee Morebits.wiki.Page iyagoo adeegsanaya tixraacan. * * * Silsiladda wicitaanka ee hawlaha caadiga ah (jawaab-celinta isticmaalaha ugu dambeysa ee ikhtiyaariga ah lama tusi): * * - Wax ka beddel nuxurka hadda ee bogga (ma jiro khilaaf wax ka beddel): * `.load(userTextEditCallback) -> ctx.loadApi.post() -> * ctx.loadApi.post.success() -> ctx.fnLoadSuccess() -> userTextEditCallback() -> * .save() -> ctx.saveApi.post() -> ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * - Wax ka beddel nuxurka hadda ee bogga (oo wata khilaaf wax ka beddel): * `.load(userTextEditCallback) -> ctx.loadApi.post() -> * ctx.loadApi.post.success() -> ctx.fnLoadSuccess() -> userTextEditCallback() -> * .save() -> ctx.saveApi.post() -> ctx.loadApi.post.success() -> * ctx.fnSaveError() -> ctx.loadApi.post() -> ctx.loadApi.post.success() -> * ctx.fnLoadSuccess() -> userTextEditCallback() -> .save() -> * ctx.saveApi.post() -> ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * - Ku dar bog dhammaadkiisa (la mid ah prepend iyo newSection): * `.append() -> ctx.loadApi.post() -> ctx.loadApi.post.success() -> * ctx.fnLoadSuccess() -> ctx.fnAutoSave() -> .save() -> ctx.saveApi.post() -> * ctx.loadApi.post.success() -> ctx.fnSaveSuccess()` * * Xusuusin: * 1. Dhammaan shaqooyinka ka dambeeya Morebits.wiki.Api.post() waxaa si asynchronous ah loogu yeeraa maktabadda jQuery AJAX. * 2. Silsiladda append/prepend/newSection waxaa loo gaabin karaa si yar, * laakiin waxay u baahan doontaa nuqulayn muhiim ah oo koodka ah faa'iido yar awgeed. * * @memberof Morebits.wiki * @class * @param {string} pageName - Magaca bogga, oo ay ka horreeyaan meesha magaca (haddii ay jirto). * Bogga hadda jira, isticmaal `mw.config.get('wgPageName')`. * @param {string|Morebits.Status} [status] - Xarig qeexaya falka la bilaabayo, * ama shay Morebits.Status ah */ Morebits.wiki.Page = function(pageName, status) { if (!status) { status = 'Furidda bogga "' + pageName + '"'; } /** * Doorsoomayaasha macnaha guud ee gaarka ah (Private context variables). * * Macnahan guud laguma arki karo dibadda, sidaas darteed dhammaan xogta halkan ku jirtaa * waa in la gaaraa iyada oo la marayo shaqooyinka getter iyo setter. * * @private */ const ctx = { // duurka dhabarka ee sifooyinka dadweynaha pageName: pageName, pageExists: false, editSummary: null, changeTags: null, testActions: null, // saf haddii ay jiraan falal ansax ah callbackParameters: null, statusElement: status instanceof Morebits.Status ? status : new Morebits.Status(status), // - wax ka beddel (edit) pageText: null, editMode: 'all', // save() waxay ku beddeshaa nuxurka buuxa ee bogga si caadi ah appendText: null, // lama isticmaali karo pageText tan sababtoo ah pageText waxaa lo baahan yahay in la raaco leexin prependText: null, // lama isticmaali karo pageText tan sababtoo ah pageText waxaa lo baahan yahay in la raaco leexin newSectionText: null, newSectionTitle: null, createOption: null, minorEdit: false, botEdit: false, pageSection: null, maxConflictRetries: 2, maxRetries: 2, followRedirect: false, followCrossNsRedirect: true, watchlistOption: 'nochange', watchlistExpiry: null, discussionToolsAutoSubscribe: null, creator: null, timestamp: null, // - dib u soo celis (revert) revertOldID: null, // - rari (move) moveDestination: null, moveTalkPage: false, moveSubpages: false, moveSuppressRedirect: false, // - ilaali (protect) protectEdit: null, protectMove: null, protectCreate: null, protectCascade: null, // - tirtir (delete) deleteTalkPage: false, // - ka soo celi tirtirka (undelete) undeleteTalkPage: false, // - raadinta abuurista (creation lookup) lookupNonRedirectCreator: false, // - deji (stabilize) (FlaggedRevs) flaggedRevs: null, // xaaladda gudaha pageLoaded: false, csrfToken: null, loadTime: null, lastEditTime: null, pageID: null, contentModel: null, revertCurID: null, revertUser: null, watched: false, fullyProtected: false, suppressProtectWarning: false, conflictRetries: 0, retries: 0, // jawaab-celinta (callbacks) onLoadSuccess: null, onLoadFailure: null, onSaveSuccess: null, onSaveFailure: null, onLookupCreationSuccess: null, onLookupCreationFailure: null, onMoveSuccess: null, onMoveFailure: null, onDeleteSuccess: null, onDeleteFailure: null, onUndeleteSuccess: null, onUndeleteFailure: null, onProtectSuccess: null, onProtectFailure: null, onStabilizeSuccess: null, onStabilizeFailure: null, // shayada gudaha loadQuery: null, loadApi: null, saveApi: null, lookupCreationApi: null, moveApi: null, moveProcessApi: null, patrolApi: null, patrolProcessApi: null, triageApi: null, triageProcessListApi: null, triageProcessApi: null, deleteApi: null, deleteProcessApi: null, undeleteApi: null, undeleteProcessApi: null, protectApi: null, protectProcessApi: null, stabilizeApi: null, stabilizeProcessApi: null }; const emptyFunction = function() { }; /** * Waxaa la soo rartaa qoraalka bogga. * * @param {Function} onSuccess - Shaqada jawaab-celinta taas oo loogu yeero marka raristu ay guulaysato. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka raristu guuldarraysato. */ this.load = function(onSuccess, onFailure) { ctx.onLoadSuccess = onSuccess; ctx.onLoadFailure = onFailure || emptyFunction; // Waa inuu awoodaa inuu sameeyo wax ka dib marka boggu soo baxo if (!onSuccess) { ctx.statusElement.error('Qalad gudaha ah: ma jiro onSuccess callback oo la bixiyay load()!'); ctx.onLoadFailure(this); return; } ctx.loadQuery = { action: 'query', prop: 'info|revisions', inprop: 'watched', intestactions: 'edit', // waa la balaarin karaa curtimestamp: '', meta: 'tokens', type: 'csrf', titles: ctx.pageName, format: 'json' // uma baahnayn rvlimit=1 sababtoo ah uma baahnayn rvstartid halkan waxaana soo laabta hal rev oo dhab ah si caadi ah }; if (ctx.editMode === 'all') { ctx.loadQuery.rvprop = 'content|timestamp'; // hel nuxurka bogga isla waqtigaas, haddii loo baahdo } else if (ctx.editMode === 'revert') { ctx.loadQuery.rvprop = 'timestamp'; ctx.loadQuery.rvlimit = 1; ctx.loadQuery.rvstartid = ctx.revertOldID; } if (ctx.followRedirect) { ctx.loadQuery.redirects = ''; // raac dhammaan leexinta } if (typeof ctx.pageSection === 'number') { ctx.loadQuery.rvsection = ctx.pageSection; } if (Morebits.userIsSysop) { ctx.loadQuery.inprop += '|protection'; } ctx.loadApi = new Morebits.wiki.Api('Soo qaadashada bogga...', ctx.loadQuery, fnLoadSuccess, ctx.statusElement, ctx.onLoadFailure); ctx.loadApi.setParent(this); ctx.loadApi.post(); }; /** * Kaydi qoraalka bogga Wikipedia. * Waa inaysan ka horrayn wicitaan lagu guulaystay oo ah `load()`. * * Digniin: Wicitaanka `save()` wuxuu keeni karaa wicitaanno dheeri ah oo ku socda * `load()` callback-yadii hore si looga soo kabsado khilaafaadka wax ka beddelka! Xaaladdan, * kuwa waca waa inay sameeyaan isla wax ka beddelka bogga cusub pageText iyo * dib ugu yeeraan `save()`. Dabeecaddan waxaa lagu joojin karaa * `setMaxConflictRetries(0)`. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka kaydintu ay guulaysato. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka kaydintu guuldarraysato. */ this.save = function(onSuccess, onFailure) { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; // miyaan heleynaa calaamadeena wax ka beddelka (edit token) mw.user.tokens? const canUseMwUserToken = fnCanUseMwUserToken('edit'); if (!ctx.pageLoaded && !canUseMwUserToken) { ctx.statusElement.error('Qalad gudaha ah: isku day inaad kaydiso bog aan la soo rarin!'); ctx.onSaveFailure(this); return; } if (!ctx.editSummary) { // habka qaybta cusub wuxuu oggolaadaa (sidoo kale dhiirrigeliyaa) isticmaalka // cinwaanka sida kooban ee wax ka beddelka, laakiin weydiinta waxaa u baahan // editSummary inay noqoto mid aan la cayimin ama '', ma aha null if (ctx.editMode === 'new' && ctx.newSectionTitle) { ctx.editSummary = ''; } else { ctx.statusElement.error('Qalad gudaha ah: kooban wax ka beddelka lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } } // waa inaysan dhicin haddii canUseMwUserToken === true if (ctx.fullyProtected && !ctx.suppressProtectWarning && !confirm( ctx.fullyProtected === 'infinity' ? 'Waxaad ku dhowdahay inaad wax ka beddesho bogga si buuxda loo ilaaliyo "' + ctx.pageName + '" (oo la ilaaliyo si aan xad lahayn). \n\nRiix OK si aad ugu sii wadato wax ka beddelka, ama Cancel si aad uga booddo wax ka beddelkan.' : 'Waxaad ku dhowdahay inaad wax ka beddesho bogga si buuxda loo ilaaliyo "' + ctx.pageName + '" (ilaalintu waxay dhacaysaa ' + new Morebits.Date(ctx.fullyProtected).calendar('utc') + ' (UTC)). \n\nRiix OK si aad ugu sii wadato wax ka beddelka, ama Cancel si aad uga booddo wax ka beddelkan.' ) ) { ctx.statusElement.error('Wax ka beddelka bogga si buuxda loo ilaaliyo waa la joojiyay.'); ctx.onSaveFailure(this); return; } ctx.retries = 0; const query = { action: 'edit', title: ctx.pageName, summary: ctx.editSummary, token: canUseMwUserToken ? mw.user.tokens.get('csrfToken') : ctx.csrfToken, watchlist: ctx.watchlistOption, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } if (typeof ctx.pageSection === 'number') { query.section = ctx.pageSection; } // Deji sifada wax ka beddelka yar (minor edit). Haddii sifooyinkan ay joogaan qiimo kasta, waxaa loo tarjumaa true if (ctx.minorEdit) { query.minor = true; } else { query.notminor = true; // ku qasab qaabeynta Twinkle inay ka gudubto dejinta doorbididda isticmaalaha ee "dhammaan wax ka beddelku waa kuwo yaryar" } // Deji sifada wax ka beddelka bot-ka. Haddii sifo tani ay joogto qiimo kasta, waxaa loo tarjumaa true if (ctx.botEdit) { query.bot = true; } if (ctx.discussionToolsAutoSubscribe !== null) { query.discussiontoolsautosubscribe = ctx.discussionToolsAutoSubscribe ? 'yes' : 'no'; } switch (ctx.editMode) { case 'append': if (ctx.appendText === null) { ctx.statusElement.error('Qalad gudaha ah: ku darista qoraalka lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.appendtext = ctx.appendText; // isticmaal qaabka aad ugu darto nuxurka bogga hadda break; case 'prepend': if (ctx.prependText === null) { ctx.statusElement.error('Qalad gudaha ah: qoraalka hordhaca ah lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.prependtext = ctx.prependText; // isticmaal qaabka aad ugu horreysiiso nuxurka bogga hadda break; case 'new': if (!ctx.newSectionText) { // API-du ma oggolaqto qoraal qayb cusub oo madhan ctx.statusElement.error('Qalad gudaha ah: qoraalka qaybta cusub lama dejin ka hor kaydinta!'); ctx.onSaveFailure(this); return; } query.section = 'new'; query.text = ctx.newSectionText; // ku dar qayb cusub nuxurka bogga hadda query.sectiontitle = ctx.newSectionTitle || ctx.editSummary; // waxaa sameeya API, laakiin qiimayaasha aan ahayn '' waxaa loola dhaqmi lahaa sida qoraal break; case 'revert': query.undo = ctx.revertCurID; query.undoafter = ctx.revertOldID; if (ctx.lastEditTime) { query.basetimestamp = ctx.lastEditTime; // hubi in bogga aan la beddelin tan iyo markii la soo raray } query.starttimestamp = ctx.loadTime; // hubi in bogga aan la tirtirin tan iyo markii la soo raray (ha dib u abuurin waxyaabaha xun) break; default: // 'all' query.text = ctx.pageText; // ku beddel nuxurka buuxa ee bogga if (ctx.lastEditTime) { query.basetimestamp = ctx.lastEditTime; // hubi in bogga aan la beddelin tan iyo markii la soo raray } query.starttimestamp = ctx.loadTime; // hubi in bogga aan la tirtirin tan iyo markii la soo raray (ha dib u abuurin waxyaabaha xun) break; } if (['recreate', 'createonly', 'nocreate'].includes(ctx.createOption)) { query[ctx.createOption] = ''; } if (canUseMwUserToken && ctx.followRedirect) { query.redirect = true; } ctx.saveApi = new Morebits.wiki.Api('Kaydinta bogga...', query, fnSaveSuccess, ctx.statusElement, fnSaveError); ctx.saveApi.setParent(this); ctx.saveApi.post(); }; /** * Ku dar qoraalka lagu bixiyay `setAppendText()` dhamaadka bogga. * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada (watchlist expiry) la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.append = function(onSuccess, onFailure) { ctx.editMode = 'append'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** * Ku dar qoraalka lagu bixiyay `setPrependText()` bilowga bogga. * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.prepend = function(onSuccess, onFailure) { ctx.editMode = 'prepend'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** * Abuur qayb cusub oo wata qoraalka ay bixisay `setNewSectionText()` * iyo cinwaanka qaybta ee ka yimid `setNewSectionTitle()`. * Haddii `editSummary` la bixiyo, taas ayaa la isticmaali doonaa beddelka cinwaanka otomaatiga ah ee "->Title (new section". * Uma baahna wicitaan `load()` marka hore, ilaa dhicitaanka liiska daawashada la isticmaalo. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta taas oo loogu yeero marka habku uu guulaysto. * @param {Function} [onFailure] - Shaqada jawaab-celinta taas oo loogu yeero marka habku guuldarraysato. */ this.newSection = function(onSuccess, onFailure) { ctx.editMode = 'new'; if (fnCanUseMwUserToken('edit')) { this.save(onSuccess, onFailure); } else { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; this.load(fnAutoSave, ctx.onSaveFailure); } }; /** @return {string} Magaca bogga la rarray, oo ay ku jirto meesha magaca (namespace) */ this.getPageName = function() { return ctx.pageName; }; /** @return {string} Qoraalka bogga ka dib load() guulaystay */ this.getPageText = function() { return ctx.pageText; }; /** @param {string} pageText - Qoraalka bogga ee la cusboonaysiiyay kaas oo la kaydin doono marka `save()` la yeero */ this.setPageText = function(pageText) { ctx.editMode = 'all'; ctx.pageText = pageText; }; /** @param {string} appendText - Qoraal lagu dari doono dhammaadka bogga marka `append()` la yeero */ this.setAppendText = function(appendText) { ctx.editMode = 'append'; ctx.appendText = appendText; }; /** @param {string} prependText - Qoraal lagu horreysiin doono bogga marka `prepend()` la yeero */ this.setPrependText = function(prependText) { ctx.editMode = 'prepend'; ctx.prependText = prependText; }; /** @param {string} newSectionText - Qoraal lagu dari doono qayb cusub oo bogga ah marka `newSection()` la yeero */ this.setNewSectionText = function(newSectionText) { ctx.editMode = 'new'; ctx.newSectionText = newSectionText; }; /** * @param {string} newSectionTitle - Cinwaanka qaybta cusub ee la abuuray marka `newSection()` la yeero * Haddii uu maqanyahay, `ctx.editSummary` ayaa la isticmaali doonaa. Dhibaatooyin ayaa dhici kara haddii template la beddelay la isticmaalo. */ this.setNewSectionTitle = function(newSectionTitle) { ctx.editMode = 'new'; ctx.newSectionTitle = newSectionTitle; }; // Sifooyinka la xiriira wax ka beddelka (Edit-related setter methods): /** * Deji kooban wax ka beddelka (edit summary) kaas oo la isticmaali doono marka `save()` la yeero. * Looma baahna haddii editMode uu yahay 'new' oo newSectionTitle la bixiyo. * * @param {string} summary */ this.setEditSummary = function(summary) { ctx.editSummary = summary; }; /** * Deji calaamadaha (tags) caadiga ah ee lagu dabaqayo falka API. * Tiro ka mid ah falalka ma taageeraan, kuwa ugu caansan waa watch, review, * iyo stabilize ({@link https://phabricator.wikimedia.org/T247721|T247721}). * * @param {string|string[]} tags - Xarig ama saf calaamado ah. */ this.setChangeTags = function(tags) { ctx.changeTags = tags; }; /** * @param {string} [createOption=null] - Wuxuu qaadan karaa afartan qiime: * - recreate: abuur bogga haddii uusan jirin, ama wax ka beddel haddii uu jiro. * - createonly: abuur bogga haddii uusan jirin, laakiin soo celi qalad haddii uu hore u jiray. * - nocreate: ha abuurin bogga, kaliya wax ka beddel haddii uu hore u jiray. * - `null`: abuur bogga haddii uusan jirin, ilaa laga tirtiray intii u dhaxaysay raridda bogga iyo kaydinta wax ka beddelka (caadiga ah). */ this.setCreateOption = function(createOption) { ctx.createOption = createOption; }; /** @param {boolean} minorEdit - Deji true si aad ugu calaamadiso wax ka beddelka mid yar. */ this.setMinorEdit = function(minorEdit) { ctx.minorEdit = minorEdit; }; /** @param {boolean} botEdit - Deji true si aad ugu calaamadiso wax ka beddelka mid bot ah */ this.setBotEdit = function(botEdit) { ctx.botEdit = botEdit; }; /** * @param {number} pageSection - Nambar buuxa (integer) oo qeexaya lambarka qaybta si loo rarto ama loo kaydiyo. * Haddii loo dejiyo `null`, bogga oo dhan ayaa la soo celin doonaa. */ this.setPageSection = function(pageSection) { ctx.pageSection = pageSection; }; /** * @param {number} maxConflictRetries - Tirada dib-u-dayisyada ee khaladaadka kaydinta ee ku lug leh khilaaf wax ka beddel ama * luminta token-ka. Caadiga ah: 2. */ this.setMaxConflictRetries = function(maxConflictRetries) { ctx.maxConflictRetries = maxConflictRetries; }; /** * @param {number} maxRetries - Tirada dib-u-dayisyada ee khaladaadka kaydinta ee aan ku lug lahayn khilaaf wax ka beddel ama * luminta token-ka. Caadiga ah: 2. */ this.setMaxRetries = function(maxRetries) { ctx.maxRetries = maxRetries; }; /** * Deji haddii iyo sida loo daawado bogga, oo ay ku jirto dejinta dhicitaanka (expiry). * * @param {boolean|string|Morebits.Date|Date} [watchlistOption=false] - * Asal ahaan isku-dhafka xulashooyinka MW API iyo Twinkley ee la heli karo ka hor dhicitaanka: * - `true`|`'yes'`|`'watch'`: bogga waxaa lagu darayaa liiska daawashada ee isticmaalaha * marka falka la yeero. Waxay u degeysaa si caadi ah daawasho aan xad lahayn ilaa `watchlistExpiry` la bixiyo. * - `false`|`'no'`|`'nochange'`: xaaladda daawashada bogga (oo ay ku jirto dhicitaanka) lama beddeli doono. * - `'default'`|`'preferences'`: xaaladda daawashada bogga waxaa loo dejin doonaa * iyadoo lagu saleynayo dejinta doorbididda isticmaalaha marka falka la yeero. Waxay u degeysaa si caadi ah daawasho aan xad lahayn ilaa `watchlistExpiry` la bixiyo. * - `'unwatch'`: si cad uga saar daawashada bogga. * - `string` ama `number` kasta oo kale, ama shay `Morebits.Date` ama `Date`: * daaw bogga ilaa wakhtiga la cayimay, adigoo u laabanaya `watchlistExpiry` haddii la bixiyo. * @param {string|number|Morebits.Date|Date} [watchlistExpiry=infinity] - * Xarig ama nambar taariikh la mid ah, ama shay taariikh. Haddii uu yahay xarig ama nambar, * wuxuu noqon karaa qaraabo (2 toddobaad) ama si kale taariikh la mid ah (tusaale MA AHA "baradho"): * ISO 8601: 2038-01-09T03:14:07Z * MediaWiki: 20380109031407 * UNIX: 2147483647 * SQL: 2038-01-09 03:14:07 * Wuxuu kaloo noqon karaa `infinity` ama sida infinity (infinite, indefinite, iyo never). * Sidoo kale eeg {@link https://phabricator.wikimedia.org/source/mediawiki-libs-Timestamp/browse/master/src/ConvertibleTimestamp.php;4e53b859a9580c55958078f46dd4f3a44d0fcaa0$57-109?as=source&blame=off} */ this.setWatchlist = function(watchlistOption, watchlistExpiry) { if (watchlistOption instanceof Morebits.Date || watchlistOption instanceof Date) { watchlistOption = watchlistOption.toISOString(); } if (typeof watchlistExpiry === 'undefined') { watchlistExpiry = 'infinity'; } else if (watchlistExpiry instanceof Morebits.Date || watchlistExpiry instanceof Date) { watchlistExpiry = watchlistExpiry.toISOString(); } switch (watchlistOption) { case 'nochange': case 'no': case false: case undefined: ctx.watchlistOption = 'nochange'; // MW API waxay oggolaataa in la beddelo dhicitaanka iyada oo aan la beddelin (sida "nochange" ay u tixraacayso xaaladda binary), // laakiin iyadoo tan loo haysto null waxay si caadi ah u noqon doontaa dhicitaan kasta oo jira, waxay xaqiijinaysaa inaysan jirin wax "isbeddel ah." ctx.watchlistExpiry = null; break; case 'unwatch': // dhicitaanku muhiim ma ahan ctx.watchlistOption = 'unwatch'; break; case 'preferences': case 'default': ctx.watchlistOption = 'preferences'; // API-du waxay oggolaataa dhicitaan halkan, laakiin ma jiro xitaa (T265716) // wax doorbidid ah oo ku saabsan dhicitaanka, markaa wax yar bay ka madhan tahay macnaha guud. ctx.watchlistExpiry = watchlistExpiry; break; case 'watch': case 'yes': case true: ctx.watchlistOption = 'watch'; ctx.watchlistExpiry = watchlistExpiry; break; default: // Ma aha mid "caadi ah" laakiin wuxuu qabtaa "xarig kasta oo kale" ctx.watchlistOption = 'watch'; ctx.watchlistExpiry = watchlistOption; break; } }; /** * Deji dhicitaanka liiska daawashada (watchlist expiry). setWatchlist waxay inta badan tan u maamuli kartaa * iyada oo keligeed ah, markaa tani waxay halkan u taallaa inta badan dhammaystiran iyo waafajinta * xulashooyinka buuxa. * * @param {string|number|Morebits.Date|Date} [watchlistExpiry=infinity] - * Xarig ama nambar taariikh la mid ah, ama shay taariikh. Haddii uu yahay xarig ama nambar, * wuxuu noqon karaa qaraabo (2 toddobaad) ama si kale taariikh la mid ah (tusaale MA AHA "baradho"): * ISO 8601: 2038-01-09T03:14:07Z * MediaWiki: 20380109031407 * UNIX: 2147483647 * SQL: 2038-01-09 03:14:07 * Wuxuu kaloo noqon karaa `infinity` ama sida infinity (infinite, indefinite, iyo never). * Sidoo kale eeg {@link https://phabricator.wikimedia.org/source/mediawiki-libs-Timestamp/browse/master/src/ConvertibleTimestamp.php;4e53b859a9580c55958078f46dd4f3a44d0fcaa0$57-109?as=source&blame=off} */ this.setWatchlistExpiry = function(watchlistExpiry) { if (typeof watchlistExpiry === 'undefined') { watchlistExpiry = 'infinity'; } else if (watchlistExpiry instanceof Morebits.Date || watchlistExpiry instanceof Date) { watchlistExpiry = watchlistExpiry.toISOString(); } ctx.watchlistExpiry = watchlistExpiry; }; /** * Haddii aad wax ka beddelayso bog wadahadal (talk page), deji haddii aad is-diiwaangelinayso nooc kasta oo * fariin wadahadal ah oo uu abuuray wax ka beddelku. * * @param {boolean} subscribe */ this.setDiscussionToolsAutoSubscribe = function(subscribe) { ctx.discussionToolsAutoSubscribe = subscribe; }; /** * @param {boolean} [followRedirect=false] - * - `true`: ugu badnaan hal leexin ayaa la raaci doonaa. Xaaladda * leexin, fariin ayaa loo bandhigayaa isticmaalaha waxaana bartilmaameedka * leexinta laga soo qaadan karaa getPageName(). * - `false`: (caadiga ah) pageName-ka la codsaday waxaa loo isticmaali doonaa iyada oo aan loo eegin leexin kasta. * @param {boolean} [followCrossNsRedirect=true] - Lama khuseeyo haddii `followRedirect` aan loo dejin true. * - `true`: (caadiga ah) raac leexinta xitaa haddii ay tahay leexin u dhexaysa meelaha magaca (cross-namespace redirect) * - `false`: ha raacin leexinta haddii ay tahay meel u dhexaysa magacyada, wax ka beddel leexinta lafteeda. */ this.setFollowRedirect = function(followRedirect, followCrossNsRedirect) { if (ctx.pageLoaded) { ctx.statusElement.error('Qalad gudaha ah: ma beddeli karo dejinta leexinta ka dib markii bogga la rarray!'); return; } ctx.followRedirect = followRedirect; ctx.followCrossNsRedirect = typeof followCrossNsRedirect !== 'undefined' ? followCrossNsRedirect : ctx.followCrossNsRedirect; }; // shaqada sifooyinka raadinta abuurista (lookup-creation setter function) /** * @param {boolean} flag - Haddii loo dejiyo true, qoraaga iyo wakhti-shaabadeedka * nooca ugu horreeya ee aan leexinta ahayn ee bogga ayaa la soo qaadayaa. * * Digniin: * 1. Haddii aysan jirin dib-u-eegisyo ka mid ah 50-ka ugu horreeya oo ah 5 * kuwo aan leexin ahayn, ama haddii ay jiraan dib-u-eegisyo ka yar 50 oo dhammaantood ay yihiin * leexino, abuuriskii asalka ahaa waa la soo qaadayaa. * 2. Dib-u-eegisyada uusan isticmaalahu xaq u lahayn inuu galo * (revdeled/suppressed) waxaa loola dhaqmi doonaa sidii kuwo aan leexin ahayn. * 3. Waa in aan la isticmaalin marka boggu leeyahay contentmodel aan wikitext ahayn * sida Modulespace Lua ama user JavaScript/CSS. */ this.setLookupNonRedirectCreator = function(flag) { ctx.lookupNonRedirectCreator = flag; }; // Sifooyinka la xiriira raridda (Move-related setter functions) /** @param {string} destination */ this.setMoveDestination = function(destination) { ctx.moveDestination = destination; }; /** @param {boolean} flag */ this.setMoveTalkPage = function(flag) { ctx.moveTalkPage = !!flag; }; /** @param {boolean} flag */ this.setMoveSubpages = function(flag) { ctx.moveSubpages = !!flag; }; /** @param {boolean} flag */ this.setMoveSuppressRedirect = function(flag) { ctx.moveSuppressRedirect = !!flag; }; // Sifooyinka la xiriira ilaalinta (Protect-related setter functions) /** * @param {string} level - Xaqqa looga baahan yahay falka gaarka ah * tusaale ahaan autoconfirmed, sysop, templateeditor, extendedconfirmed * (enWiki oo keliya). * @param {string} [expiry=infinity] */ this.setEditProtection = function(level, expiry) { ctx.protectEdit = { level: level, expiry: expiry || 'infinity' }; }; this.setMoveProtection = function(level, expiry) { ctx.protectMove = { level: level, expiry: expiry || 'infinity' }; }; this.setCreateProtection = function(level, expiry) { ctx.protectCreate = { level: level, expiry: expiry || 'infinity' }; }; this.setCascadingProtection = function(flag) { ctx.protectCascade = !!flag; }; this.suppressProtectWarning = function() { ctx.suppressProtectWarning = true; }; // Sifooyinka la xiriira tirtiridda (Delete-related setter) /** @param {boolean} flag */ this.setDeleteTalkPage = function(flag) { ctx.deleteTalkPage = !!flag; }; // Sifooyinka la xiriira ka soo celinta tirtirka (Undelete-related setter) /** @param {boolean} flag */ this.setUndeleteTalkPage = function(flag) { ctx.undeleteTalkPage = !!flag; }; // Sifooyinka la xiriira dib u soo celinta (Revert-related getters/setters): this.setOldID = function(oldID) { ctx.revertOldID = oldID; }; /** @return {string} Aqoonsiga dib-u-eegiska hadda ee bogga (current revision ID) */ this.getCurrentID = function() { return ctx.revertCurID; }; /** @return {string} Tafatiraha ugu dambeeya ee bogga */ this.getRevisionUser = function() { return ctx.revertUser; }; /** @return {string} Waqti-shaabadeedka ISO 8601 ee uu boggu ugu dambeeyay ee la beddelay. */ this.getLastEditTime = function() { return ctx.lastEditTime; }; // Sifooyinka kale (Miscellaneous getters/setters): /** * Qeex shay loogu isticmaalo shaqada jawaab-celinta. * * `callbackParameters` waxaa loogu talagalay isticmaalaha waca keliya. Halbeegyada * waxay u oggolaanayaan qofka waca inuu u gudbiyo macnaha saxda ah ee jawaab-celintiisa * shaqada. Kuwa waca waa inay xaqiijiyaan in wixii isbeddel ah ee ku yimaada * shayga callbackParameters ee gudaha jawaab-celinta `load()` ay weli u oggolaanayaan * dib-u-gelitaan sax ah oo ku socda jawaab-celinta `load()` haddii khilaaf wax ka beddel * la ogaado marka la yeerayo `save()`. * * @param {Object} callbackParameters */ this.setCallbackParameters = function(callbackParameters) { ctx.callbackParameters = callbackParameters; }; /** * @return {Object} - Shayga hore loogu dejiyay `setCallbackParameters()`. */ this.getCallbackParameters = function() { return ctx.callbackParameters; }; /** * @param {Morebits.Status} statusElement */ this.setStatusElement = function(statusElement) { ctx.statusElement = statusElement; }; /** * @return {Morebits.Status} Shayga xaaladda ee abuuray dhisaha (constructor). */ this.getStatusElement = function() { return ctx.statusElement; }; /** * @param {string} level - Xaqqa looga baahan yahay wax ka beddelka si uusan ugu baahan * dib-u-eegis. Xulashooyinka suurtogalka ah: none, autoconfirmed, review (ma aha enWiki). * @param {string} [expiry=infinity] */ this.setFlaggedRevs = function(level, expiry) { ctx.flaggedRevs = { level: level, expiry: expiry || 'infinity' }; }; /** * @return {boolean} True haddii boggu uu ka jiray wiki-ga markii ugu dambeysay ee la rarray. */ this.exists = function() { return ctx.pageExists; }; /** * @return {string} Aqoonsiga bogga ee bogga la rarray. 0 haddii uusan boggu jirin. */ this.getPageID = function() { return ctx.pageID; }; /** * @return {string} - Qaabka nuxurka ee bogga (Content model). Qiimayaasha suurtogalka ah * waxaa ka mid ah (laakiin waxaa laga yaabaa inaysan ku xaddidnayn): `wikitext`, `javascript`, * `css`, `json`, `Scribunto`, `sanitized-css`, `MassMessageListContent`. * Sidoo kale waxaa lagu heli karaa iyada oo la marayo `mw.config.get('wgPageContentModel')`. */ this.getContentModel = function() { return ctx.contentModel; }; /** * @return {boolean|string} - Xaaladda daawashada ee bogga. Boolean * ilaa laga daawanayo si ku-meel-gaar ah, xaaladdaas oo kale waxay soo celinaysaa xarigga dhicitaanka. */ this.getWatched = function() { return ctx.watched; }; /** * @return {string} Waqti-shaabadeedka ISO 8601 ee uu boggu ugu dambeeyay ee la rarray. */ this.getLoadTime = function() { return ctx.loadTime; }; /** * @return {string} Qoraaga abuuray bogga ka dib `lookupCreation()`. */ this.getCreator = function() { return ctx.creator; }; /** * @return {string} Waqti-shaabadeedka ISOString ee abuurista bogga ka dib `lookupCreation()`. */ this.getCreationTimestamp = function() { return ctx.timestamp; }; /** @return {boolean} haddii aad wax ka beddeli karto bogga iyo in kale */ this.canEdit = function() { return !!ctx.testActions && ctx.testActions.includes('edit'); }; /** * Soo qaado magaca isticmaalaha ee abuuray bogga iyo sidoo kale * wakhti-shaabadeedka abuurista. Magaca isticmaalaha waxaa lagu soo qaadan karaa iyadoo la adeegsanayo * shaqada `getCreator()`; wakhti-shaabadeedka waxaa lagu soo qaadan karaa iyadoo la adeegsanayo * shaqada `getCreationTimestamp()`. * Bishii Juun 2019 wuxuu aaggu aaqoon u lahaa `lookupCreator()`. * * @param {Function} onSuccess - Shaqada jawaab-celinta ee la wacayo marka 5 * magaca isticmaalaha iyo wakhti-shaabadeedka laga helo gudaha jawaab-celinta. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee la wacayo marka * raadintu guuldarraysato */ this.lookupCreation = function(onSuccess, onFailure) { ctx.onLookupCreationSuccess = onSuccess; ctx.onLookupCreationFailure = onFailure || emptyFunction; if (!onSuccess) { ctx.statusElement.error('Qalad gudaha ah: ma jiro onSuccess callback oo la bixiyay lookupCreation()!'); ctx.onLookupCreationFailure(this); return; } const query = { action: 'query', prop: 'revisions', titles: ctx.pageName, rvlimit: 1, rvprop: 'user|timestamp', rvdir: 'newer', format: 'json' }; // Kaliya qaabka nuxurka wikitext ayaa si lagu kalsoonaan karo u maamuli kara // rvsection, kuwa kalena waxay soo celiyaan qalad marka lala lammaaniyo // nuxurka rvprop. Sidoo kale, moodooyinka aan wikitext ahayn ma fahmaan // fikradda #REDIRECT, markaa waa in aynaan isku dayin // xallinta leexinta ee fnLookupCreationSuccess if (ctx.lookupNonRedirectCreator) { query.rvsection = 0; query.rvprop += '|content'; } if (ctx.followRedirect) { query.redirects = ''; // raac dhammaan leexinta } ctx.lookupCreationApi = new Morebits.wiki.Api('Soo qaadashada macluumaadka abuurista bogga', query, fnLookupCreationSuccess, ctx.statusElement, ctx.onLookupCreationFailure); ctx.lookupCreationApi.setParent(this); ctx.lookupCreationApi.post(); }; /** * Dib ugu celi bogga `revertOldID` ee ay dejisay `setOldID`. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.revert = function(onSuccess, onFailure) { ctx.onSaveSuccess = onSuccess; ctx.onSaveFailure = onFailure || emptyFunction; if (!ctx.revertOldID) { ctx.statusElement.error('Qalad gudaha ah: aqoonsiga dib-u-eegiska ee dib loogu noqonayo lama dejin ka hor dib u celinta!'); ctx.onSaveFailure(this); return; } ctx.editMode = 'revert'; this.load(fnAutoSave, ctx.onSaveFailure); }; /** * Rari bog cinwaan kale. * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.move = function(onSuccess, onFailure) { ctx.onMoveSuccess = onSuccess; ctx.onMoveFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'move', ctx.onMoveFailure)) { return; // jooji } if (!ctx.moveDestination) { ctx.statusElement.error('Qalad gudaha ah: magaca bogga bartilmaameedka lama dejin ka hor raridda!'); ctx.onMoveFailure(this); return; } if (fnCanUseMwUserToken('move')) { fnProcessMove.call(this, this); } else { const query = fnNeedTokenInfoQuery('move'); ctx.moveApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessMove, ctx.statusElement, ctx.onMoveFailure); ctx.moveApi.setParent(this); ctx.moveApi.post(); } }; /** * Calaamadee bogga in la ilaalo (patrolled), iyadoo la adeegsanayo `rcid` (haddii la heli karo) ama `revid`. * * Ilaalinta sidaas oo kale uma baahna inay ku tiirsanaato raridda bogga * la su'aalayo; si fudud gudbinta revid ee API-ga waa ku filan tahay, markaa xaaladahaas * kaliya adeegsiga {@link Morebits.wiki.Api} ayaa laga yaabaa inay roon tahay. * * Ma jiro maamul qalad ah maadaama aynaan dhab ahaantii u daneeyneyn khaladaadka. */ this.patrol = function() { if (!Morebits.userIsSysop && !Morebits.userIsInGroup('patroller')) { return; } // Haddii xiriiriye uu jiro, uma baahnid inaad hubiso in la ilaaliyay if ($('.patrollink').length) { const patrolhref = $('.patrollink a').attr('href'); ctx.rcid = mw.util.getParamValue('rcid', patrolhref); fnProcessPatrol(this, this); } else { const patrolQuery = { action: 'query', prop: 'info', meta: 'tokens', type: 'patrol', // illaa inta aan waydiinayno, waxaa laga yaabaa inay sidoo kale helaan token list: 'recentchanges', // hubi haddii boggu uusan lahayn ilaalino titles: ctx.pageName, rcprop: 'patrolled', rctitle: ctx.pageName, rclimit: 1, format: 'json' }; ctx.patrolApi = new Morebits.wiki.Api('soo qaadashada token...', patrolQuery, fnProcessPatrol); ctx.patrolApi.setParent(this); ctx.patrolApi.post(); } }; /** * Calaamadee bogga in dib-u-eegis lagu sameeyay kordhinta PageTriage. * * Wuxuu, dabeecad ahaan, u calaamadin doonaa in la ilaaliyay sidoo kale. Wuxuu u laabanayaa * ilaalinta haddii uusan ku jirin meel magac ku habboon. * * Si dabiici ah ugu ma tiirsana raridda bogga su'aasha ku jira; si fudud * gudbinta `pageid` ee API-ga waa ku filan tahay, markaa xaaladahaas oo keliya * adeegsiga {@link Morebits.wiki.Api} ayaa laga yaabaa inay roon tahay. * * Wuxuu marka hore hubin doonaa haddii boggu saf ku jiro iyada oo loo marayo * {@link Morebits.wiki.Page~fnProcessTriageList|fnProcessTriageList}. * * Ma jiro maamul qalad ah maadaama aynaan dhab ahaantii u daneeyneyn khaladaadka. * * @see {@link https://www.mediawiki.org/wiki/Extension:PageTriage} Waxaa loogu yeeraa "review" on-wiki. */ this.triage = function() { // U laabo ilaalinta haddii uusan ahayn meel magac triage oo ansax ah if (!mw.config.get('pageTriageNamespaces').includes(new mw.Title(ctx.pageName).getNamespaceId())) { this.patrol(); } else { if (!Morebits.userIsSysop && !Morebits.userIsInGroup('patroller')) { return; } // Haddii aad joogto bogga su'aasha ku jira, uma baahnid inaad u waydiiso aqoonsiga bogga (page ID) if (new mw.Title(Morebits.pageNameNorm).getPrefixedText() === new mw.Title(ctx.pageName).getPrefixedText()) { ctx.pageID = mw.config.get('wgArticleId'); fnProcessTriageList(this, this); } else { const query = fnNeedTokenInfoQuery('triage'); ctx.triageApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessTriageList); ctx.triageApi.setParent(this); ctx.triageApi.post(); } } }; // |delete| waa eray la keydiyay dhadhanka qaarkood ee JS /** * Tirtir bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.deletePage = function(onSuccess, onFailure) { ctx.onDeleteSuccess = onSuccess; ctx.onDeleteFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'delete', ctx.onDeleteFailure)) { return; // jooji } if (fnCanUseMwUserToken('delete')) { fnProcessDelete.call(this, this); } else { const query = fnNeedTokenInfoQuery('delete'); ctx.deleteApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessDelete, ctx.statusElement, ctx.onDeleteFailure); ctx.deleteApi.setParent(this); ctx.deleteApi.post(); } }; /** * Ka soo celi tirtirka bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.undeletePage = function(onSuccess, onFailure) { ctx.onUndeleteSuccess = onSuccess; ctx.onUndeleteFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'undelete', ctx.onUndeleteFailure)) { return; // jooji } if (fnCanUseMwUserToken('undelete')) { fnProcessUndelete.call(this, this); } else { const query = fnNeedTokenInfoQuery('undelete'); ctx.undeleteApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessUndelete, ctx.statusElement, ctx.onUndeleteFailure); ctx.undeleteApi.setParent(this); ctx.undeleteApi.post(); } }; /** * Ilaali bog (maamulayaasha oo keliya). * * @param {Function} [onSuccess] - Shaqada jawaab-celinta ee lagu fulinayo guusha. * @param {Function} [onFailure] - Shaqada jawaab-celinta ee lagu fulinayo guuldarrada. */ this.protect = function(onSuccess, onFailure) { ctx.onProtectSuccess = onSuccess; ctx.onProtectFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'protect', ctx.onProtectFailure)) { return; // jooji } if (!ctx.protectEdit && !ctx.protectMove && !ctx.protectCreate) { ctx.statusElement.error('Qalad gudaha ah: waa inaad dejisaa ilaalinta wax ka beddelka iyo/ama raridda iyo/ama abuurista ka hor inta aadan wicin protect()!'); ctx.onProtectFailure(this); return; } // sababtoo ah habka uu MW API u tarjumayo heerarka ilaalinta // (absolute, ee ma aha differential), waxaan had iyo jeer u baahanahay inaan codsanno // heerarka ilaalinta ee server-ka const query = fnNeedTokenInfoQuery('protect'); ctx.protectApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessProtect, ctx.statusElement, ctx.onProtectFailure); ctx.protectApi.setParent(this); ctx.protectApi.post(); }; /** * Dabaq dejinta ilaalinta FlaggedRevs. Kaliya waxay ka shaqeysaa wiki-yada halkaas oo * kordhintu ay ka rakiban tahay (`$wgFlaggedRevsProtection = true` * tusaale ahaan halkaas oo dejinta FlaggedRevs ay ka muuqato tab-ka "protect"). * * @see {@link https://www.mediawiki.org/wiki/Extension:FlaggedRevs} * Waxaa loogu yeeraa "pending changes" on-wiki. * * @param {Function} [onSuccess] * @param {Function} [onFailure] */ this.stabilize = function(onSuccess, onFailure) { ctx.onStabilizeSuccess = onSuccess; ctx.onStabilizeFailure = onFailure || emptyFunction; if (!fnPreflightChecks.call(this, 'FlaggedRevs', ctx.onStabilizeFailure)) { return; // jooji } if (!ctx.flaggedRevs) { ctx.statusElement.error('Qalad gudaha ah: waa inaad dejisaa flaggedRevs ka hor inta aadan wicin stabilize()!'); ctx.onStabilizeFailure(this); return; } if (fnCanUseMwUserToken('stabilize')) { fnProcessStabilize.call(this, this); } else { const query = fnNeedTokenInfoQuery('stabilize'); ctx.stabilizeApi = new Morebits.wiki.Api('soo qaadashada token...', query, fnProcessStabilize, ctx.statusElement, ctx.onStabilizeFailure); ctx.stabilizeApi.setParent(this); ctx.stabilizeApi.post(); } }; /* * Shaqooyinka xubnaha gaarka ah (Private member functions) * Kuwani laguma soo bandhigo dibadda */ /** * Go'aami haddii aan badbaadin karno wicitaan API ah adigoo isticmaalaya csrf token * ee lagu soo diray HTML-ka bogga, ama haddii aan u baahanahay inaan waydiino server-ka * macluumaad dheeraad ah (tusaale ilaalinta ama dhicitaanka liiska daawashada). * * Hadda waxaa loo isticmaalaa `append`, `prepend`, `newSection`, `move`, * `stabilize`, `deletePage`, iyo `undeletePage`. Looma isticmaalo * `protect` maadaama ay mar walba u baahan tahay in la codsado xaaladda ilaalinta. * * @param {string} [action=edit] - Falka la fulinayo, tusaale * "edit" ama "delete". Ficil ahaan, kaliya "edit" ama "notedit" ayaa muhiim ah. * @return {boolean} */ var fnCanUseMwUserToken = function(action = 'edit') { // Haddii dhicitaanka liiska daawashada la dejiyo, waa inaan mar walba soo rarnaa bogga // si looga fogaado in la tirtiro ilaalinta aan xadka lahayn. Dabcan, looma baahna // haddii la dejinayo daawasho aan xad lahayn! if (ctx.watchlistExpiry && !Morebits.string.isInfinity(ctx.watchlistExpiry)) { return false; } // Xallinta leexinta ee ku saleysan API waxay u shaqaysaa oo keliya action=query iyo // action=edit ee hababka append/prepend/new if (ctx.followRedirect) { if (!ctx.followCrossNsRedirect) { return false; // waa in la soo raro bogga si loo hubiyo leexinta u dhexaysa meelaha magaca } if (action !== 'edit' || (ctx.editMode === 'all' || ctx.editMode === 'revert')) { return false; } } // ma u baahanahay inaan soo qaadano dhicitaanka ilaalinta wax ka beddelka? if (Morebits.userIsSysop && !ctx.suppressProtectWarning) { if (new mw.Title(Morebits.pageNameNorm).getPrefixedText() !== new mw.Title(ctx.pageName).getPrefixedText()) { return false; } // wgRestrictionEdit waa null bogagga aan jirin, // markaa tani si fiican ayay u maamushaa bogagga aan jirin const editRestriction = mw.config.get('wgRestrictionEdit'); if (!editRestriction || editRestriction.includes('sysop')) { return false; } } return !!mw.user.tokens.get('csrfToken'); }; /*** Marka shaqooyinka aysan isticmaali karin * {@link Morebits.wiki.Page~fnCanUseMwUserToken|fnCanUseMwUserToken} * ama ay u baahan yihiin in la hubiyo ilaalinta ama xaaladda daawashada, ku hay weydiinta * meel keliya. Waxaa loo isticmaalaa {@link Morebits.wiki.Page#deletePage|delete}, * {@link Morebits.wiki.Page#undeletePage|undelete}, * {@link Morebits.wiki.Page#protect|protect}, * {@link Morebits.wiki.Page#stabilize|stabilize}, * iyo {@link Morebits.wiki.Page#move|move} * (asal ahaan, kaliya ma aha {@link Morebits.wiki.Page#load|load}). * * @param {string} action - Falka la fulinayo, tusaale "edit" ama * "delete". * @return {Object} Weydiinta habboon. */ var fnNeedTokenInfoQuery = function(action) { const query = { action: 'query', meta: 'tokens', type: 'csrf', titles: ctx.pageName, prop: 'info', inprop: 'watched', format: 'json' }; // Ilaalinta lama hubiyo flagged-revs ama dhaqaaqyada aan sysop ahayn if (action !== 'stabilize' && (action !== 'move' || Morebits.userIsSysop)) { query.inprop += '|protection'; } if (ctx.followRedirect && action !== 'undelete') { query.redirects = ''; // raac dhammaan leexinta } return query; }; // jawaab-celinta ka timid loadSuccess() ee dunta append(), prepend(), iyo newSection() var fnAutoSave = function(pageobj) { pageobj.save(ctx.onSaveSuccess, ctx.onSaveFailure); }; // jawaab-celinta ka timid loadApi.post() var fnLoadSuccess = function() { const response = ctx.loadApi.getResponse().query; if (!fnCheckPageName(response, ctx.onLoadFailure)) { return; // jooji } const page = response.pages[0]; let rev; ctx.pageExists = !page.missing; if (ctx.pageExists) { rev = page.revisions[0]; ctx.lastEditTime = rev.timestamp; ctx.pageText = rev.content; ctx.pageID = page.pageid; } else { ctx.pageText = ''; // u oggolow isku-darka, iwm. ctx.pageID = 0; // ma jiro jawaabta, wuxuu la mid yahay wgArticleId } ctx.csrfToken = response.tokens.csrftoken; if (!ctx.csrfToken) { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo qaado calaamadda wax ka beddelka (edit token).'); ctx.onLoadFailure(this); return; } ctx.loadTime = ctx.loadApi.getResponse().curtimestamp; if (!ctx.loadTime) { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo qaado wakhti-shaabadeedka hadda (current timestamp).'); ctx.onLoadFailure(this); return; } ctx.contentModel = page.contentmodel; ctx.watched = page.watchlistexpiry || page.watched; // soo saar macluumaadka ilaalinta, si looga digtoonaado maamulayaasha marka ay ku dhow yihiin inay wax ka beddelaan bog la ilaaliyo // Waxaa ku jira ilaalinta isku xigta (cascading protection) if (Morebits.userIsSysop) { const editProt = page.protection.filter((pr) => pr.type === 'edit' && pr.level === 'sysop').pop(); if (editProt) { ctx.fullyProtected = editProt.expiry; } else { ctx.fullyProtected = false; } } ctx.revertCurID = page.lastrevid; const testactions = page.actions; ctx.testActions = []; // wuxuu ahaa null Object.keys(testactions).forEach((action) => { if (testactions[action]) { ctx.testActions.push(action); } }); if (ctx.editMode === 'revert') { ctx.revertCurID = rev && rev.revid; if (!ctx.revertCurID) { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo qaado aqoonsiga dib-u-eegiska hadda.'); ctx.onLoadFailure(this); return; } ctx.revertUser = rev && rev.user; if (!ctx.revertUser) { if (rev && rev.userhidden) { // magaca isticmaalaha waa la qariyay (RevDel'd ama oversighted) ctx.revertUser = '<magaca isticmaalaha waa la qariyay>'; } else { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo qaado isticmaalaha sameeyay dib-u-eegiska.'); ctx.onLoadFailure(this); return; } } // deji kooban wax ka beddelka dib u celinta ctx.editSummary = '[[Help:Revert|Waa la soo celiyay]] nuqulkii ' + ctx.revertOldID + ' ee uu sameeyay ' + ctx.revertUser + ': ' + ctx.editSummary; } ctx.pageLoaded = true; // alert("Generate edit conflict now"); // loogu talagalay tijaabinta macquulka ah ee kabashada khilaafka wax ka beddelka ctx.onLoadSuccess(this); // yeero jawaab-celinta }; // shaqo caawiye ah si loo falanqeeyo magaca bogga ee laga soo celiyay API-ga var fnCheckPageName = function(response, onFailure) { if (!onFailure) { onFailure = emptyFunction; } const page = response.pages && response.pages[0]; if (page) { // hubi cinwaannada aan ansax ahayn if (page.invalid) { ctx.statusElement.error('Cinwaanka boggu ma ansax ahan: ' + ctx.pageName); onFailure(this); return false; // jooji } // soo qaad magaca dhabta ah ee bogga ka dib caadiyaynta iyo leexinta const resolvedName = page.title; if (response.redirects) { // hubi leexinta u dhexaysa meelaha magaca: const origNs = new mw.Title(ctx.pageName).namespace; const newNs = new mw.Title(resolvedName).namespace; if (origNs !== newNs && !ctx.followCrossNsRedirect) { ctx.statusElement.error(ctx.pageName + ' waa leexin u dhexaysa meelaha magaca oo ku socota ' + resolvedName + ', waa la joojiyay'); onFailure(this); return false; } } // kaliya ogeysii isticmaalaha leexinta, ee ma aha caadiyaynta new Morebits.Status('Fiiro gaar ah', 'Laga leexiyay ' + ctx.pageName + ' una socota ' + resolvedName); } ctx.pageName = resolvedName; // u cusboonaysii bartilmaameedka leexinta ama magaca la caadiyeeyay } else { // wuxuu noqon karaa leexin wareegsan ama dhibaato kale ctx.statusElement.error('Wuusan xallin karin leexinta tan: ' + ctx.pageName); onFailure(this); // ku qasbi qaladka inuu ku sii ahaado shaashadda ++Morebits.wiki.numberOfActionsLeft; return false; // jooji } return true; // wax walba waa caadi }; /** * Go'aami haddii aan bixinno dhicitaanka liiska daawashada. Ma * samayn doono haddii bogga hadda si joogto ah loo daawanayo, ama dhicitaanka * hadda uu ka dambeeyo (`after`) dhicitaanka cusub ee la bixiyay. Kaliya wuxuu maamulaa xargaha * ee ay aqoonsato {@link Morebits.Date} ama waqtiyada qaraabada ah ee wata * unug uu habayn karo. Wuxuu ku tiirsan yahay xaqiiqda ah in fnCanUseMwUserToken * uu u baahan yahay raridda bogga haddii la bixiyo watchlistexpiry, markaa waxaa loo xaqiijiyay * inaan ognahay xaaladda daawashada adigoo isticmaalaya tan. * * @return {boolean} */ var fnApplyWatchlistExpiry = function() { if (ctx.watchlistExpiry) { if (!ctx.watched || Morebits.string.isInfinity(ctx.watchlistExpiry)) { return true; } else if (typeof ctx.watched === 'string') { let newExpiry; // Isku day inaad go'aamiso haddii dhicitaanka cusub uu yahay // mid qaraabo ah (tusaale `1 month`) ama taariikh-waqti sugan const rel = ctx.watchlistExpiry.split(' '); try { newExpiry = new Morebits.Date().add(rel[0], rel[1]); } catch (e) { newExpiry = new Morebits.Date(ctx.watchlistExpiry); } // Haddii taariikhdu ay ansax tahay, kaliya isticmaal haddii ay kordhinays}`} dhicitaanka hadda if (newExpiry.isValid()) { if (newExpiry.isAfter(new Morebits.Date(ctx.watched))) { return true; } } else { // Haddii aysan weli ansax ahayn, rajeyso inay tahay qaab dhicitaan MW oo sax ah oo // aysan aqoon Morebits.Date, markaa kaliya u deg adeegsigeeda. // Tani waxay sidoo kale ahaan doontaa qalad qoraal yar yar. return true; } } } return false; }; // jawaab-celinta ka timid saveApi.post() var fnSaveSuccess = function() { ctx.editMode = 'all'; // jooji hababka append/prepend/newSection/revert const response = ctx.saveApi.getResponse(); // eeg haddii API-du ay u malaynayso inaan guulaysanay if (response.edit.result === 'Success') { // guul dhab ah // caadiga ah ee falka guusha - muuji xiriiriyaha bogga la tifatiray const link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(ctx.pageName)); link.appendChild(document.createTextNode(ctx.pageName)); ctx.statusElement.info(['la dhammeeyay (', link, ')']); if (ctx.onSaveSuccess) { ctx.onSaveSuccess(this); // yeero jawaab-celinta } return; } // khaladaadka halkan waxaa soo saara oo keliya kordhintyada xiriiriya APIEditBeforeSave gudaha MediaWiki, // taas oo laga bilaabo 1.34.0-wmf.23 (Sept 2019) ay tahay inay ku jiraan fariimaha captcha oo keliya if (response.edit.captcha) { ctx.statusElement.error('Wuusan kaydin karin bogga sababtoo ah server-ka wiki wuxuu rabay inaad buuxiso CAPTCHA.'); } else { ctx.statusElement.error('Qalad aan la aqoon ayaa laga helay API marka la kaydinayay bogga'); } // ku qasbi qaladka inuu ku sii ahaado shaashadda ++Morebits.wiki.numberOfActionsLeft; ctx.onSaveFailure(this); }; // jawaab-celinta ka timid saveApi.post() var fnSaveError = function() { const errorCode = ctx.saveApi.getErrorCode(); // hubi khilaafka wax ka beddelka if (errorCode === 'editconflict' && ctx.conflictRetries++ < ctx.maxConflictRetries) { // khilaafaadka wax ka beddelka waxay dhici karaan marka bogga loo baahdo in laga nadiifiyo kaydka server-ka (cache) const purgeQuery = { action: 'purge', titles: ctx.pageName // leexinta horay waa loo xalliyay }; const purgeApi = new Morebits.wiki.Api('Khilaaf wax ka beddel ah ayaa la ogaaday, nadiifinta kaydka server-ka', purgeQuery, (() => { --Morebits.wiki.numberOfActionsLeft; // u oggolow dhammaystirka caadiga ah haddii dib-u-dayisku guulaysto ctx.statusElement.info('Khilaaf wax ka beddel ah ayaa la ogaaday, dib u dabaqida tifatirka'); if (fnCanUseMwUserToken('edit')) { ctx.saveApi.post(); // si khasab ah append, prepend, ama newSection, markaa tani waxay u shaqayn doontaa sida la rabay } else { ctx.loadApi.post(); // dib u soo rari bogga oo dib u dabaq tifatirka } }), ctx.statusElement); purgeApi.post(); // hubi shabakadda ama qaladka server-ka } else if ((errorCode === null || errorCode === undefined) && ctx.retries++ < ctx.maxRetries) { // qaladku wuxuu noqon karaa mid ku meel gaar ah, markaa dib u day ctx.statusElement.info('Kaydintu waa guuldarraysatay, dib u dayaya 2 ilbiriqsi gudahood ...'); --Morebits.wiki.numberOfActionsLeft; // u oggolow dhammaystirka caadiga ah haddii dib-u-dayisku guulaysto // sug wakhti yar si macaamiilku u soo ceshado xiriirka sleep(2000).then(() => { ctx.saveApi.post(); // si kalena u day! }); // qalad adag, ka tanaasul } else { const response = ctx.saveApi.getResponse(); const errorData = response.error || // bc error format response.errors[0].data; // html/wikitext/plaintext error format switch (errorCode) { case 'protectedpage': // qof aan maamule ahayn oo isku dayaya inuu wax ka beddelo bog la ilaaliyo - tani waxay bixisaa fariin ka saaxiibtinimo badan tan caadiga ah ctx.statusElement.error('Wuu ku guuldarraystay inuu kaydiyo tifatirka: Boggu waa la ilaaliyay'); break; case 'abusefilter-disallowed': ctx.statusElement.error('Tifatirka waxaa diiday shaandhada tifatirka: "' + errorData.abusefilter.description + '".'); break; case 'abusefilter-warning': ctx.statusElement.error(['Digid ayaa laga soo celiyay shaandhada tifatirka: "', errorData.abusefilter.description, '". Haddii aad rabto inaad la sii waddo tifatirka, fadlan dib u fuli. Digidani mar labaad ma soo muuqan doonto.']); // Waa inaan u weyno isticmaalaha hab si otomaatig ah ugu dib u dayo falka haddii uu sidaas doorto - // Ma arki karo sida tan loo sameeyo iyada oo aan la abuurin ku xirnaanshaha UI ee Morebits.wiki.Page bagase -- TTO break; case 'spamblacklist': // Haddii walxo badan la madow-liis gareeyay, waxaan soo celinnaa kan koowaad oo keliya var spam = errorData.spamblacklist.matches[0]; ctx.statusElement.error('Wuusan kaydin karin bogga sababtoo ah URL-ka ' + spam + ' wuxuu ku jiraa liiska madow ee spam-ka'); break; default: ctx.statusElement.error('Wuu ku guuldarraystay inuu kaydiyo tifatirka: ' + ctx.saveApi.getErrorText()); } ctx.editMode = 'all'; // jooji hababka append/prepend/newSection/revert if (ctx.onSaveFailure) { ctx.onSaveFailure(this); // yeero jawaab-celinta } } }; const isTextRedirect = function(text) { if (!text) { // ma jiro qoraal - nuxurku waa madhan ama lama heli karo (revdelled ama suppressed) return false; } return Morebits.l10n.redirectTagAliases.some((tag) => new RegExp('^\\s*' + tag + '\\W', 'i').test(text)); }; var fnLookupCreationSuccess = function() { const response = ctx.lookupCreationApi.getResponse().query; if (!fnCheckPageName(response, ctx.onLookupCreationFailure)) { return; // jooji } const rev = response.pages[0].revisions && response.pages[0].revisions[0]; if (!rev) { ctx.statusElement.error('Ma heli karin wax dib-u-eegis ah oo ku saabsan ' + ctx.pageName); ctx.onLookupCreationFailure(this); return; } if (!ctx.lookupNonRedirectCreator || !isTextRedirect(rev.content)) { ctx.creator = rev.user; if (!ctx.creator) { ctx.statusElement.error('Ma heli karin magaca abuuraha bogga'); ctx.onLookupCreationFailure(this); return; } ctx.timestamp = rev.timestamp; if (!ctx.timestamp) { ctx.statusElement.error('Ma heli karin wakhti-shaabadeedka abuurista bogga'); ctx.onLookupCreationFailure(this); return; } ctx.statusElement.info('la soo saaray macluumaadka abuurista bogga'); ctx.onLookupCreationSuccess(this); } else { ctx.lookupCreationApi.query.rvlimit = 50; // wax ka beddel weydiintii hore si loo soo qaado dib-u-eegisyo badan ctx.lookupCreationApi.query.titles = ctx.pageName; // cusboonaysii pageName haddii xallinta leexinta ay ka dhacday weydiintii hore ctx.lookupCreationApi = new Morebits.wiki.Api('Soo qaadashada macluumaadka abuurista bogga', ctx.lookupCreationApi.query, fnLookupNonRedirectCreator, ctx.statusElement, ctx.onLookupCreationFailure); ctx.lookupCreationApi.setParent(this); ctx.lookupCreationApi.post(); } }; var fnLookupNonRedirectCreator = function() { const response = ctx.lookupCreationApi.getResponse().query; const revs = response.pages[0].revisions; for (let i = 0; i < revs.length; i++) { if (!isTextRedirect(revs[i].content)) { ctx.creator = revs[i].user; ctx.timestamp = revs[i].timestamp; break; } } if (!ctx.creator) { // ku laabo bixinta qoraaga dib-u-eegiska koowaad haddii aysan jirin nuqul aan leexin ahayn 50-ka ugu horreeya ctx.creator = revs[0].user; ctx.timestamp = revs[0].timestamp; if (!ctx.creator) { ctx.statusElement.error('Ma heli karin magaca abuuraha bogga'); ctx.onLookupCreationFailure(this); return; } } if (!ctx.timestamp) { ctx.statusElement.error('Ma heli karin wakhti-shaabadeedka abuurista bogga'); ctx.onLookupCreationFailure(this); return; } ctx.statusElement.info('la soo saaray macluumaadka abuurista bogga'); ctx.onLookupCreationSuccess(this); }; /** * Hubinta caadiga ah ee hababka falalka. Waxaa loo isticmaalaa move, undelete, delete, * protect, stabilize. * * @param {string} action - Falka la hubinayo. * @param {string} onFailure - Jawaab-celinta guuldarrada. * @return {boolean} */ var fnPreflightChecks = function(action, onFailure) { // haddii qof aan maamule ahayn uu isku dayo inuu sameeyo tan, ha dhibin if (!Morebits.userIsSysop && action !== 'move') { ctx.statusElement.error('Ma geli karo ' + action + ' bogga : maamulayaasha oo keliya ayaa samayn kara tan'); onFailure(this); return false; } if (!ctx.editSummary) { ctx.statusElement.error('Qalad gudaha ah: ' + action + ' sababta lama dejin (isticmaal shaqada setEditSummary)!'); onFailure(this); return false; } return true; // wax walba waa caadi }; /** * Hubinta caadiga ah ee shaqooyinka fnProcess (`fnProcessDelete`, `fnProcessMove`, iwm. * Waxaa loo isticmaalaa move, undelete, delete, protect, stabilize. * * @param {string} action - Falka la hubinayo. * @param {string} onFailure - Jawaab-celinta guuldarrada. * @param {string} response - Dukumentiga jawaab-celinta ee ka yimid wicitaanka API. * @return {boolean} */ const fnProcessChecks = function(action, onFailure, response) { const missing = response.pages[0].missing; // Ma jiro undelete maadaama bogga jira uu yeelan karo dib-u-eegisyo la tirtiray const actionMissing = missing && ['delete', 'stabilize', 'move'].includes(action); const protectMissing = action === 'protect' && missing && (ctx.protectEdit || ctx.protectMove); const saltMissing = action === 'protect' && !missing && ctx.protectCreate; if (actionMissing || protectMissing || saltMissing) { ctx.statusElement.error('Ma samayn karo ' + action + ' bogga sababtoo ah ' + (missing ? 'mar dambe ma jiro' : 'horay ayuu u jiray')); onFailure(this); return false; } // Delete, undelete, move // soo saar macluumaadka ilaalinta let editprot; if (action === 'undelete') { editprot = response.pages[0].protection.filter((pr) => pr.type === 'create' && pr.level === 'sysop').pop(); } else if (action === 'delete' || action === 'move') { editprot = response.pages[0].protection.filter((pr) => pr.type === 'edit' && pr.level === 'sysop').pop(); } if (editprot && !ctx.suppressProtectWarning && !confirm('Waxaad ku dhowdahay inaad ' + action + ' bogga si buuxda loo ilaaliyo "' + ctx.pageName + (editprot.expiry === 'infinity' ? '" (la ilaaliyay si aan xad lahayn)' : '" (ilaalintu waxay dhacaysaa ' + new Morebits.Date(editprot.expiry).calendar('utc') + ' (UTC))') + '. \n\nRiix OK si aad ugu sii wadato ' + action + ', ama Cancel si aad uga booddo.')) { ctx.statusElement.error('Waa la joojiyay ' + action + ' ee bogga si buuxda loo ilaaliyo.'); onFailure(this); return false; } if (!response.tokens.csrftoken) { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo qaado calaamadda (token).'); onFailure(this); return false; } return true; // wax walba waa caadi }; var fnProcessMove = function() { let pageTitle, token; if (fnCanUseMwUserToken('move')) { token = mw.user.tokens.get('csrfToken'); pageTitle = ctx.pageName; } else { const response = ctx.moveApi.getResponse().query; if (!fnProcessChecks('move', ctx.onMoveFailure, response)) { return; // jooji } token = response.tokens.csrftoken; const page = response.pages[0]; pageTitle = page.title; ctx.watched = page.watchlistexpiry || page.watched; } const query = { action: 'move', from: pageTitle, to: ctx.moveDestination, token: token, reason: ctx.editSummary, watchlist: ctx.watchlistOption, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } if (ctx.moveTalkPage) { query.movetalk = 'true'; } if (ctx.moveSubpages) { query.movesubpages = 'true'; } if (ctx.moveSuppressRedirect) { query.noredirect = 'true'; } ctx.moveProcessApi = new Morebits.wiki.Api('dhaqaajinta bogga...', query, ctx.onMoveSuccess, ctx.statusElement, ctx.onMoveFailure); ctx.moveProcessApi.setParent(this); ctx.moveProcessApi.post(); }; var fnProcessPatrol = function() { const query = { action: 'patrol', format: 'json' }; // Uma baahnayn in la rarro bogga if (ctx.rcid) { query.rcid = ctx.rcid; query.token = mw.user.tokens.get('patrolToken'); } else { const response = ctx.patrolApi.getResponse().query; // Ha ilaalin haddii aysan ahayn mid aan la ilaalin if (!response.recentchanges[0].unpatrolled) { return; } const lastrevid = response.pages[0].lastrevid; if (!lastrevid) { return; } query.revid = lastrevid; const token = response.tokens.csrftoken; if (!token) { return; } query.token = token; } if (ctx.changeTags) { query.tags = ctx.changeTags; } const patrolStat = new Morebits.Status('Calaamadaynta bogga mid la eegay'); ctx.patrolProcessApi = new Morebits.wiki.Api('ilaalinta bogga...', query, null, patrolStat); ctx.patrolProcessApi.setParent(this); ctx.patrolProcessApi.post(); }; // Hubi in boggu yahay var fnProcessTriageList = function() { if (ctx.pageID) { ctx.csrfToken = mw.user.tokens.get('csrfToken'); } else { const response = ctx.triageApi.getResponse().query; ctx.pageID = response.pages[0].pageid; if (!ctx.pageID) { return; } ctx.csrfToken = response.tokens.csrftoken; if (!ctx.csrfToken) { return; } } const query = { action: 'pagetriagelist', page_id: ctx.pageID, format: 'json' }; ctx.triageProcessListApi = new Morebits.wiki.Api('hubinta xaaladda daryeelka...', query, fnProcessTriage); ctx.triageProcessListApi.setParent(this); ctx.triageProcessListApi.post(); }; // jawaab-celinta ka timid triageProcessListApi.post() var fnProcessTriage = function() { const responseList = ctx.triageProcessListApi.getResponse().pagetriagelist; // Ka bax haddii aysan ku jirin safka if (!responseList || responseList.result !== 'success') { return; } const page = responseList.pages && responseList.pages[0]; // Wax ha samayn haddii bogga horay loo daryeelay/la ilaaliyay if (!page || !parseInt(page.patrol_status, 10)) { const query = { action: 'pagetriageaction', pageid: ctx.pageID, reviewed: 1, token: ctx.csrfToken, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } const triageStat = new Morebits.Status('Calaamadaynta bogga mid la habeeyay'); ctx.triageProcessApi = new Morebits.wiki.Api('habaynta bogga...', query, null, triageStat); ctx.triageProcessApi.setParent(this); ctx.triageProcessApi.post(); } }; var fnProcessDelete = function() { let pageTitle, token; if (fnCanUseMwUserToken('delete')) { token = mw.user.tokens.get('csrfToken'); pageTitle = ctx.pageName; } else { const response = ctx.deleteApi.getResponse().query; if (!fnProcessChecks('delete', ctx.onDeleteFailure, response)) { return; // jooji } token = response.tokens.csrftoken; const page = response.pages[0]; pageTitle = page.title; ctx.watched = page.watchlistexpiry || page.watched; } const query = { action: 'delete', title: pageTitle, token: token, reason: ctx.editSummary, watchlist: ctx.watchlistOption, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } if (ctx.deleteTalkPage) { query.deletetalk = 'true'; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } ctx.deleteProcessApi = new Morebits.wiki.Api('tirtiridda bogga...', query, ctx.onDeleteSuccess, ctx.statusElement, fnProcessDeleteError); ctx.deleteProcessApi.setParent(this); ctx.deleteProcessApi.post(); }; // jawaab-celinta ka timid deleteProcessApi.post() var fnProcessDeleteError = function() { const errorCode = ctx.deleteProcessApi.getErrorCode(); // hubi "Database query error" if (errorCode === 'internal_api_error_DBQueryError' && ctx.retries++ < ctx.maxRetries) { ctx.statusElement.info('Qaladka weydiinta xog-ururinta (Database), dib u dayaya'); --Morebits.wiki.numberOfActionsLeft; // u oggolow dhammaystirka caadiga ah haddii dib-u-dayisku guulaysto ctx.deleteProcessApi.post(); // si kalena u day! } else if (errorCode === 'missingtitle') { ctx.statusElement.error('Ma tirtiri karo bogga, sababtoo ah mar dambe ma jiro'); if (ctx.onDeleteFailure) { ctx.onDeleteFailure.call(this, ctx.deleteProcessApi); // yeero jawaab-celinta } // qalad adag, ka tanaasul } else { ctx.statusElement.error('Wuu ku guuldarraystay inuu tirtiro bogga: ' + ctx.deleteProcessApi.getErrorText()); if (ctx.onDeleteFailure) { ctx.onDeleteFailure.call(this, ctx.deleteProcessApi); // yeero jawaab-celinta } } }; var fnProcessUndelete = function() { let pageTitle, token; if (fnCanUseMwUserToken('undelete')) { token = mw.user.tokens.get('csrfToken'); pageTitle = ctx.pageName; } else { const response = ctx.undeleteApi.getResponse().query; if (!fnProcessChecks('undelete', ctx.onUndeleteFailure, response)) { return; // jooji } token = response.tokens.csrftoken; const page = response.pages[0]; pageTitle = page.title; ctx.watched = page.watchlistexpiry || page.watched; } const query = { action: 'undelete', title: pageTitle, token: token, reason: ctx.editSummary, watchlist: ctx.watchlistOption, format: 'json' }; if (ctx.changeTags) { query.tags = ctx.changeTags; } if (ctx.undeleteTalkPage) { query.undeletetalk = 'true'; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } ctx.undeleteProcessApi = new Morebits.wiki.Api('soo-celinta bogga...', query, ctx.onUndeleteSuccess, ctx.statusElement, fnProcessUndeleteError); ctx.undeleteProcessApi.setParent(this); ctx.undeleteProcessApi.post(); }; // jawaab-celinta ka timid undeleteProcessApi.post() var fnProcessUndeleteError = function() { const errorCode = ctx.undeleteProcessApi.getErrorCode(); // hubi "Database query error" if (errorCode === 'internal_api_error_DBQueryError') { if (ctx.retries++ < ctx.maxRetries) { ctx.statusElement.info('Qaladka weydiinta xog-ururinta (Database), dib u dayaya'); --Morebits.wiki.numberOfActionsLeft; // u oggolow dhammaystirka caadiga ah haddii dib-u-dayisku guulaysto ctx.undeleteProcessApi.post(); // si kalena u day! } else { ctx.statusElement.error('Qalad weydiinta xog-ururinta oo soo noqnoqday, fadlan dib u day'); if (ctx.onUndeleteFailure) { ctx.onUndeleteFailure.call(this, ctx.undeleteProcessApi); // yeero jawaab-celinta } } } else if (errorCode === 'cantundelete') { ctx.statusElement.error('Ma soo celin karo bogga, sababtoo ah ma jiraan dib-u-eegisyo la soo celiyo ama hore looga soo celiyay'); if (ctx.onUndeleteFailure) { ctx.onUndeleteFailure.call(this, ctx.undeleteProcessApi); // yeero jawaab-celinta } // qalad adag, ka tanaasul } else { ctx.statusElement.error('Wuu ku guuldarraystay inuu soo celiyo bogga: ' + ctx.undeleteProcessApi.getErrorText()); if (ctx.onUndeleteFailure) { ctx.onUndeleteFailure.call(this, ctx.undeleteProcessApi); // yeero jawaab-celinta } } }; var fnProcessProtect = function() { const response = ctx.protectApi.getResponse().query; if (!fnProcessChecks('protect', ctx.onProtectFailure, response)) { return; // jooji } const token = response.tokens.csrftoken; const page = response.pages[0]; const pageTitle = page.title; ctx.watched = page.watchlistexpiry || page.watched; // Soo qaado heerarka ilaalinta ee jira const prs = response.pages[0].protection; let editprot, moveprot, createprot; prs.forEach((pr) => { // Sifee ilaalinta ka timaadda cascading if (pr.type === 'edit' && !pr.source) { editprot = pr; } else if (pr.type === 'move') { moveprot = pr; } else if (pr.type === 'create') { createprot = pr; } }); // Ku laabo heerarka hadda haddii aan si cad loo dejin if (!ctx.protectEdit && editprot) { ctx.protectEdit = { level: editprot.level, expiry: editprot.expiry }; } if (!ctx.protectMove && moveprot) { ctx.protectMove = { level: moveprot.level, expiry: moveprot.expiry }; } if (!ctx.protectCreate && createprot) { ctx.protectCreate = { level: createprot.level, expiry: createprot.expiry }; } // Ku laabo ilaalinta cascading ee horay u jirtay haddii aan la beddelin (la mid ah kor ku xusan) if (ctx.protectCascade === null) { ctx.protectCascade = !!prs.filter((pr) => pr.cascade).length; } // Ka digtoonow haddii ilaalinta cascading la dabaqayo iyada oo wadata heer ilaalina oo aan ansax ahayn, // taas oo u ilaalinta wax ka beddelka ay sababi doonto in cascading si aamusan loo xayuubiyo if (ctx.protectCascade) { // Ilaalinta raridda, tani waa mid aad adag marka loo eego MW API, // laakiin waxay u muuqataa mid macquul ah si looga fogaado qiimayaasha doqonimada iyo gelitaanka diiwaanka ee khaldan (T265626) if (((!ctx.protectEdit || ctx.protectEdit.level !== 'sysop') || (!ctx.protectMove || ctx.protectMove.level !== 'sysop')) && !confirm('Waxaad shidday ilaalinta cascading ee "' + ctx.pageName + '" laakiin ma aanad dooran ilaalinta heerka sysop ee le'eg.\n\n' + 'Riix OK si aad u habayso oo aad ugu sii wadato ilaalinta cascading ee heerka sysop, ama Cancel si aad uga booddo falkan.')) { ctx.statusElement.error('Iaalinta cascading waa la joojiyay.'); ctx.onProtectFailure(this); return; } ctx.protectEdit.level = 'sysop'; ctx.protectMove.level = 'sysop'; } // Dhis heerarka ilaalinta iyo dhicitaannada weydiinta const protections = [], expirys = []; if (ctx.protectEdit) { protections.push('edit=' + ctx.protectEdit.level); expirys.push(ctx.protectEdit.expiry); } if (ctx.protectMove) { protections.push('move=' + ctx.protectMove.level); expirys.push(ctx.protectMove.expiry); } if (ctx.protectCreate) { protections.push('create=' + ctx.protectCreate.level); expirys.push(ctx.protectCreate.expiry); } const query = { action: 'protect', title: pageTitle, token: token, protections: protections.join('|'), expiry: expirys.join('|'), reason: ctx.editSummary, watchlist: ctx.watchlistOption, format: 'json' }; // Kaliya wuxuu ka muuqdaa diiwaannada, ma aha taariikhda bogga [[phab:T259983]] if (ctx.changeTags) { query.tags = ctx.changeTags; } if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } if (ctx.protectCascade) { query.cascade = 'true'; } ctx.protectProcessApi = new Morebits.wiki.Api('ilaalinta bogga...', query, ctx.onProtectSuccess, ctx.statusElement, ctx.onProtectFailure); ctx.protectProcessApi.setParent(this); ctx.protectProcessApi.post(); }; var fnProcessStabilize = function() { let pageTitle, token; if (fnCanUseMwUserToken('stabilize')) { token = mw.user.tokens.get('csrfToken'); pageTitle = ctx.pageName; } else { const response = ctx.stabilizeApi.getResponse().query; // 'stabilize' oo ah fal si wanaagsan looma fahmin if (!fnProcessChecks('stabilize', ctx.onStabilizeFailure, response)) { return; // jooji } token = response.tokens.csrftoken; const page = response.pages[0]; pageTitle = page.title; // Ma taageerto dhicitaanka liiska daawashada [[phab:T263336]] // ctx.watched = page.watchlistexpiry || page.watched; } const query = { action: 'stabilize', title: pageTitle, token: token, protectlevel: ctx.flaggedRevs.level, expiry: ctx.flaggedRevs.expiry, // tags: ctx.changeTags, // taageerada calaamadda flaggedrevs: [[phab:T247721]] reason: ctx.editSummary, watchlist: ctx.watchlistOption, format: 'json' }; /* Ma taageerto dhicitaanka liiska daawashada [[phab:T263336]] if (fnApplyWatchlistExpiry()) { query.watchlistexpiry = ctx.watchlistExpiry; } */ ctx.stabilizeProcessApi = new Morebits.wiki.Api('habaynta dejinta xasillinta...', query, ctx.onStabilizeSuccess, ctx.statusElement, ctx.onStabilizeFailure); ctx.stabilizeProcessApi.setParent(this); ctx.stabilizeProcessApi.post(); }; var sleep = function(milliseconds) { const deferred = $.Deferred(); setTimeout(deferred.resolve, milliseconds); return deferred; }; }; // dhamaadka Morebits.wiki.Page /* Morebits.wiki.Page TODO: (XXX) * - Miyaannu sidoo kale dib u dayinnaa raridda? * - Ma u baahanahay inaan dib u dejino falka hadda ka hor kaydinta? * - Wax ka qabashada arrimaha action.completed * - Ma u baahanahay inaan dib u dejino dhammaan cabbiraadaha marka la dhammeeyo (tusaale kooban wax ka beddel, halka loo rarayo, iwm.) */ /* **************** Morebits.wiki.Preview **************** */ /** * Isticmaal API-ga si aad u tatro qayb wikitext ah oo aad u soo bandhigto sida HTML. * * Habka hirgelinta ee lagu taliyay (ee xaaladaha {@link Morebits.SimpleWindow} iyo * {@link Morebits.QuickForm}) waa in la dhiso shay * `Morebits.wiki.Preview` ka dib marka la soo bandhigo `Morebits.QuickForm`, iyo * in la xiro shayga hanti aan la cayimin ee foomka (tusaale |previewer|). * Tusaale ahaan, fiiri twinklewarn.js. * * @memberof Morebits.wiki * @class * @param {HTMLElement} previewbox - Shayga ka koobnaan doona HTML-ka la soo bandhigay, * badanaa waa shay <div> ah. */ Morebits.wiki.Preview = function(previewbox) { this.previewbox = previewbox; $(previewbox).addClass('morebits-previewbox').hide(); /** * Soo bandhigaya sanduuqa hor-u-eegiska, waxayna bilaabeysaa isku day asynchronous ah * si loo soo bandhigo wikitext-ka la cayimay. * * @param {string} wikitext - Wikitext si loo soo bandhigo; waxyaabaha badankoodu waa inay shaqeeyaan, oo ay ku jiraan `subst:` iyo `~~~~`. * @param {string} [pageTitle] - Cabbir ikhtiyaari ah oo loogu talagalay boggan kaas oo tan loo soo bandhigi doono sidii ay u taallo, haddii la tago waxaa loo qaadanayaa bogga hadda jira. * @param {string} [sectionTitle] - Haddii la bixiyo, soo bandhig qoraalka sida qayb cusub oo tan u adeegsanaysa cinwaan ahaan. * @return {jQuery.promise} */ this.beginRender = function(wikitext, pageTitle, sectionTitle) { $(previewbox).show(); const statusspan = document.createElement('span'); previewbox.appendChild(statusspan); Morebits.Status.init(statusspan); const query = { action: 'parse', prop: ['text', 'modules'], pst: true, // PST = pre-save transform; tani waxay ka dhigeysaa beddelka mid si sax ah u shaqeeya preview: true, text: wikitext, title: pageTitle || mw.config.get('wgPageName'), disablelimitreport: true, disableeditsection: true, format: 'json' }; if (sectionTitle) { query.section = 'new'; query.sectiontitle = sectionTitle; } const renderApi = new Morebits.wiki.Api('soo raraya...', query, fnRenderSuccess, new Morebits.Status('Hor-u-eegis')); return renderApi.post(); }; var fnRenderSuccess = function(apiobj) { const response = apiobj.getResponse(); const html = response.parse.text; if (!html) { apiobj.statelem.error('wuu ku guuldarraystay inuu soo qaado hor-u-eegiska, ama qaabku wuxuu ahaa mid madhan'); return; } previewbox.innerHTML = html; mw.loader.load(response.parse.modulestyles); mw.loader.load(response.parse.modules); // tani waxay ka dhigeysaa xiriiriyeyaasha inay ka furmaan tab cusub $(previewbox).find('a').attr('target', '_blank'); // La xiriir qoraallada ka shaqeeya nuxurka la soo bandhigay, sida navpopups mw.hook('wikipage.content').fire($(previewbox)); }; /** Wuxuu qariyaa sanduuqa hor-u-eegiska oo wuu nadiifiyaa. */ this.closePreview = function() { $(previewbox).empty().hide(); }; }; /* **************** Morebits.wikitext **************** */ /** * Wax ka beddelka Wikitext. * * @namespace Morebits.wikitext * @memberof Morebits */ Morebits.wikitext = {}; /** * Hel qiimaha cabbir kasta oo laga helay wikitext ee qaab gaar ah. * * @memberof Morebits.wikitext * @param {string} text - Wikitext ka kooban qaab (template). * @param {number} [start=0] - Tusmada tilmaamaysa halka uu qoraalka ka bilaabmayo qaabku. * @return {Object} `{name: templateName, parameters: {key: value}}`. */ Morebits.wikitext.parseTemplate = function(text, start) { start = start || 0; const level = []; // La soco inta ay le'eg tahay qoto dheerayntayada ({{, {{{, ama [[) let count = -1; // Tirada cabbiraadaha la helay let unnamed = 0; // La soco lambarka uu cabbirka aan la magacobin helayo let equals = -1; // Ka dib markii la helay "=" ka hor cabbirka, tusmada; haddii kale, -1 let current = ''; const result = { name: '', parameters: {} }; let key, value; /** * Shaqada lagu maamulayo helidda qiimaha cabbiraadaha. * * @param {boolean} [final=false] - Haddii tani ay tahay cabbirka * ugu dambeeya oo aan u baahannahay inaan ka saarno `}}` ee dhammaadka. */ function findParam(final) { // Waxba lama helin weli, tani waa inay ahaataa magaca qaabka if (count === -1) { result.name = current.slice(2).trim(); ++count; } else { // Cabbir dhexdiisa ah if (equals !== -1) { // Waxaan helnay "=" oo u dhigma, markaa kaydi cabbirka sida key: value key = current.substring(0, equals).trim(); value = final ? current.substring(equals + 1, current.length - 2).trim() : current.substring(equals + 1).trim(); result.parameters[key] = value; equals = -1; } else { // Ma jiro equals, markaa waa inaysan lahayn magac; ma jiro trim maadaama boosaska bannaan la oggolyahay const param = final ? current.substring(equals + 1, current.length - 2) : current; if (param) { result.parameters[++unnamed] = param; ++count; } } } } for (let i = start; i < text.length; ++i) { const test3 = text.substr(i, 3); if (test3 === '{{{' || (test3 === '}}}' && level[level.length - 1] === 3)) { current += test3; i += 2; if (test3 === '{{{') { level.push(3); } else { level.pop(); } continue; } const test2 = text.substr(i, 2); // Gelitaanka qaab (ama xiriiriye) if (test2 === '{{' || test2 === '[[') { current += test2; ++i; if (test2 === '{{') { level.push(2); } else { level.push('wl'); } continue; } // Ka bixitaanka xiriiriye ama qaab/shaqada falanqeeyaha if ((test2 === '}}' && level[level.length - 1] === 2) || (test2 === ']]' && level[level.length - 1] === 'wl')) { current += test2; ++i; level.pop(); // Hel cabbirka ugu dambeeya haddii tani dhab ahaantii ay tahay dhammaadka if (test2 === '}}' && level.length === 0) { findParam(true); break; } continue; } if (text.charAt(i) === '|' && level.length === 1) { // Tuubo kale ayaa la helay, heerka sare, markaa cabbir ayaa soo socda! findParam(); current = ''; } else if (equals === -1 && text.charAt(i) === '=' && level.length === 1) { // Equals ayaa la helay, heerka sare equals = current.length; current += text.charAt(i); } else { // Kaliya horay u soco booska current += text.charAt(i); } } return result; }; /** * Hagaaji oo wax ka beddel wikitext ee bogga. * * @class * @memberof Morebits.wikitext * @param {string} text - Wikitext si loo wax ka beddelo. */ Morebits.wikitext.Page = function mediawikiPage(text) { this.text = text; }; Morebits.wikitext.Page.prototype = { text: '', /** * Meesha ka saar xiriiriyeyaasha ku socda `link_target` qoraalka bogga. * * @param {string} link_target * @return {Morebits.wikitext.Page} */ removeLink: function(link_target) { const mwTitle = mw.Title.newFromText(link_target); const namespaceID = mwTitle.getNamespaceId(); const title = mwTitle.getMainText(); let link_regex_string = ''; if (namespaceID !== 0) { link_regex_string = Morebits.namespaceRegex(namespaceID) + ':'; } link_regex_string += Morebits.pageNameRegex(title); // Meelaha magacyada badankoodu, ka saar xiriirinta labadaba [[User:Test]] iyo [[:User:Test]] // Faylasha iyo qaybaha, kaliya ka saar xiriirinta [[:Category:Test]]. Ha ka saarin xiriirinta [[Category:Test]] const isFileOrCategory = [6, 14].includes(namespaceID); const colon = isFileOrCategory ? ':' : ':?'; const simple_link_regex = new RegExp('\\[\\[' + colon + '(' + link_regex_string + ')\\]\\]', 'g'); const piped_link_regex = new RegExp('\\[\\[' + colon + link_regex_string + '\\|(.+?)\\]\\]', 'g'); this.text = this.text.replace(simple_link_regex, '$1').replace(piped_link_regex, '$1'); return this; }, /** * Faallo ku qari sawirrada qoraalka bogga; haddii lagu isticmaalo gallery, tirtir xariiqda oo dhan. * Haddii lagu isticmaalo dood qaab ah (lagama maarmaan ma aha in la wato hordhaca `File:`), cabbirka qaabka ayaa la faallaynayaa. * * @param {string} image - Magaca sawirka oo aan lahayn hordhaca `File:`. * @param {string} [reason] - Sababta lagu darayo faallada, oo ay la socoto sawirka la faallada ka baxsaday. * @return {Morebits.wikitext.Page} */ commentOutImage: function(image, reason) { const unbinder = new Morebits.Unbinder(this.text); unbinder.unbind('<!--', '-->'); reason = reason ? reason + ': ' : ''; const image_re_string = Morebits.pageNameRegex(image); // Hubi xiriiriyeyaasha sawirka caadiga ah, tusaale [[File:Foobar.png|...]] // Wuxuu cuni doonaa xiriiriyaha oo dhan const links_re = new RegExp('\\[\\[' + Morebits.namespaceRegex(6) + ':\\s*' + image_re_string + '\\s*[\\|(?:\\]\\])]'); const allLinks = Morebits.string.splitWeightedByKeys(unbinder.content, '[[', ']]'); for (let i = 0; i < allLinks.length; ++i) { if (links_re.test(allLinks[i])) { const replacement = '<!-- ' + reason + allLinks[i] + ' -->'; unbinder.content = unbinder.content.replace(allLinks[i], replacement); // ka fur faallooyinka cusub ee la abuuray unbinder.unbind('<!--', '-->'); } } // Hubi sawirrada gallery, tusaale kiisaska ay tahay inay ka bilowdaan xariiq cusub, // oo ugu dambayn ay ka horreeyaan boos bannaan, waana inay ku jiraan hordhaca File: // Wuxuu cuni doonaa xariiqda oo dhan. const gallery_image_re = new RegExp('(^\\s*' + Morebits.namespaceRegex(6) + ':\\s*' + image_re_string + '\\s*(?:\\|.*?$|$))', 'mg'); unbinder.content = unbinder.content.replace(gallery_image_re, '<!-- ' + reason + '$1 -->'); // ka fur faallooyinka cusub ee la abuuray unbinder.unbind('<!--', '-->'); // Hubi isticmaalka sawirka bilaashka ah, tusaale ahaan sida doodaha qaabka, waxaa laga yaabaa in hordhaca File: laga reebo, laakiin waa inay ka horreeyaan | // Wuxuu cuni doonaa magaca sawirka iyo bar-ka ka horreeya iyo cabbirka la magacaabay ee dhici kara const free_image_re = new RegExp('(\\|\\s*(?:[\\w\\s]+\\=)?\\s*(?:' + Morebits.namespaceRegex(6) + ':\\s*)?' + image_re_string + ')', 'mg'); unbinder.content = unbinder.content.replace(free_image_re, '<!-- ' + reason + '$1 -->'); // Dib ugu xir nuxurka hadda, waa aan dhammaannay! this.text = unbinder.rebind(); return this; }, /** * U beddel isticmaalka [[File:`image`]] ilaa [[File:`image`|`data`]]. * * @param {string} image - Magaca sawirka oo aan lahayn hordhaca File:. * @param {string} data - Xulashooyinka bandhigga. * @return {Morebits.wikitext.Page} */ addToImageComment: function(image, data) { const image_re_string = Morebits.pageNameRegex(image); const links_re = new RegExp('\\[\\[' + Morebits.namespaceRegex(6) + ':\\s*' + image_re_string + '\\s*[\\|(?:\\]\\])]'); const allLinks = Morebits.string.splitWeightedByKeys(this.text, '[[', ']]'); for (let i = 0; i < allLinks.length; ++i) { if (links_re.test(allLinks[i])) { let replacement = allLinks[i]; // kaliya ku dhufo dhammaadka? replacement = replacement.replace(/\]\]$/, '|' + data + ']]'); this.text = this.text.replace(allLinks[i], replacement); } } const gallery_re = new RegExp('^(\\s*' + image_re_string + '.*?)\\|?(.*?)$', 'mg'); const newtext = '$1|$2 ' + data; this.text = this.text.replace(gallery_re, newtext); return this; }, /** * Meesha ka saar dhammaan is-dhexgalka qaabka qoraalka bogga. * * @param {string} template - Magaca bogga kaas oo is-dhexgalkiisa la tirtirayo, * ku dar hordhaca meesha magaca kaliya haddii uusan ku jirin meesha magaca qaabka. * @return {Morebits.wikitext.Page} */ removeTemplate: function(template) { const template_re_string = Morebits.pageNameRegex(template); const links_re = new RegExp('\\{\\{(?:' + Morebits.namespaceRegex(10) + ':)?\\s*' + template_re_string + '\\s*[\\|(?:\\}\\})]'); const allTemplates = Morebits.string.splitWeightedByKeys(this.text, '{{', '}}', ['{{{', '}}}']); for (let i = 0; i < allTemplates.length; ++i) { if (links_re.test(allTemplates[i])) { this.text = this.text.replace(allTemplates[i], ''); } } return this; }, /** * Si caqli gal ah ugu geli calaamad dusha sare ee qoraalka bogga laakiin ka dib qaababka la cayimay, * sida hatnotes, sharaxaadda gaaban, ama tirtiridda iyo qaababka ilaalinta. * Waxaa xusid mudan, ma geli *karo* xariiq cusub ka dib calaamadda. * * @param {string} tag - Calaamadda la gelinayo. * @param {string|string[]} regex - Qaababka ka dib marka la gelinayo calaamadda, * oo la bixiyay labadaba sida xarig (regex-valid ah) ama saf ay ku biirayaan tuubooyin. * @param {string} [flags=i] - Calamadaha Regex ee la dabaqayo. `''` si aan loo bixin calaamado; * qiimayaasha kale ee been-sheegga ah waxay u degeysaa `i`. * @param {string|string[]} [preRegex] - Xarig regex ikhtiyaari ah ama saf si uu u waafaqo * ka hor wax kasta oo ku habboon qaabka (tusaale ka hor `{{`), sida faallooyinka html. * @return {Morebits.wikitext.Page} */ insertAfterTemplates: function(tag, regex, flags, preRegex) { if (typeof tag === 'undefined') { throw new Error('Ma jiro calaamad la bixiyay'); } // .length waa hanti xarfaha iyo safafka oo keliya markaa ma // inoo baahna inaan hubino nooca if (typeof regex === 'undefined' || !regex.length) { throw new Error('Ma jiro regex la bixiyay'); } else if (Array.isArray(regex)) { regex = regex.join('|'); } if (typeof flags !== 'string') { flags = 'i'; } if (!preRegex || !preRegex.length) { preRegex = ''; } else if (Array.isArray(preRegex)) { preRegex = preRegex.join('|'); } // Regex waa mid aad u dhib badan si loo oggolaado qaababka wata // cabbiraadaha iyo in si sax ah loo maamulo boosaska bannaan this.text = this.text.replace( new RegExp( // booska bannaan ee hordhaca ah '^\\s*' + // qabashada qaabka(yada) '(?:((?:\\s*' + // Regex-ka ka hor qaabka, sida faallooyinka html ee hordhaca ah preRegex + '|' + // bilow qaabka qaabeynta '\\{\\{\\s*(?:' + // Qaabka Regex regex + // dhammaadka magaca qaabka ugu weyn, oo ikhtiyaari ah wata nambar // Malaha ka saar (?:) inkasta oo ')\\d*\\s*' + // cabbiraadaha qaabka '(\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?' + // dhammaadka qaabka qaabeynta '\\}\\})+' + // dhammaadka qabashada '(?:\\s*\\n)?)' + // booska bannaan ee daba-galka ah '\\s*)?', flags), '$1' + tag ); return this; }, /** * Hel wikitext-ka la wax ka beddelay. * * @return {string} */ getText: function() { return this.text; } }; /* *********** Morebits.UserspaceLogger ************ */ /** * Maamula falalka diiwaangelinta ee diiwaanka meesha isticmaalaha (userspace log). * Waxaa lagu isticmaalaa CSD, PROD, iyo XFD. * * @memberof Morebits * @class * @param {string} logPageName - Ciwaanka hoos-bogga ee diiwaanka isticmaalaha hadda. */ Morebits.UserspaceLogger = function(logPageName) { if (!logPageName) { throw new Error('magaca bogga diiwaanka lama cayimin'); } /** * Qoraalka lagu hormarinayo diiwaanka marka la abuurayo, wuxuu u degeysaa mid madhan. * * @type {string} */ this.initialText = ''; /** * Heerka madaxa ee loo isticmaalo bilaha, wuxuu u degeysaa 3 (`===`). * * @type {number} */ this.headerLevel = 3; this.changeTags = ''; /** * Diiwaangeli gelitaanka. * * @param {string} logText - Ma ku jiraan hordhaca `#` ama `*`. * @param {string} summaryText - Kooban wax ka beddelka. * @return {jQuery.Promise} */ this.log = function(logText, summaryText) { const def = $.Deferred(); if (!logText) { return def.reject(); } const page = new Morebits.wiki.Page('User:' + mw.config.get('wgUserName') + '/' + logPageName, 'Ku darida gelitaanka diiwaanka meesha isticmaalaha'); // ka dhig tan '... to ' + logPageName ? page.load((pageobj) => { // ku dar blurb haddii bogga diiwaanka uusan jirin ama uu madhan yahay let text = pageobj.getPageText() || this.initialText; // abuur madaxa bilaha ah haddii uusan jirin hore const date = new Morebits.Date(pageobj.getLoadTime()); if (!date.monthHeaderRegex().exec(text)) { text += '\n\n' + date.monthHeader(this.headerLevel); } pageobj.setPageText(text + '\n' + logText); pageobj.setEditSummary(summaryText); pageobj.setChangeTags(this.changeTags); pageobj.setCreateOption('recreate'); pageobj.save(def.resolve, def.reject); }); return def; }; }; /* **************** Morebits.Status **************** */ /** * Abuur oo muuji fariimaha xaaladda ee degdegga ah ee kala duwan. * {@link Morebits.Status.init|Morebits.Status.init()} waa in la waco ka hor inta aan la * abuurin shay xaalad ah, haddii kale xaaladahaas ma muuqan doonaan. * * @memberof Morebits * @class * @param {string} text - Qoraalka ka hor labada dhibcood `:`. * @param {string} stat - Qoraalka ka dib labada dhibcood `:`. * @param {string} [type=status] - Go'aami midabka farta ee xariiqda xaaladda, * qiimayaasha la oggol yahay waa: `status` (buluug), `info` (cagaar), `warn` (cas), * ama `error` (cas adag). */ Morebits.Status = function Status(text, stat, type) { this.textRaw = text; this.text = Morebits.createHtml(text); this.type = type || 'status'; this.generate(); if (stat) { this.update(stat, type); } }; /** * Cayim meel walxaha fariinta xaaladda lagu darayo. * * @memberof Morebits.Status * @param {HTMLElement} root - Badanaa waa shay div ah. * @throws {Error} Haddii `root` uusan ahayn `HTMLElement`. */ Morebits.Status.init = function(root) { if (!(root instanceof Element)) { throw new Error('shaygu ma aha tusaale ka mid ah Element'); } while (root.hasChildNodes()) { root.removeChild(root.firstChild); } Morebits.Status.root = root; Morebits.Status.errorEvent = null; }; Morebits.Status.root = null; /** * @memberof Morebits.Status * @param {Function} handler - Shaqada lagu fulinayo qaladka. * @throws {Error} Marka `handler` uusan ahayn shaqo. */ Morebits.Status.onError = function(handler) { if (typeof handler === 'function') { Morebits.Status.errorEvent = handler; } else { throw new Error('Morebits.Status.onError: handler ma aha shaqo'); } }; Morebits.Status.prototype = { stat: null, statRaw: null, text: null, textRaw: null, type: 'status', target: null, node: null, linked: false, /** Ku dar shayga xaaladda DOM-ka. */ link: function() { if (!this.linked && Morebits.Status.root) { Morebits.Status.root.appendChild(this.node); this.linked = true; } }, /** Ka saar shayga xaaladda DOM-ka. */ unlink: function() { if (this.linked) { Morebits.Status.root.removeChild(this.node); this.linked = false; } }, /** * Cusbooneysii xaaladda. * * @param {string} status - Qayb ka mid ah fariinta xaaladda ka dib labada dhibcood. * @param {string} type - 'status' (buluug), 'info' (cagaar), 'warn' * (cas), ama 'error' (cas adag). */ update: function(status, type) { this.statRaw = status; this.stat = Morebits.createHtml(status); if (type) { this.type = type; if (type === 'error') { // hack si loogu qasbo bogga inuu aanu dib u rarina marka qalad la soo saaro - fiiri sidoo kale Morebits.Status() kor ku xusan Morebits.wiki.numberOfActionsLeft = 1000; // yeero jawaab-celinta qaladka if (Morebits.Status.errorEvent) { Morebits.Status.errorEvent(); } // sidoo kale diiwaangeli fariimaha qaladka ee konsole-ka biraawsarka console.error(this.textRaw + ': ' + this.statRaw); // eslint-disable-line no-console } } this.render(); }, /** Soo saar html-ka qaybta koowaad ee fariinta xaaladda. */ generate: function() { this.node = document.createElement('div'); this.node.appendChild(document.createElement('span')).appendChild(this.text); this.node.appendChild(document.createElement('span')).appendChild(document.createTextNode(': ')); this.target = this.node.appendChild(document.createElement('span')); this.target.appendChild(document.createTextNode('')); // dummy node }, /** Dhammaystir html-ka, qaybta labaad ee fariinta xaaladda. */ render: function() { this.node.className = 'morebits_status_' + this.type; while (this.target.hasChildNodes()) { this.target.removeChild(this.target.firstChild); } this.target.appendChild(this.stat); this.link(); }, status: function(status) { this.update(status, 'status'); }, info: function(status) { this.update(status, 'info'); }, warn: function(status) { this.update(status, 'warn'); }, error: function(status) { this.update(status, 'error'); } }; /** * @memberof Morebits.Status * @param {string} text - Ka hor labada dhibcood * @param {string} status - Ka dib labada dhibcood * @return {Morebits.Status} - `status`-nooca (buluug) */ Morebits.Status.status = function(text, status) { return new Morebits.Status(text, status); }; /** * @memberof Morebits.Status * @param {string} text - Ka hor labada dhibcood * @param {string} status - Ka dib labada dhibcood * @return {Morebits.Status} - `info`-nooca (cagaar) */ Morebits.Status.info = function(text, status) { return new Morebits.Status(text, status, 'info'); }; /** * @memberof Morebits.Status * @param {string} text - Ka hor labada dhibcood * @param {string} status - Ka dib labada dhibcood * @return {Morebits.Status} - `warn`-nooca (cas) */ Morebits.Status.warn = function(text, status) { return new Morebits.Status(text, status, 'warn'); }; /** * @memberof Morebits.Status * @param {string} text - Ka hor labada dhibcood * @param {string} status - Ka dib labada dhibcood * @return {Morebits.Status} - `error`-nooca (cas adag) */ Morebits.Status.error = function(text, status) { return new Morebits.Status(text, status, 'error'); }; /** * Fariinta dhammaystirka falka ee dhamaadka, abuur xariiq xaalad ah oo aan lahayn * kala-soocaha laba dhibcood. * * @memberof Morebits.Status * @param {string} text */ Morebits.Status.actionCompleted = function(text) { const node = document.createElement('div'); node.appendChild(document.createElement('b')).appendChild(document.createTextNode(text)); node.className = 'morebits_status_info morebits_action_complete'; if (Morebits.Status.root) { Morebits.Status.root.appendChild(node); } }; /** * Muuji sababta isticmaalaha, faallooyinka, iwm. Dib ugu celi iyaga ka dib guuldarro, * si ay dib ugu isticmaalaan. * * @memberof Morebits.Status * @param {string} comments * @param {string} message */ Morebits.Status.printUserText = function(comments, message) { const p = document.createElement('p'); p.innerHTML = message; const div = document.createElement('div'); div.className = 'morebits-usertext'; div.style.marginTop = '0'; div.style.whiteSpace = 'pre-wrap'; div.textContent = comments; p.appendChild(div); Morebits.Status.root.appendChild(p); }; /** * Shaqo caawiye fudud si loo abuuro shay fudud. * * @param {string} type - Nooca shayga HTML. * @param {string} content - Nuxurka qoraalka. * @param {string} [color] - Midabka farta. * @return {HTMLElement} */ Morebits.htmlNode = function(type, content, color) { const node = document.createElement(type); if (color) { node.style.color = color; } node.appendChild(document.createTextNode(content)); return node; }; /** * Ku dar taageerada shift-click sanduuqyada hubinta. Nooca wikibits * (`window.addCheckboxClickHandlers`) wuxuu leeyahay xaddidaadyo qaar, mana la shaqeeyo * sanduuqyada hubinta ee ku dhex jira miiska la kala sooci karo, markaa aan dhisno mid adeer ah. * * @param {jQuery} jQuerySelector * @param {jQuery} jQueryContext */ Morebits.checkboxShiftClickSupport = function(jQuerySelector, jQueryContext) { let lastCheckbox = null; function clickHandler(event) { const thisCb = this; if (event.shiftKey && lastCheckbox !== null) { const $cbs = $(jQuerySelector, jQueryContext); // ma kaydin karo, si cad, haddii aan rabno inaan taageerno dib-u-kala-soocidda let index = -1, lastIndex = -1, i; for (i = 0; i < $cbs.length; i++) { if ($cbs[i] === thisCb) { index = i; if (lastIndex > -1) { break; } } if ($cbs[i] === lastCheckbox) { lastIndex = i; if (index > -1) { break; } } } if (index > -1 && lastIndex > -1) { // oo ay dhiiri gelisay wikibits const endState = thisCb.checked; let start, finish; if (index < lastIndex) { start = index + 1; finish = lastIndex; } else { start = lastIndex; finish = index - 1; } for (i = start; i <= finish; i++) { if ($cbs[i].checked !== endState) { $cbs[i].click(); } } } } lastCheckbox = thisCb; return true; } $(jQuerySelector, jQueryContext).on('click', clickHandler); }; /* **************** Morebits.BatchOperation **************** */ /** * Wuxuu dhex maraa koox bogag ah (ama shay caadi ah) wuxuuna fuliyaa shaqada shaqaale * mid kasta. * * `setPageList(pageList)`: Wuxuu dejiyaa liiska bogagga lagu shaqeynayo. Wuxuu noqon karaa * saf magacyada bogagga ah. * * `setOption(optionName, optionValue)`: Wuxuu dejiyaa xulasho la og yahay: * - `chunkSize` (nambar buuxa): Cabbirka xabbooyinka lagu jebinayo safka (caadiga ah * 50). Dejinta tan qiima yar (<5) waxay keeni kartaa dhibaatooyin. * - `preserveIndividualStatusLines` (boolean): Ma lagu hayaa shayga xaaladda bog kasta * muuqa marka shaqaaluhu dhammaado? Fiiri qoraalka hoose. * * `run(worker, postFinish)`: Wuxuu wadaa jawaab-celinta `worker` bog kasta oo ku jira * liiska. Jawaab-celintu waa inay wacdaa `workerSuccess` marka ay guulaysato, ama * `workerFailure` marka ay guuldarraysato. Haddii la isticmaalayo {@link Morebits.wiki.Api} ama * {@link Morebits.wiki.Page}, tani si fudud ayaa loo sameeyaa iyadoo la gudbinayo labadan * shaqo sida cabbiraadaha hababka shayadaas: tusaale ahaan, * `page.save(batchOp.workerSuccess, batchOp.workerFailure)`. Hubi in hababka * si toos ah loo waco haddii kiisas guul/guuldarro gaar ah ay soo baxaan. Haddii aad * ilowdo inaad wacdo hababkan, hawlgalka xirmada wuu istaagi doonaa ka dib xabbada * koowaad! Sidoo kale hubi in workerSuccess ama workerFailure aan la wicin * in ka badan hal mar. Jawaab-celinta labaad `postFinish` waxaa la fuliyaa marka * xirmada oo dhan la habeeyo. * * Haddii aad isticmaaleyso `preserveIndividualStatusLines`, waa inaad isku daydaa inaad hubiso in * jawaab-celinta `workerSuccess` ay heli karto cinwaanka bogga. Tani ma ahan dhibaato * {@link Morebits.wiki.Page} shayada. Laakiin marka la isticmaalayo API-ga, fadlan deji * hantida |pageName| ee shayga {@link Morebits.wiki.Api}. * * Waxaa jira hirgelinta batchOperation tusaale ah oo isticmaalaya Morebits.wiki.Page gudaha * twinklebatchdelete.js, twinklebatchundelete.js, iyo twinklebatchprotect.js. * * @memberof Morebits * @class * @param {string} [currentAction] */ Morebits.BatchOperation = function(currentAction) { const ctx = { // duurka dhabarka ee sifooyinka dadweynaha pageList: null, options: { chunkSize: 50, preserveIndividualStatusLines: false }, // xisaabaadka gudaha, iwm. statusElement: new Morebits.Status(currentAction || 'Fulinaya hawlgalka xirmada'), worker: null, // shaqada fulisa shay kasta oo ku jira pageList postFinish: null, // shaqada fulisa marka xirmada oo dhan la habeeyo countStarted: 0, countFinished: 0, countFinishedSuccess: 0, currentChunkIndex: -1, pageChunks: [], running: false }; // looma baahna in ay helaan isticmaalayaasha dibadda, laakiin waxaa la bixiyay si kastaba ha ahaatee si loo helo dabacsanaan ugu badan this.getStatusElement = function() { return ctx.statusElement; }; /** * Deji liiska bogagga lagu shaqeynayo. * * @param {Array} pageList - Safka shayada aad rabto inaad fuliso shaqada shaqaalaha * Tani badanaa waa liiska magacyada bogga (strings). */ this.setPageList = function(pageList) { ctx.pageList = pageList; }; /** * Deji xulasho la og yahay. * * @param {string} optionName - Magaca xulashada: * - chunkSize (nambar buuxa): Cabbirka xabbooyinka lagu jebinayo safka * (caadiga ah 50). Dejinta tan qiima yar (<5) waxay keeni kartaa dhibaatooyin. * - preserveIndividualStatusLines (boolean): Ma lagu hayaa shayga xaaladda bog kasta * muuqa marka shaqaaluhu dhammaado? * @param {number|boolean} optionValue - Qiimaha xulashada loogu * talagalay in la dejiyo. Waa inuu noqdaa nambar buuxa oo ah chunkSize iyo boolean ah * preserveIndividualStatusLines. */ this.setOption = function(optionName, optionValue) { ctx.options[optionName] = optionValue; }; /** * Waa daaweynta jawaab-celinta koowaad ee bog kasta oo ku jira liiska. * Jawaab-celintu waa inay wacdaa workerSuccess marka ay guulaysato, ama workerFailure marka ay guuldarraysato. * Waxaa la wadaa jawaab-celinta labaad ee ikhtiyaariga ah marka xirmada oo dhan la habeeyo. * * @param {Function} worker * @param {Function} [postFinish] */ this.run = function(worker, postFinish) { if (ctx.running) { ctx.statusElement.error('Hawlgalka xirmada ayaa horay u socda'); return; } ctx.running = true; ctx.worker = worker; ctx.postFinish = postFinish; ctx.countStarted = 0; ctx.countFinished = 0; ctx.countFinishedSuccess = 0; ctx.currentChunkIndex = -1; ctx.pageChunks = []; const total = ctx.pageList.length; if (!total) { ctx.statusElement.info('ma jiraan bogag la cayimay'); ctx.running = false; if (ctx.postFinish) { ctx.postFinish(); } return; } // u jebin liiska bogga xabbooyin si fudud loo maamuli karo ctx.pageChunks = Morebits.array.chunk(ctx.pageList, ctx.options.chunkSize); // billow habsocodka Morebits.wiki.addCheckpoint(); ctx.statusElement.status('0%'); fnStartNewChunk(); }; /** * Si loo waco shaqaalaha ka hor inta aysan si guul leh u dhammaan. * * @param {(Morebits.wiki.Page|Morebits.wiki.Api|string)} arg - * Tani waa inay noqotaa shayga `Morebits.wiki.Page` ama `Morebits.wiki.Api` ee ay isticmaashay shaqaaluhu * (si loo hagaajiyo xariiqyada xaaladda ee ay soo saareen). * Haddii aan la isticmaalin shay Morebits.wiki.* ah (tusaale waxaad isticmaaleysaa `mw.Api()` ama wax kale), iyo * xulashada `preserveIndividualStatusLines` ay shidan tahay, bixi magaca bogga (string) sida dood ahaan. */ this.workerSuccess = function(arg) { if (arg instanceof Morebits.wiki.Api || arg instanceof Morebits.wiki.Page) { // cusbooneysii ama ka saar xariiqda xaaladda const statelem = arg.getStatusElement(); if (ctx.options.preserveIndividualStatusLines) { if (arg.getPageName || arg.pageName || (arg.query && arg.query.title)) { // waan ognahay cinwaanka bogga - muuji fariin khuseysa const pageName = arg.getPageName ? arg.getPageName() : arg.pageName || arg.query.title; statelem.info('la dhammeeyay ([[' + pageName + ']])'); } else { // ma ogin cinwaanka bogga - kaliya muuji fariin guud statelem.info('la sameeyay'); } } else { // ka saar xariiqda xaaladda ee si otomaatig ah u soo saaray Morebits.wiki.* statelem.unlink(); } } else if (typeof arg === 'string' && ctx.options.preserveIndividualStatusLines) { new Morebits.Status(arg, 'la dhammeeyay ([[' + arg + ']])'); } ctx.countFinishedSuccess++; fnDoneOne(); }; this.workerFailure = function() { fnDoneOne(); }; // shaqooyinka gaarka ah (private functions) const thisProxy = this; var fnStartNewChunk = function() { const chunk = ctx.pageChunks[++ctx.currentChunkIndex]; if (!chunk) { return; // waa la dhammeeyay! yay } // billow shaqaalaha xabbada hadda ctx.countStarted += chunk.length; chunk.forEach((page) => { ctx.worker(page, thisProxy); }); }; var fnDoneOne = function() { ctx.countFinished++; // cusbooneysii xariiqda xaaladda guud const total = ctx.pageList.length; if (ctx.countFinished < total) { const progress = Math.round(100 * ctx.countFinished / total); ctx.statusElement.status(progress + '%'); // billow xabbo cusub haddii aan ku dhow nahay dhammaadka xabbadii hore, iyo // aynaan weli bilaabin tan xigta if (ctx.countFinished >= (ctx.countStarted - Math.max(ctx.options.chunkSize / 10, 2)) && Math.floor(ctx.countFinished / ctx.options.chunkSize) > ctx.currentChunkIndex) { fnStartNewChunk(); } } else if (ctx.countFinished === total) { const statusString = 'La dhammeeyay (' + ctx.countFinishedSuccess + '/' + ctx.countFinished + ' falal si guul leh ayay u dhammaadeen)'; if (ctx.countFinishedSuccess < ctx.countFinished) { ctx.statusElement.warn(statusString); } else { ctx.statusElement.info(statusString); } else { ctx.statusElement.info(statusString); } if (ctx.postFinish) { ctx.postFinish(); } Morebits.wiki.removeCheckpoint(); ctx.running = false; } else { // ctx.countFinished > total // kaliya qosol! (hagaag, cilad-bixin culus, dhab ahaantii) ctx.statusElement.warn('La dhammeeyay (la dhaafiyay ' + (ctx.countFinished - total) + ')'); Morebits.wiki.removeCheckpoint(); ctx.running = false; } }; }; /** * Marka la siiyo koox shaqooyin asynchronous ah si ay u wataan iyaga iyo tiirarkooda ku xiran, * ku wado taxane wax-ku-ool ah si shaqooyin badan * oo aan isku tiirsaneyn loo kiciyo isku mar. Halkaas oo ay * tiirsanaashuhu ka jiraan, waxay xaqiijineysaa in shaqooyinka ku xiran ay dhammeeyaan socodka * ka hor inta aysan shaqada ku xirni socon. Qiimayaasha ay xaliyeen tiirarka * waxaa la heli karaa midka ku xiran sida dood ahaan. * * @memberof Morebits * @class */ Morebits.TaskManager = function(context) { this.taskDependencyMap = new Map(); this.failureCallbackMap = new Map(); this.deferreds = new Map(); this.context = context || window; /** * Is-diiwaangeli shaqo iyada iyo tiirarkeeda ku xiran (shaqooyin ah inay dhammeeyaan * fulinta ka hor inta aysan bilaaban tan). Shaqo kasta waa shaqo ay tahay inay soo celiso * ballanqaad (promise). Shaqadu waxay heli doontaa qiimayaasha ay xaliyeen shaqooyinka tiirarka ku xiran * sida dood ahaan. * * @param {Function} func - Shaqo. * @param {Function[]} deps - Tiirarkeeda ku xiran. * @param {Function} [onFailure] - jawaab-celinta guuldarrada taas oo la wado haddii shaqada ama mid ka mid ah * tiirarkeeda ku xiran ay guuldarraysato. */ this.add = function(func, deps, onFailure) { this.taskDependencyMap.set(func, deps); this.failureCallbackMap.set(func, onFailure || (() => {})); const deferred = $.Deferred(); this.deferreds.set(func, deferred); }; /** * Wado dhammaan shaqooyinka. Shaqooyin badan ayaa la wadi karaa hal mar. * * @return {jQuery.Promise} - Waa la xaliyay haddii dhammaan shaqooyinka ay guulaystaan, waa la diiday haddii kale. */ this.execute = function() { const self = this; // wakiilka `this` si loogu isticmaalo gudaha shaqooyinka halkaas oo `this` uu yahay wax kale this.taskDependencyMap.forEach((deps, task) => { const dependencyPromisesArray = deps.map((dep) => self.deferreds.get(dep)); $.when.apply(self.context, dependencyPromisesArray).then(function() { const result = task.apply(self.context, arguments); if (result === undefined) { // malaha shaqadu way tuurtay, ama waxba ma soo celin mw.log.error('Morebits.TaskManager: shaqadu waxay soo celisay undefined'); self.deferreds.get(task).reject.apply(self.context, arguments); self.failureCallbackMap.get(task).apply(self.context, []); } result.then(function() { self.deferreds.get(task).resolve.apply(self.context, arguments); }, function() { // shaqadu waa guuldarraysatay self.deferreds.get(task).reject.apply(self.context, arguments); self.failureCallbackMap.get(task).apply(self.context, arguments); }); }, function() { // mid ama ka badan tiirarkii ku xirnaa ayaa guuldarraystay self.failureCallbackMap.get(task).apply(self.context, arguments); }); }); return $.when.apply(null, [...this.deferreds.values()]); // waa la xaliyay marka wax walba la dhammeeyo! }; }; /** * Daaqad fudud oo la jiidi karo. Mar dambe ma isticmaasho jQuery UI. * * @memberof Morebits * @class * @param {number} width * @param {number} height - Dhererka ugu badan ee la oggol yahay ee goobta nuxurka. */ Morebits.SimpleWindow = function SimpleWindow(width, height) { const $dialog = $('<div>').addClass('morebits-dialog').attr('role', 'dialog').attr('tabindex', -1); const $titleBar = $('<div>').addClass('morebits-dialog-titlebar').append( $('<span>').addClass('morebits-dialog-title'), $('<button>') .addClass('morebits-dialog-close') .text('\u00D7') .on('click', () => this.close()) ); const $content = $('<div>') .addClass('morebits-dialog-content') .attr('id', 'morebits-dialog-content-' + Math.round(Math.random() * 1e15)); const $buttonPane = $('<div>').addClass('morebits-dialog-buttonpane').append( $('<span>').addClass('morebits-dialog-buttons'), $('<span>').addClass('morebits-dialog-footerlinks') ); const $resizer = $('<div>').addClass('morebits-dialog-resizer'); $dialog.append($titleBar, $content, $buttonPane, $resizer) .css('width', Math.min(parseInt(width || 800, 10), $(window).width())) .css('height', 'auto') .css('max-height', height + 20) .css('top', Math.max(0, window.scrollY + $(window).height() / 2 - (height + 20) / 2)) // Xarreey (u qaado dhererka ugu badan) .css('left', Math.max(0, window.scrollX + $(window).width() / 2 - $dialog.width() / 2)); // Xarreey $dialog.on('focus', () => this.focus()).on('keydown', (e) => { if (e.key === 'Escape') { this.close(); } }); // Ka dhig wada-sheekaysiga mid la jiidi karo oo la cabbiri karo let isDragging = false, isResizing = false, initialX, initialY, initialWidth, initialHeight; $titleBar.on('mousedown', (e) => { isDragging = true; initialX = e.clientX - $dialog.offset().left; initialY = e.clientY - $dialog.offset().top; }); $resizer.on('mousedown', (e) => { isResizing = true; $dialog.css('height', $dialog.height()); $dialog.css('max-height', 'none'); initialWidth = $dialog.width(); initialHeight = $dialog.height(); initialX = e.clientX; initialY = e.clientY; }); $(document).on('mousemove', (e) => { if (isDragging) { $dialog.css('left', Math.max(0, e.clientX - initialX)) .css('top', Math.max(0, e.clientY - initialY)); } else if (isResizing) { $dialog.css('width', initialWidth + (e.clientX - initialX)) .css('height', initialHeight + (e.clientY - initialY)); } }).on('mouseup', () => { isDragging = false; isResizing = false; }); this.$dialog = $dialog; this.content = $content[0]; this.height = height; }; Morebits.SimpleWindow.prototype = { buttons: [], height: 600, hasFooterLinks: false, scriptName: null, /** * Keen wada-sheekaysi dusha sare, marka ay jiraan wada-sheekaysiyo kale oo is dul saaran oofuran. * * @return {Morebits.SimpleWindow} */ focus: function() { if (!this.$dialog.hasClass('morebits-dialog-modal')) { $('.morebits-dialog:not(.morebits-dialog-modal)').get() .filter((dialog) => dialog !== this.$dialog[0]) .concat(this.$dialog[0]) .forEach((dialog, idx) => { dialog.style.zIndex = 501 + idx; }); } return this; }, /** * Xir wada-sheekaysiga. Haddii tan loo dejiyo sida maareeyaha dhacdada, waxay joojin doontaa dhacdada * inaysan samayn wax kale. * * @param {event} [event] * @return {Morebits.SimpleWindow} */ close: function(event) { if (event) { event.preventDefault(); } this.setModality(false); this.$dialog.remove(); return this; }, /** * Muuji wada-sheekaysiga. Wicida display() ee wada-sheekaysi horay loo xiray 5 * laga yaabaa inuu shaqeeyo, laakiin lama damaanad qaadayo. * * @return {Morebits.SimpleWindow} */ display: function() { if (this.scriptName) { const $titleBar = this.$dialog.find('.morebits-dialog-title'); $titleBar.find('.morebits-dialog-scriptname').remove(); $titleBar.prepend($('<span>') .addClass('morebits-dialog-scriptname') .text(this.scriptName + ' \u00B7 ') // U+00B7 DOT DHEXE = &middot; ); } if (this.$dialog.find('.morebits-scrollbox').length) { // quickform waxay u baahan tahay CSS dheeri ah haddii ay ku dhacdo in ay ku jirto scrollbox. // Xulashada CSS :has() waxaa la isticmaali karaa mustaqbalka taas oo ah mid sahlan oo lagu kalsoonaan karo. this.$dialog.find('.quickform').addClass('has-scrollbox'); } this.$dialog.appendTo(document.body); // Geli diiradda shayga foomka koowaad ee wada-sheekaysiga, ama wada-sheekaysiga laftiisa. const $firstField = this.$dialog.find('input, select, textarea').first(); const $firstFieldOrDialog = $firstField.length ? $firstField : this.$dialog; $firstFieldOrDialog.trigger('focus'); return this; }, /** * Deji cinwaanka wada-sheekaysiga. * * @param {string} title * @return {Morebits.SimpleWindow} */ setTitle: function(title) { this.$dialog.find('.morebits-dialog-title').text(title); return this; }, /** * Deji magaca qoraalka, oo u muuqda hordhac cinwaanka si uu u caawiyo isticmaalayaasha go'aaminta kan * qoraalka isticmaalaha uu soo saarayo wada-sheekaysiga. Tusaale ahaan, qaybaha Twinkle waxay tan u dejiyaan "Twinkle". * * @param {string} name * @return {Morebits.SimpleWindow} */ setScriptName: function(name) { this.scriptName = name; return this; }, /** * Deji ballaca wada-sheekaysiga. * * @param {number} width * @return {Morebits.SimpleWindow} */ setWidth: function(width) { this.$dialog.css('width', width + 'px'); return this; }, /** * Deji dhererka ugu badan ee wada-sheekaysiga. Wada-sheekaysigu wuxuu si otomaatig ah u cabbiri doonaa si uu ugu habboonaado nuxurkiisa. * * @param {number} height * @return {Morebits.SimpleWindow} */ setHeight: function(height) { this.$dialog.css('height', 'auto'); this.$dialog.css('max-height', (height + 20) + 'px'); return this; }, /** * Deji nuxurka wada-sheekaysiga shayga node ee la bixiyay, badanaa laga soo qaaday soo bandhigidda * {@link Morebits.QuickForm}. * Dib u tirinaya badhamada hoose, laakiin waxay ka tagtaa xiriiriyeyaasha hoose sida ay yihiin. * Hubi inaad wacdo tan ugu yaraan hal mar ka hor inta aan la soo bandhigin wada-sheekaysiga... * * @param {HTMLElement} content * @return {Morebits.SimpleWindow} */ setContent: function(content) { this.purgeContent(); this.addContent(content); return this; }, /** * Ku dar shayga node ee la bixiyay nuxurka wada-sheekaysiga. * * @param {HTMLElement} content * @return {Morebits.SimpleWindow} */ addContent: function(content) { this.content.appendChild(content); // raadi badhamada gudbinta ee nuxurka, qari, oo ku dar badhan wakiil ah qaybta badhamada $(this.content).find('input[type="submit"], button[type="submit"]').get().forEach((node) => { node.style.display = 'none'; const button = document.createElement('button'); button.textContent = node.getAttribute('value') || node.textContent || 'Gudbi'; button.className = node.className || 'submitButtonProxy'; button.addEventListener('click', () => node.click(), false); this.buttons.push(button); }); // ka saar dhammaan badhamada qaybta badhamada oo dib ugu dar this.$dialog.find('.morebits-dialog-buttons') .empty() .append(...this.buttons) // Deji sifo data-empty ah oo keliya haddii aysan jirin badhamo. Waxaa isticmaala CSS. .attr('data-empty', this.buttons.length ? null : 'data-empty'); return this; }, /** * Ka saar dhammaan nuxurka wada-sheekaysiga, marka laga reebo xiriiriyeyaasha hoose. * * @return {Morebits.SimpleWindow} */ purgeContent: function() { this.buttons = []; // tirtir dhammaan badhamada qaybta badhamada this.$dialog.find('.morebits-dialog-buttons').empty(); $(this.content).empty(); return this; }, /** * Ku dar xiriiriye geeska midig ee hoose ee wada-sheekaysiga. * Tani waxaa loo isticmaali karaa in lagu bixiyo caawimaad ama xiriiriyeyaal siyaasadeed. * Tusaale ahaan, qaybta CSD ee Twinkle waxay ku darsataa xiriiriye bogga siyaasadda CSD, * iyo sidoo kala xiriiriye dokumentiga Twinkle. * * @param {string} text - Qoraalka la soo bandhigayo. * @param {string} wikiPage - Bartilmaameedka xiriiriyaha. * @return {Morebits.SimpleWindow} */ addFooterLink: function(text, wikiPage) { const $footerlinks = this.$dialog.find('.morebits-dialog-footerlinks'); if (this.hasFooterLinks) { const bullet = document.createElement('span'); bullet.textContent = ' \u2022 '; // U+2022 BULLET $footerlinks.append(bullet); } const link = document.createElement('a'); link.setAttribute('href', mw.util.getUrl(wikiPage)); link.setAttribute('title', wikiPage); link.setAttribute('target', '_blank'); link.textContent = text; $footerlinks.append(link); this.hasFooterLinks = true; return this; }, /** * Deji haddii daaqaddu ay noqoto mid modal ah iyo in kale. Wada-sheekaysiga Modal waxay abuurayaan 5 * lakab oo ka hooseeya wada-sheekaysiga laakiin ka sarreeya walxaha bogga kale. Tani * waa in la isticmaalo (haddii loo baahdo) ka hor inta aan la wicin display(). * * @param {boolean} [modal=false] - Haddii loo dejiyo true, walxaha kale ee * bogga waa la curyaamin doonaa, tusaale ahaan, loma dhex-geli karo. * @return {Morebits.SimpleWindow} */ setModality: function(modal) { if (modal) { $('<div>').addClass('morebits-dialog-overlay').appendTo(document.body); this.$dialog.addClass('morebits-dialog-modal'); } else { $('.morebits-dialog-overlay').remove(); this.$dialog.removeClass('morebits-dialog-modal'); } return this; } }; /** * Hawlgeli ama curyaami dhammaan badhamada hoose ee dhammaan {@link Morebits.SimpleWindow}-yada bogga hadda. * Tani waa in lagu wacaa `false` marka badhannadu ay noqdaan kuwa aan khusayn (tusaale isla markaana * ka hor inta aan la wicin {@link Morebits.Status.init}). * Tani ma aha hab tusaale ah si aysan macaamiishu ugu baahnin inay haystaan tixraac ku socda * shayga asalka ah ee `Morebits.SimpleWindow` ee meel fadhiya. Si kastaba ha ahaatee, inta badan wakhtiga * waxaa jiri doona oo keliya hal `Morebits.SimpleWindow` oo furan, markaa tani ma dhibayso. * * @memberof Morebits.SimpleWindow * @param {boolean} enabled */ Morebits.SimpleWindow.setButtonsEnabled = function(enabled) { $('.morebits-dialog-buttons button').prop('disabled', !enabled); }; // Magacyada fasalka ee la diiday (Deprecated) ee camelCase. Fadlan isticmaalkooda beddelkiisa isticmaal magacyada PascalCase. Morebits.batchOperation = Morebits.BatchOperation; Morebits.date = Morebits.Date; Morebits.quickForm = Morebits.QuickForm; Morebits.quickForm.element = Morebits.QuickForm.Element; Morebits.simpleWindow = Morebits.SimpleWindow; Morebits.status = Morebits.Status; Morebits.taskManager = Morebits.TaskManager; Morebits.unbinder = Morebits.Unbinder; Morebits.userspaceLogger = Morebits.UserspaceLogger; Morebits.wiki.api = Morebits.wiki.Api; Morebits.wiki.page = Morebits.wiki.Page; Morebits.wiki.preview = Morebits.wiki.Preview; Morebits.wikitext.page = Morebits.wikitext.Page; }()); // </nowiki> jff2bv9ynbp7clhze2407uls6qntupr MediaWiki:Gadget-script-installer-core.js 8 53741 311226 310935 2026-10-28T15:43:42Z Isma4l 41797 311226 javascript text/javascript ( function () { // Shayga mw.Api let api; // Keydi "common" bilowga const SKINS = [ 'common', 'monobook', 'minerva', 'vector', 'vector-2022', 'timeless' ]; // Imisa qoraal ayaan u baahannahy kahor inta aanaan soo bandhigin shaandhaynta degdegga ah? const NUM_SCRIPTS_FOR_SEARCH = 5; const imports = {}; const localScriptsByName = {}; // Imisa qoraal ayaa la rakibay? let scriptCount = 0; // Waxaa lagu daraa dhammaadka soo koobidda wax-ka-beddelka const ADVERT = ' ([[:en:User:Enterprisey/script-installer|rakibaha qoraalka]])'; /** * Xadhkaha (strings), ee turjumidda */ const STRINGS = { skinCommon: 'common (kuxiran dhammaan maqaallada/maqaarka)', backlink: 'Xiriirka dib u soo celinta:', installSummary: 'Rakibidda $1', installLinkText: 'Rakib', installProgressMsg: 'Waa la rakibayaa...', uninstallSummary: 'Ka saaridda $1', uninstallLinkText: 'Ka saar', uninstallProgressMsg: 'Waa la ka saarayaa...', disableSummary: 'Daminta $1', disableLinkText: 'Dami', disableProgressMsg: 'Waa la daminayaa...', enableSummary: 'Daaridda $1', enableLinkText: 'Daar', enableProgressMsg: 'Waa la daarayaa...', moveLinkText: 'Raree', moveProgressMsg: 'Waa la rarayaa...', movePrompt: 'Meesha loo socdo? Geli mid ka mid ah:', // waxaa ku xiga magacyada maqaarka/skins normalizeSummary: 'Hagaajinta rakibidda qoraallada', remoteUrlDesc: '$1, laga raray $2', panelHeader: 'Hadda waxaad haysataa qoraallada soo socda oo la rakibay (ka hel wax dheeraad ah WP:USL)', cannotInstall: 'Lama rakibi karo', cannotInstallSkin: 'Boggan waa mid ka mid ah bogaggaaga habaynta isticmaalaha, waana uu horay u shaqeyn karaa (ama wuu shaqeyn doonaa, haddii uu yahay common.js) markasta oo bogga la raro.', cannotInstallContentModel: "Qaabka nuxurka boggu waa $1, ee ma aha 'javascript'", insecure: '(amaah ama amni-darro)', // waxaa lagu isticmaalaa dhammaadka fariimaha qaar notJavaScript: 'ma aha JavaScript', installViaPreferences: 'Ku rakib iyada oo loo marayo dooqyada', showNormalizeLinks: 'Muuji xiriirada "hagaajinta"?', normalize: 'hagaaji', showMoveLinks: 'Muuji xiriirada "raridda"?', quickFilter: 'Shaandhaynta degdegga ah:', tempWarning: 'Rakibidda bogagga aan ahayn User, ama aan la ilaalin ee MediaWiki waa ku meel gaar waxaana laga yaabaa in la tirtiro mustaqbalka.', badPageError: 'Boggu ma aha User: ama MediaWiki: mana la ilaaliyo', manageUserScripts: 'Maaree qoraallada isticmaalaha', bigSecurityWarning: "Digniin!$1\n\nDhammaan qoraallada isticmaalaha waxay yeelan karaan nuxur xaasidnimo ah oo awood u leh inuu wax u dhimo koontadaada. Rakibidda qoraal waxay la macno tahay in dad kale ay beddeli karaan; hubi inaad ku kalsoon tahay qoraageeda. Haddii aadan hubin in qoraalku ammaan yahay, ka hubi golaha bulshada farsamada. Ma rakibtaa qoraalkan?", securityWarningSection: ' Waxaa la rabaa in la rakibo $1.' }; const USER_NAMESPACE_NAME = mw.config.get( 'wgFormattedNamespaces' )[ 2 ]; /** * Dhisidda Soo-dejinta (Import). Soo-dejintu waa xariiq ku jirta faylka JS oo soo dejineysa * qoraalka isticmaalaha. Astaamaha: * * KELIYAHADDA mid ka mid ah "page" ama "url" ayaa eber ah (null) soo-dejinta kasta. * * this.type = 0 haddii ay tahay maxalli (local), 1 haddii meel fog laga soo raray, iyo 2 haddii ay tahay URL. */ function Import( page, wiki, url, target, disabled ) { this.page = page; this.wiki = wiki; this.url = url; this.target = target; this.disabled = disabled; this.type = this.url ? 2 : ( this.wiki ? 1 : 0 ); } Import.ofLocal = function ( page, target, disabled ) { if ( disabled === undefined ) { disabled = false; } return new Import( page, null, null, target, disabled ); }; /** * URL-ka loo dhoofiyo. Waxay u qaadanaysaa wgScriptPath inuu yahay "/w" */ Import.ofUrl = function ( url, target, disabled ) { if ( disabled === undefined ) { disabled = false; } const URL_RGX = /^(?:https?:)?\/\/(.+?)\.org\/w\/index\.php\?.*?title=(.+?(?:&|$))/; const match = URL_RGX.exec( url ); if ( match ) { const title = decodeURIComponent( match[ 2 ].replace( /&$/, '' ) ), wiki = decodeURIComponent( match[ 1 ] ); return new Import( title, wiki, null, target, disabled ); } return new Import( null, null, url, target, disabled ); }; Import.fromJs = function ( line, target ) { const IMPORT_RGX = /^\s*(\/\/)?\s*importScript\s*\(\s*(?:"|')(.+?)(?:"|')\s*\)/; let match = IMPORT_RGX.exec( line ); if ( match ) { return Import.ofLocal( unescapeForJsString( match[ 2 ] ), target, !!match[ 1 ] ); } const LOADER_RGX = /^\s*(\/\/)?\s*mw\.loader\.load\s*\(\s*(?:"|')(.+?)(?:"|')\s*\)/; match = LOADER_RGX.exec( line ); if ( match ) { return Import.ofUrl( unescapeForJsString( match[ 2 ] ), target, !!match[ 1 ] ); } }; Import.prototype.getDescription = function ( useWikitext ) { switch ( this.type ) { case 0: return useWikitext ? ( '[[' + this.page + ']]' ) : this.page; case 1: return STRINGS.remoteUrlDesc.replace( '$1', this.page ).replace( '$2', this.wiki ); case 2: return this.url; } }; /** * URL bini'aadamku akhrin karo (oo aan khasab ku ahayn ResourceLoader). */ Import.prototype.getHumanUrl = function () { switch ( this.type ) { case 0: return '/wiki/' + encodeURI( this.page ); case 1: return '//' + this.wiki + '.org/wiki/' + encodeURI( this.page ); case 2: return this.url; } }; Import.prototype.toJs = function () { const dis = this.disabled ? '//' : ''; let url = this.url; switch ( this.type ) { case 0: return dis + "importScript('" + escapeForJsString( this.page ) + "'); // " + STRINGS.backlink + ' [[' + escapeForJsComment( this.page ) + ']]'; case 1: url = '//' + encodeURIComponent( this.wiki ) + '.org/w/index.php?title=' + encodeURIComponent( this.page ) + '&action=raw&ctype=text/javascript'; /* KU DHAC HOOS */ case 2: return dis + "mw.loader.load('" + escapeForJsString( url ) + "');"; } }; /** * Rakibaadda soo-dejinta. */ Import.prototype.install = function () { return api.postWithEditToken( { action: 'edit', title: getFullTarget( this.target ), summary: STRINGS.installSummary.replace( '$1', this.getDescription( /* useWikitext */ true ) ) + ADVERT, appendtext: '\n' + this.toJs() } ); }; /** * Hel dhammaan nambarada xariiqda ee bogga bartilmaameedka ah ee xusaya * qoraalka cayiman. */ Import.prototype.getLineNums = function ( targetWikitext ) { function quoted( s ) { return new RegExp( "(['\"])" + escapeForRegex( s ) + '\\1' ); } let toFind; switch ( this.type ) { case 0: toFind = quoted( escapeForJsString( this.page ) ); break; case 1: toFind = new RegExp( escapeForRegex( encodeURIComponent( this.wiki ) ) + '.*?' + escapeForRegex( encodeURIComponent( this.page ) ) ); break; case 2: toFind = quoted( escapeForJsString( this.url ) ); break; } const lineNums = [], lines = targetWikitext.split( '\n' ); for ( let i = 0; i < lines.length; i++ ) { if ( toFind.test( lines[ i ] ) ) { lineNums.push( i ); } } return lineNums; }; /** * Ka saarista soo-dejinta la bixiyay. Taasi waa, tirtir dhammaan xariiqyada bogga * bartilmaameedka ah ee soo dejinaya qoraalka cayiman. */ Import.prototype.uninstall = function () { const that = this; return getWikitext( getFullTarget( this.target ) ).then( ( wikitext ) => { const lineNums = that.getLineNums( wikitext ), newWikitext = wikitext.split( '\n' ).filter( ( _, idx ) => lineNums.indexOf( idx ) < 0 ).join( '\n' ); return api.postWithEditToken( { action: 'edit', title: getFullTarget( that.target ), summary: STRINGS.uninstallSummary.replace( '$1', that.getDescription( /* useWikitext */ true ) ) + ADVERT, text: newWikitext } ); } ); }; /** * Dejinta in soo-dejinta la bixiyay ay curyaan tahay (disabled), iyadoo sal looga dhigayo qiimaha * boolean-ka ee la bixiyay. */ Import.prototype.setDisabled = function ( disabled ) { const that = this; this.disabled = disabled; return getWikitext( getFullTarget( this.target ) ).then( ( wikitext ) => { const lineNums = that.getLineNums( wikitext ), newWikitextLines = wikitext.split( '\n' ); if ( disabled ) { lineNums.forEach( ( lineNum ) => { if ( newWikitextLines[ lineNum ].trim().indexOf( '//' ) !== 0 ) { newWikitextLines[ lineNum ] = '//' + newWikitextLines[ lineNum ].trim(); } } ); } else { lineNums.forEach( ( lineNum ) => { if ( newWikitextLines[ lineNum ].trim().indexOf( '//' ) === 0 ) { newWikitextLines[ lineNum ] = newWikitextLines[ lineNum ].replace( /^\s*\/\/\s*/, '' ); } } ); } const summary = ( disabled ? STRINGS.disableSummary : STRINGS.enableSummary ) .replace( '$1', that.getDescription( /* useWikitext */ true ) ) + ADVERT; return api.postWithEditToken( { action: 'edit', title: getFullTarget( that.target ), summary: summary, text: newWikitextLines.join( '\n' ) } ); } ); }; Import.prototype.toggleDisabled = function () { this.disabled = !this.disabled; return this.setDisabled( this.disabled ); }; /** * U rarista soo-dejintan fayl kale. */ Import.prototype.move = function ( newTarget ) { if ( this.target === newTarget ) { return; } const old = new Import( this.page, this.wiki, this.url, this.target, this.disabled ); this.target = newTarget; return $.when( old.uninstall(), this.install() ); }; function getAllTargetWikitexts() { return $.getJSON( mw.util.wikiScript( 'api' ), { format: 'json', action: 'query', prop: 'revisions', rvprop: 'content', rvslots: 'main', titles: SKINS.map( getFullTarget ).join( '|' ) } ).then( ( data ) => { if ( data && data.query && data.query.pages ) { const result = {}; Object.values( data.query.pages ).forEach( ( moreData ) => { const nameWithoutExtension = new mw.Title( moreData.title ).getNameText(); const targetName = nameWithoutExtension.substring( nameWithoutExtension.indexOf( '/' ) + 1 ); result[ targetName ] = moreData.revisions ? moreData.revisions[ 0 ].slots.main[ '*' ] : null; } ); return result; } } ); } function buildImportList() { return getAllTargetWikitexts().then( ( wikitexts ) => { Object.keys( wikitexts ).forEach( ( targetName ) => { const targetImports = []; if ( wikitexts[ targetName ] ) { const lines = wikitexts[ targetName ].split( '\n' ); let currImport; for ( let i = 0; i < lines.length; i++ ) { currImport = Import.fromJs( lines[ i ], targetName ); if ( currImport ) { targetImports.push( currImport ); scriptCount++; if ( currImport.type === 0 ) { if ( !localScriptsByName[ currImport.page ] ) { localScriptsByName[ currImport.page ] = []; } localScriptsByName[ currImport.page ].push( currImport.target ); } } } } imports[ targetName ] = targetImports; } ); } ); } /** * "Hagaajinta" (jaangooynta qaabdhismeedka) xariiqyada bogga habaynta * ee la bixiyay. */ function normalize( target ) { return getWikitext( getFullTarget( target ) ).then( ( wikitext ) => { const lines = wikitext.split( '\n' ), newLines = Array( lines.length ); let currImport; for ( let i = 0; i < lines.length; i++ ) { currImport = Import.fromJs( lines[ i ], target ); if ( currImport ) { newLines[ i ] = currImport.toJs(); } else { newLines[ i ] = lines[ i ]; } } return api.postWithEditToken( { action: 'edit', title: getFullTarget( target ), summary: STRINGS.normalizeSummary + ADVERT, text: newLines.join( '\n' ) } ); } ); } function conditionalReload( openPanel ) { if ( window.scriptInstallerAutoReload ) { if ( openPanel ) { document.cookie = 'open_script_installer=yes'; } window.location.reload( true ); } } /******************************************** * * Koodka UI * ********************************************/ function makePanel() { const $list = $( '<div>' ).attr( 'id', 'script-installer-panel' ) .append( $( '<header>' ).text( STRINGS.panelHeader ) ); const $container = $( '<div>' ).addClass( 'container' ).appendTo( $list ); // Meesha sanduuqyada calaamadaynta (checkboxes) $container.append( $( '<div>' ) .attr( 'class', 'checkbox-container' ) .append( $( '<input>' ) .attr( { id: 'siNormalize', type: 'checkbox' } ) .on( 'click', () => { $( '.normalize-wrapper' ).toggle( 0 ); } ), $( '<label>' ) .attr( 'for', 'siNormalize' ) .text( STRINGS.showNormalizeLinks ), $( '<input>' ) .attr( { id: 'siMove', type: 'checkbox' } ) .on( 'click', () => { $( '.move-wrapper' ).toggle( 0 ); } ), $( '<label>' ) .attr( 'for', 'siMove' ) .text( STRINGS.showMoveLinks ) ) ); if ( scriptCount > NUM_SCRIPTS_FOR_SEARCH ) { $container.append( $( '<div>' ) .attr( 'class', 'filter-container' ) .append( $( '<label>' ) .attr( 'for', 'siQuickFilter' ) .text( STRINGS.quickFilter ), $( '<input>' ) .attr( { id: 'siQuickFilter', type: 'text' } ) .on( 'input', function () { const filterString = $( this ).val(); if ( filterString ) { const sel = "#script-installer-panel li[name*='" + $.escapeSelector( $( this ).val() ) + "']"; $( '#script-installer-panel li.script' ).toggle( false ); $( sel ).toggle( true ); } else { $( '#script-installer-panel li.script' ).toggle( true ); } } ) ) ); // Hadda, ka saar sanduuqyada calaamadaynta jidka $container.find( '.checkbox-container' ) .css( 'float', 'right' ); } $.each( imports, ( targetName, targetImports ) => { const fmtTargetName = ( targetName === 'common' ? STRINGS.skinCommon : targetName ); if ( targetImports.length ) { $container.append( $( '<h2>' ).append( fmtTargetName, $( '<span>' ) .addClass( 'normalize-wrapper' ) .append( ' (', $( '<a>' ) .text( STRINGS.normalize ) .on( 'click', () => { normalize( targetName ).done( () => { conditionalReload( true ); } ); } ), ')' ) .hide() ), $( '<ul>' ).append( targetImports.map( ( anImport ) => $( '<li>' ) .addClass( 'script' ) .attr( 'name', anImport.getDescription() ) .append( $( '<a>' ) .text( anImport.getDescription() ) .addClass( 'script' ) .attr( 'href', anImport.getHumanUrl() ), ' (', $( '<a>' ) .text( STRINGS.uninstallLinkText ) .on( 'click', function () { $( this ).text( STRINGS.uninstallProgressMsg ); anImport.uninstall().done( () => { conditionalReload( true ); } ); } ), ' | ', $( '<a>' ) .text( anImport.disabled ? STRINGS.enableLinkText : STRINGS.disableLinkText ) .on( 'click', function () { $( this ).text( anImport.disabled ? STRINGS.enableProgressMsg : STRINGS.disableProgressMsg ); anImport.toggleDisabled().done( function () { $( this ).toggleClass( 'disabled' ); conditionalReload( true ); } ); } ), $( '<span>' ) .addClass( 'move-wrapper' ) .append( ' | ', $( '<a>' ) .text( STRINGS.moveLinkText ) .on( 'click', function () { let dest = null; const PROMPT = STRINGS.movePrompt + ' ' + SKINS.join( ', ' ); do { dest = ( window.prompt( PROMPT ) || '' ).toLowerCase(); } while ( dest && SKINS.indexOf( dest ) < 0 ); if ( !dest ) { return; } $( this ).text( STRINGS.moveProgressMsg ); anImport.move( dest ).done( () => { conditionalReload( true ); } ); } ) ) .hide(), ')' ) .toggleClass( 'disabled', anImport.disabled ) ) ) ); } } ); return $list; } function buildCurrentPageInstallElement() { let addingInstallLink = false; // miyaanu ku daraynaa xiriir rakibid oo sax ah? const $installElement = $( '<span>' ); // waxaa la isticmaalaa oo keliya haddii addingInstallLink loo dejiyeen run (true) const namespaceNumber = mw.config.get( 'wgNamespaceNumber' ); const pageName = mw.config.get( 'wgPageName' ); // Magaca bannaan (Namespace) 2 waa User if ( namespaceNumber === 2 && pageName.indexOf( '/' ) > 0 ) { const contentModel = mw.config.get( 'wgPageContentModel' ); if ( contentModel === 'javascript' ) { const prefixLength = mw.config.get( 'wgUserName' ).length + 6; if ( pageName.indexOf( USER_NAMESPACE_NAME + ':' + mw.config.get( 'wgUserName' ) ) === 0 ) { const skinIndex = SKINS.indexOf( pageName.substring( prefixLength ).slice( 0, -3 ) ); if ( skinIndex >= 0 ) { return $( '<abbr>' ).text( STRINGS.cannotInstall ) .attr( 'title', STRINGS.cannotInstallSkin ); } } addingInstallLink = true; } else { return $( '<abbr>' ).text( STRINGS.cannotInstall + ' (' + STRINGS.notJavaScript + ')' ) .attr( 'title', STRINGS.cannotInstallContentModel.replace( '$1', contentModel ) ); } } // Magaca bannaan (Namespace) 8 waa MediaWiki if ( namespaceNumber === 8 ) { return $( '<a>' ).text( STRINGS.installViaPreferences ) .attr( 'href', mw.util.getUrl( 'Special:Preferences' ) + '#mw-prefsection-gadgets' ); } const editRestriction = mw.config.get( 'wgRestrictionEdit' ) || []; if ( ( namespaceNumber !== 2 && namespaceNumber !== 8 ) && ( editRestriction.indexOf( 'sysop' ) >= 0 || editRestriction.indexOf( 'editprotected' ) >= 0 ) ) { $installElement.append( ' ', $( '<abbr>' ).append( $( '<img>' ).attr( 'src', 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Achtung-yellow.svg/20px-Achtung-yellow.svg.png' ).addClass( 'warning' ), STRINGS.insecure ) .attr( 'title', STRINGS.tempWarning ) ); addingInstallLink = true; } if ( addingInstallLink ) { const fixedPageName = mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ); $installElement.prepend( $( '<a>' ) .attr( 'id', 'script-installer-main-install' ) .text( localScriptsByName[ fixedPageName ] ? STRINGS.uninstallLinkText : STRINGS.installLinkText ) .on( 'click', makeLocalInstallClickHandler( fixedPageName ) ) ); // Haddii qoraalka la rakibay laakiin uu curyaan yahay, u oggolow isticmaalaha inuu daarayo const allScriptsInTarget = imports[ localScriptsByName[ fixedPageName ] ]; const importObj = allScriptsInTarget && allScriptsInTarget.find( ( anImport ) => anImport.page === fixedPageName ); if ( importObj && importObj.disabled ) { $installElement.append( ' | ', $( '<a>' ) .attr( 'id', 'script-installer-main-enable' ) .text( STRINGS.enableLinkText ) .on( 'click', function () { $( this ).text( STRINGS.enableProgressMsg ); importObj.setDisabled( false ).done( () => { conditionalReload( false ); } ); } ) ); } return $installElement; } return $( '<abbr>' ).text( STRINGS.cannotInstall + ' ' + STRINGS.insecure ) .attr( 'title', STRINGS.badPageError ); } function showUi() { $( '#firstHeading' ).append( $( '<span>' ) .attr( 'id', 'script-installer-top-container' ) .append( buildCurrentPageInstallElement(), ' | ', $( '<a>' ) .text( STRINGS.manageUserScripts ).on( 'click', () => { if ( !document.getElementById( 'script-installer-panel' ) ) { $( '#mw-content-text' ).before( makePanel() ); } else { $( '#script-installer-panel' ).remove(); } } ) ) ); } function attachInstallLinks() { // Dhamaadka tarjumaad kasta oo {{Userscript}}, waxaa jira // <span id='User:Foo/Bar.js' class='scriptInstallerLink'></span> $( 'span.scriptInstallerLink' ).each( function () { const scriptName = this.id.replace( /_/g, ' ' ); $( this ).append( ' | ', $( '<a>' ) .text( localScriptsByName[ scriptName ] ? STRINGS.uninstallLinkText : STRINGS.installLinkText ) .on( 'click', makeLocalInstallClickHandler( scriptName ) ) ); } ); // Ku dar badhan rakibid oo buluug ah oo weyn {{Infobox user script}} kasta $( 'table.infobox-user-script' ).each( function () { const $infoboxScriptField = $( this ).find( "th:contains('Source')" ).next(); let scriptName = mw.config.get( 'wgPageName' ); const isHyperlink = $infoboxScriptField.html() !== $infoboxScriptField.text(); if ( isHyperlink ) { const $link = $infoboxScriptField.find( 'a' ).first(); const isExternalLink = $link.hasClass( 'external' ); if ( !isExternalLink ) { scriptName = /\/wiki\/(.*)/.exec( $link.attr( 'href' ) )[ 1 ]; } } else { scriptName = $infoboxScriptField.text(); } scriptName = /user:.+?\/.+?.js/i.exec( scriptName )[ 0 ]; scriptName = scriptName.replace( /_/g, ' ' ); // hubi in magaca qoraalku uusan lahayn hoosta ka xarriiq (underscores) $( this ).children( 'tbody' ).append( $( '<tr>' ).append( $( '<td>' ) .attr( 'colspan', '2' ) .addClass( 'script-installer-ibx' ) .append( $( '<button>' ) .addClass( 'mw-ui-button mw-ui-progressive mw-ui-big' ) .text( localScriptsByName[ scriptName ] ? STRINGS.uninstallLinkText : STRINGS.installLinkText ) .on( 'click', makeLocalInstallClickHandler( scriptName ) ) ) ) ); }); } function makeLocalInstallClickHandler( scriptName ) { return function () { const $this = $( this ); if ( $this.text() === STRINGS.installLinkText ) { const okay = window.confirm( STRINGS.bigSecurityWarning.replace( '$1', STRINGS.securityWarningSection.replace( '$1', scriptName ) ) ); if ( okay ) { $( this ).text( STRINGS.installProgressMsg ); Import.ofLocal( scriptName, window.scriptInstallerInstallTarget ).install().done( () => { $( this ).text( STRINGS.uninstallLinkText ); conditionalReload( false ); } ); } } else { $( this ).text( STRINGS.uninstallProgressMsg ); const uninstalls = uniques( localScriptsByName[ scriptName ] ) .map( ( target ) => Import.ofLocal( scriptName, target ).uninstall() ); $.when.apply( $, uninstalls ).then( () => { $( this ).text( STRINGS.installLinkText ); conditionalReload( false ); } ); } }; } /******************************************** * * Shaqooyinka kaalmada (Utility functions) * ********************************************/ /** * Hel wikitext-ka bogga oo wata cinwaanka la bixiyay (magaca bannaanka / namespace ayaa loo baahan yahay). */ function getWikitext( title ) { return $.getJSON( mw.util.wikiScript( 'api' ), { format: 'json', action: 'query', prop: 'revisions', rvprop: 'content', rvslots: 'main', rvlimit: 1, titles: title } ).then( ( data ) => { const pageId = Object.keys( data.query.pages )[ 0 ]; if ( data.query.pages[ pageId ].revisions ) { return data.query.pages[ pageId ].revisions[ 0 ].slots.main[ '*' ]; } return ''; } ); } function escapeForRegex( s ) { return s.replace( /[-/\\^$*+?.()|[\]{}]/g, '\\$&' ); } /** * Ka baxsashada xadhig si loogu isticmaalo xadhig suugaaneed JavaScript ah. * Shaqadan waxaa laga soo qaatay * https://github.com/joliss/js-string-escape/blob/6887a69003555edf5c6caaa75f2592228558c595/index.js * (waxaa lagu sii daayay shatiga MIT). */ function escapeForJsString( s ) { return s.replace( /["'\\\n\r\u2028\u2029]/g, ( character ) => { switch ( character ) { case '"': case "'": case '\\': return '\\' + character; case '\n': return '\\n'; case '\r': return '\\r'; case '\u2028': return '\\u2028'; case '\u2029': return '\\u2029'; } } ); } /** * Ka baxsashada xadhig si loogu isticmaalo faallo JavaScript ah oo dhexda ku jirta (faallooyinka ku billowda labada jeex "//"). */ function escapeForJsComment( s ) { return s.replace( /[\n\r\u2028\u2029]/g, ( character ) => { switch ( character ) { case '\n': return '\\n'; case '\r': return '\\r'; case '\u2028': return '\\u2028'; case '\u2029': return '\\u2029'; } } ); } /** * Dib-u-soo-celinta xadhig suugaaneed JavaScript ah. */ function unescapeForJsString( s ) { return s.replace( /\\"|\\'|\\\\|\\n|\\r|\\u2028|\\u2029/g, ( substring ) => { switch ( substring ) { case '\\"': return '"'; case "\\'": return "'"; case '\\\\': return '\\'; case '\\r': return '\r'; case '\\n': return '\n'; case '\\u2028': return '\u2028'; case '\\u2029': return '\u2029'; } } ); } function getFullTarget( target ) { return USER_NAMESPACE_NAME + ':' + mw.config.get( 'wgUserName' ) + '/' + target + '.js'; } // Laga soo qaatay https://stackoverflow.com/a/10192255 function uniques( array ) { return array.filter( ( el, index, arr ) => index === arr.indexOf( el ) ); } if ( window.scriptInstallerAutoReload === undefined ) { window.scriptInstallerAutoReload = true; } if ( window.scriptInstallerInstallTarget === undefined ) { window.scriptInstallerInstallTarget = 'common'; // si caadi ah, ugu rakib waxyaabaha common.js ee isticmaalaha } const jsPage = mw.config.get( 'wgPageName' ).slice( -3 ) === '.js' || mw.config.get( 'wgPageContentModel' ) === 'javascript'; $.when( $.ready, mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ) ).then( () => { api = new mw.Api(); buildImportList().then( () => { attachInstallLinks(); if ( jsPage ) { showUi(); } // Si otomaatig ah u fur guddiga haddii aan dejino cookie-ga si aan sidaas u yeelno (eeg `conditionalReload()`) if ( document.cookie.indexOf( 'open_script_installer=yes' ) >= 0 ) { document.cookie = 'open_script_installer=; expires=Thu, 01 Jan 1970 00:00:01 GMT'; $( "#script-installer-top-container a:contains('Manage')" ).trigger( 'click' ); } } ); } ); }() ); engylqu4umqd6pdizvxunzv0hymglf2 MediaWiki:Timeless.css 8 53973 311223 2026-10-28T13:53:46Z Isma4l 41797 Abuuray 311223 css text/css /* Ha soo bandhigin waxyaabaha qaarkood bogga hore */ .page-Main_Page #deleteconfirm, .page-Main_Page #t-cite, .page-Main_Page #footer-info-lastmod, .action-view.page-Main_Page #siteSub, .action-view.page-Main_Page #contentSub { display: none !important; } /* Meelaynta isku-duwayaasha */ .mw-body-content #coordinates { position: absolute; top: 0.25em; right: 0; float: right; margin: 0; padding: 0; line-height: 1.5em; text-align: right; text-indent: 0; font-size: 85%; text-transform: none; white-space: nowrap; } .mw-indicators { position: relative; } #mw-indicator-coordinates { font-size: 13px; } #mw-indicator-coordinates #coordinates { top: 4.7em; } /* Meelaynta saxda ah ee VE */ .ve-ce-surface #coordinates { margin-right: 3em; margin-top: -6.25; } /* Moobaylka: qari isku duwayaasha ilaa aan ka helayno meel ka habboon */ @media screen and ( max-width: 719px ) { #coordinates { display: none; } } /* Habaynta calaamadaha ku jira bogagga isbeddellada */ .mw-tag-markers { font-style: italic; font-size: 90%; } bp1s9bjzyugfmlw79fa3x2ypfdzd3h9 311224 311223 2026-10-28T13:54:15Z Isma4l 41797 311224 css text/css /* Ha soo bandhigin waxyaabaha qaarkood bogga hore */ .page-Bogga_Hore #deleteconfirm, .page-Bogga_Hore #t-cite, .page-Bogga_Hore #footer-info-lastmod, .action-view.page-Bogga_Hore #siteSub, .action-view.page-Bogga_Hore #contentSub { display: none !important; } /* Meelaynta isku-duwayaasha */ .mw-body-content #coordinates { position: absolute; top: 0.25em; right: 0; float: right; margin: 0; padding: 0; line-height: 1.5em; text-align: right; text-indent: 0; font-size: 85%; text-transform: none; white-space: nowrap; } .mw-indicators { position: relative; } #mw-indicator-coordinates { font-size: 13px; } #mw-indicator-coordinates #coordinates { top: 4.7em; } /* Meelaynta saxda ah ee VE */ .ve-ce-surface #coordinates { margin-right: 3em; margin-top: -6.25; } /* Moobaylka: qari isku duwayaasha ilaa aan ka helayno meel ka habboon */ @media screen and ( max-width: 719px ) { #coordinates { display: none; } } /* Habaynta calaamadaha ku jira bogagga isbeddellada */ .mw-tag-markers { font-style: italic; font-size: 90%; } qnex1lc1e5sqoaogiaf52f6n0c3zzq5 Sayid Xasan Imaam Rizvi Zangipuri 0 53974 311233 2026-10-29T06:06:36Z NormieIndian 48061 Bog cusub: '''Ayatollah Syed Hasan Imam Rizvi Zangipuri''' (wuxuu dhashay 2-dii Maarso 1974) waa [[Faqiih]], wadaad diineed, [[Mujtahid]] iyo hoggaamiye diineed oo Hindi ah, kana tirsan [[Islaamka Shiicada|Shiicada]].<ref>{{Cite book|url=https://openlibrary.org/books/OL62675026M/Contemporary_Shia_Religious_Leadership_in_the_Indian_Diaspora|title=Contemporary Shia Religious Leadership in the Indian Diaspora|last=Al-Musawi|first=Hassan|date=2022|publisher=Dar al-Thaqalayn Publications|locatio... 311233 wikitext text/x-wiki '''Ayatollah Syed Hasan Imam Rizvi Zangipuri''' (wuxuu dhashay 2-dii Maarso 1974) waa [[Faqiih]], wadaad diineed, [[Mujtahid]] iyo hoggaamiye diineed oo Hindi ah, kana tirsan [[Islaamka Shiicada|Shiicada]].<ref>{{Cite book|url=https://openlibrary.org/books/OL62675026M/Contemporary_Shia_Religious_Leadership_in_the_Indian_Diaspora|title=Contemporary Shia Religious Leadership in the Indian Diaspora|last=Al-Musawi|first=Hassan|date=2022|publisher=Dar al-Thaqalayn Publications|location=[[Najaf]], [[Karbala]]|pages=Unit 7, Allamah Maulana Syed Hasan Imam, Page 49 to Page 57|ol=62675026M}}</ref> Waxa uu muddo ka badan [[2|laba]] [[Toban sano|toban sano]] u soo shaqaynayay [[Imaam|Imaamka Salaadda Jimcaha]] ee Masjidka Haidery Jama ee Mira Road, [[Mumbai]].<ref name="inquilab2021">{{cite news|date=27 November 2021|title=وسیم رضوی کے خلاف میراروڈ کے مسلمانوں میں بھی شدید بے چینی اور اضطراب|language=Urdu|trans-title=Extreme unrest and anxiety among the Muslims of Mira Road against Wasim Rizvi|work=Inquilab|url=https://www.inquilab.com/news/articles/extreme-unrest-and-anxiety-among-the-muslims-of-mira-road-against-wasim-rizvi-31886}}</ref><ref>{{Cite book|url=http://archive.org/details/the-shia-times-2-successful-decades-of-maulana-hasan-imam-rizvi|title=The Shia Times, 2 Successful Decades Of Maulana Hasan Imam Rizvi|last=The Shia Times|date=2022-03-09}}</ref> == Dhaxalka == Zangipuri waxa uu ku dhashay bishii Maarso 1974 magaalada Jangipur, Ghazipur.<ref name=":1">{{Cite web|title=Internet Archive: Digital Library of Free & Borrowable Texts, Movies, Music & Wayback Machine|url=https://archive.org/details/the-shia-times-shia-olama-magazine-2005-pg-19-maulana-hasan-imam-rizvi|access-date=2026-10-17|website=archive.org}}</ref> Waxa uu waxbarashadiisii aasaasiga ahayd ku qaatay [[Hindiya]], dabadeedna waxa uu u guuray [[Qom]], [[Iiraan]]<ref name=":2">{{Cite book|url=https://openlibrary.org/books/OL62675024M/The_Family_of_Masters|title=The Family of Masters|last=Falkenberger|first=Matthias|date=|publisher=Falkenberger Verlag|year=2026|location=[[Frankfurt am Main]], [[Germany]]|pages=Chapter no 12- Syed Hasan Imam Rizvi Zangipuri, Page 70 to Page 110|ol=62675024M}}</ref>, halkaas oo uu waxbarasho ka waday [[Madaarista Qom|Madaarasada Diineed ee Qom]] muddo ka badan toban sano<ref name=":2" />. Intaa waxaa dheer, Zangipuri waxa uu ahaa [[Hormuud (waxbarasho)|Hormuudka]] Hawzah-e-Sahibe Zamaan, oo ah [[madarasad]] Shiico oo ku taalla Qom, Iiraan.<ref>{{Cite book|url=https://openlibrary.org/books/OL62675031M/Qom_Ke_Ayyam|title=Qom Ke Ayyam|last=Ahmed|first=Syed|date=1995|publisher=Original Publisher: Qom Publications Place of Publication: Qom, Iran Year of Original Publication: 1995 Republished by: Zarr Press Place of Republishing: Dasht-e Barchi, District 13, Kabul, Afghanistan Year of Republishing: 1997|location=Qom, Iran and Dasht-e Barchi, District 13, Kabul, Afghanistan|pages=Page 5-6|ol=62675031M}}</ref><ref>Maulana Syed Ahmed, Qom ke Ayyam, p.22&23, Kabul</ref>. Waxa uu ahaa qofkii ugu horreeyay ee Hindi ah ee qabta xilka hormuudka Hawzah-e-Sahibe Zamaan.<ref>{{Cite book|url=https://openlibrary.org/books/OL62675031M/Qom_Ke_Ayyam|title=Qom Ke Ayyam|last=Ahmed|first=Syed|date=1995|publisher=Original Publisher: Qom Publications Place of Publication: Qom, Iran Year of Original Publication: 1995 Republished by: Zarr Press Place of Republishing: Dasht-e Barchi, District 13, Kabul, Afghanistan Year of Republishing: 1997|location=Qom, Iran and Dasht-e Barchi, District 13, Kabul, Afghanistan|pages=Page no 9|ol=62675031M}}</ref>. Zangipuri waxa uu xilka ka tegay sannadkii 2002, isaga oo ku soo laabtay Hindiya.<ref>{{Cite book|url=https://openlibrary.org/books/OL62675031M/Qom_Ke_Ayyam|title=Qom Ke Ayyam|last=Afghanistani|first=Maulana Syed Ahmed|date=1995|publisher=Original Publisher: Qom Publications Place of Publication: Qom, Iran Year of Original Publication: 1995 Republished by: Zarr Press Place of Republishing: Dasht-e Barchi, District 13, Kabul, Afghanistan Year of Republishing: 1997|location=Qom, Iran and Dasht-e Barchi, District 13, Kabul, Afghanistan|pages=Page no 13-14|ol=62675031M}}</ref><ref>Maulana Syed Ahmed, Qom ke Ayyam, P.17, Iran</ref> Markii uu Hindiya ku soo laabtay, waxa loo soo bandhigay xilka [[Imaam|Imaamka Salaadda Jimcaha]] ee Mira Road, oo ah xaafad ku taalla galbeedka [[Mumbai]]. Tan iyo 2003, waxa uu si joogto ah u hayay xilka [[Imaam|Imaamka Salaadda Jimcaha]], dabadeedna waxa uu noqday hoggaamiyaha [[Islaamka Shiicada|bulshada Shiicada]].<ref>{{Cite web|last=IbrahimShaykh|date=2026-10-15|title=Syed Hasan Imam Rizvi: A Prominent Religious Leader and One of Most Influential Muslim Figures|url=https://submitpr.org/press-release/syed-hasan-imam-rizvi-a-prominent-religious-leader-and-one-of-most-influential-muslim-figures|access-date=2026-10-17|website=SubmitPR Free|language=en}}</ref> Warbixinnadu waxay sheegayaan in Zangipuri uu leeyahay in ka badan 100,000 oo raacsan.<ref>{{Cite book|url=https://openlibrary.org/books/OL62675030M/Religious_Authority_and_Social_Change_among_Twelver_Shia_Communities|title=Religious Authority and Social Change among Twelver Shia Communities|last=Cohen|first=David Michael|date=2024|publisher=Meridian Scholarly Publications|location=New York, United States|pages=Ayatollah Syed Hasan Imam Rizvi, Page 109 to Page 130|ol=62675030M}}</ref><ref name=":3">{{Cite book|url=https://openlibrary.org/books/OL62675025M/Ulama_of_the_Indian_Subcontinent_Biographical_Profiles_and_Intellectual_Traditions|title=Ulama of the Indian Subcontinent: Biographical Profiles and Intellectual Traditions|last=Naqvi|first=Syed Abbas|date=2023|publisher=Maktaba-e-Tahqiq, Pakistan|location=Karachi, Pakistan|pages=Section 19, Naqeeb-ul-Millat Ayatollah Syed Hasan Imam Rizvi, Page 127 to Page 149|ol=62675025M}}</ref><ref>{{Cite book|url=https://openlibrary.org/books/OL62675027M/Faith_and_Public_Leadership_among_India's_Muslim_Minorities|title=Faith and Public Leadership among India's Muslim Minorities|last=Williams|first=Eleanor J.|date=2024|publisher=Meridian Studies Press|location=New York, United States|ol=62675027M}}</ref> Ayatollah Zangipuri waxa lagu yaqaannaa magaca ''Naqeeb ul Millat'', oo macnihiisu yahay “hoggaamiyaha bulshada”.<ref name=":3" /><ref name=":4">{{Cite book|url=https://openlibrary.org/books/OL62675032M/Indian_Muslim_Legends|title=Indian Muslim Legends: A Comprehensive Historical Encyclopedia of Muslim scholars, Sufis, poets, philosophers, educators and reformers of Indian Sub continent.|last=Levesque|first=Dr Robert|date=2026|publisher=RL Publishing, USA|location=Fremont, California, United States|pages=Chapter 73, Page 465-467|doi=10.5281/zenodo.23338154}}</ref><ref name=":5">{{Cite book|url=https://zenodo.org/records/23338154|title=Indian Muslim Legends|last=Levesque|first=Dr. Robert|publisher=RL Publishing, USA|location=Fremont, California, United States|pages=Chapter No 73- Syed Hasan Imam Rizvi, Page 464 to Page 472|doi=10.5281/zenodo.23338154|ol=62675032M}}</ref> Waxa kale oo loo yaqaan ''Daqeeq ul Daqaaeq'', oo macnihiisu yahay “kan ugu wanaagsan waxyaabaha wanaagsan”.<ref name=":4" /><ref name=":5" /> ''Allamah'' waa magac sharafeed loo isticmaalo aqoonyahannada.<ref name=":4" /><ref name=":5" /> Waxa kale oo lagu yaqaan ''Aaftab-e-Imamat'', oo macnihiisu yahay “Qorraxda Imaamnimada”.<ref name=":4" /><ref name=":5" /> ''Maulana'', oo sidoo kale loo qoro Mawlana ama Molana, waa magac xushmad leh oo inta badan loo adeegsado culimada diinta Islaamka.<ref name=":5" /> Ururin ka kooban [[Khudbad|khudbadihiisa]] ayaa lagu daabacay buug cinwaankiisu yahay ''Mimbar-e-Mudallal'', kaas oo uu qoray Syed Mehdi Jafri, oo ah qoraa u dhashay Pakistan, waxaana daabacday Idara-e-Ma'arif Publications oo ku taalla [[Karachi]], [[Pakistan]].<ref>{{Cite book|url=https://openlibrary.org/books/OL62675029M/Mimbar-e-Mudallal|title=Mimbar-e-Mudallal: Sermons and Intellectual Contributions of Syed Hasan Imam Rizvi|last=Jafri|first=Syed Mehdi|date=2023|publisher=Idara-e-Ma'arif Publications|location=Karachi, Pakistan|ol=OL62675029M}}</ref> == Aragtiyaha == Wargeyska ''Inquilab'', oo ah [[wargeys maalinle ah|wargeys maalinle ah oo ku baxa afka Urduuga]], ayaa Zangipuri ku tilmaamay Imaam iyo [[Afhayeen]].<ref name="inquilab2021" /> Muddo sannado ah, waxa uu jeediyay khudbado diini ah, wuxuuna ka qaybgalay barnaamijyo diimeed iyo kuwo [[bulsho]] oo kala duwan oo ay bulshada [[Islaamka Shiicada|Shiicadu]] ku qabatay Mira Road iyo meelo kale. Bishii Maarso 2025, Zangipuri waxa uu ka hadlay arrimo la xiriira [[Maalinta Qudus]], [[Falastiin]] iyo midnimada Muslimiinta.<ref name="quds2025">{{cite news|date=29 March 2025|title=رمضان المبارک کے آخری جمعہ کوشہر و مضافات میں ’یوم القدس‘ منایا گیا|language=Urdu|trans-title=Quds Day was observed in the city and suburbs on the last Friday of Ramadan|work=Inquilab|url=https://www.inquilab.com/news/articles/quds-day-was-celebrated-in-the-city-and-suburbs-on-the-last-friday-of-ramadan-75185}}</ref> Bishii Diseembar 2025, Inquilab waxa uu soo tebiyay shir cinwaankiisu ahaa ''"Shirka Seerat-un-Nabi iyo Ittehad-ul-Ummah"'' oo ka dhacay [[Mira Road]], kaas oo uu Zangipuri sidoo kale ka qaybgalay. Halkaas ayuu dadkii isugu yimid kula hadlay doorka shakhsiyaadka ee xoojinta nidaamka qoyska.<ref name="seerat2025">{{cite news|date=1 December 2025|title=سیرت النبیؐ و اتحاد امت کانفرنس میں قرآن مجید کے راستے پر چلنے کی تلقین|language=Urdu|trans-title=Call to follow the path of the Holy Quran at the Seerat-un-Nabi and Ittehad-ul-Ummah conference|work=Inquilab|url=https://www.inquilab.com/news/articles/exhortation-to-follow-the-path-of-the-holy-quran-at-the-seerat-ul-nabi-pbuh-and-ittehad-ul-ummah-conference-87709}}</ref> Warbixin ay ''Hamari Aawaz'' daabacday sannadkii 2021 ayaa ka hadashay hadallo uu Zangipuri ka jeediyay kulan ku saabsanaa [[Dib-u-habaynta bulshada|dib-u-habaynta bulshada]] ee [[Mira Road]].<ref name="hamariaawaz">{{cite news|date=16 March 2021|title=کرونا وائرس سے زیادہ خطرناک جہیز کا وائرس ہے: قاضی مطیع الرحمٰن قاسمی|language=Urdu|work=Hamari Aawaz|url=https://news.hamariaawaz.com/7967/}}</ref> Zangipuri waxa uu ka qaybgalay [[Muxaadaro diini ah|muxaadarooyin diini ah]], [[Kulan|kulammo bulsho]] iyo [[Banaanbax|banaanbaxyo dadweyne]] oo kala duwan. Duubitaanno kayd ah ayaa muujinaya isaga oo ka qaybgalaya munaasabado la xiriira [[Qabuuraha Al-Baqi|Jannatul Baqi]], [[Maalinta Qudus|Qudus]], murankii [[2022 Karnataka hijab row|xijaabka]] iyo murankii [[Syed Wasim Rizvi|Waseem Rizvi]].<ref name="baqi2017">{{cite web|title=2017 Maulana Hasan Imam Rizvi's Protest on Jannatul Baqi|url=https://archive.org/details/2017-maulana-hasan-imam-rizvis-protest-on-jannatul-baqi|website=Internet Archive}}</ref><ref name="quds2023">{{cite web|title=2023 Yaum E Quds Protest, Mira Road, Maulana Hasan Imam Rizvi|url=https://archive.org/details/2023-yaum-e-quds-protest-mira-road-maulana-hasan-imam-rizvi|website=Internet Archive}}</ref><ref name="waseemarchive">{{cite web|title=2021 Darul Qaza Mira Road With Maulana Hasan Imam Rizvi|url=https://archive.org/details/2021-darul-qaza-mira-road-with-maulana-hasan-imam-rizvi-protest-on-waseem-rizvi-la|website=Internet Archive}}</ref> Hawlaha uu ka qabto bulshada ayaa sidoo kale waxaa tebiyay warbaahin ay ka mid yihiin ''Hawzah News'' iyo adeegyada ''IQNA ee Isfahan iyo Khorasan''.<ref>{{Cite news |last=Isfahan |first=IQNA |title=IQNA Isfahan- Shia Olama wa Khuteba Board, Mira Road |url=https://isfahan.iqna.ir/ur/news/3512933/ممبئی-میں-شیعہ-علماء-اسمبلی-ہندوستان-کا-دو-روزہ-اہم-اجلاس-منعقد}}</ref><ref>{{Cite news |last=Khorasan |first=IQNA |title=IQNA Khorasan- Shia Olama wa Khuteba Council, Mira Road |url=https://khorasan.iqna.ir/ur/news/3512933/ممبئی-میں-شیعہ-علماء-اسمبلی-ہندوستان-کا-دو-روزہ-اہم-اجلاس-منعقد}}</ref><ref>{{Cite web |date=2022-10-21 |title=ممبئی میں شیعہ علماء اسمبلی ہندوستان کا دو روزہ اجلاس؛ قومی مسائل کو باہمی اتفاق سے حل کرنے پر زور |url=https://ur.hawzahnews.com/news/384946/%D9%85%D9%85%D8%A8%D8%A6%DB%8C-%D9%85%DB%8C%DA%BA-%D8%B4%DB%8C%D8%B9%DB%81-%D8%B9%D9%84%D9%85%D8%A7%D8%A1-%D8%A7%D8%B3%D9%85%D8%A8%D9%84%DB%8C-%DB%81%D9%86%D8%AF%D9%88%D8%B3%D8%AA%D8%A7%D9%86-%DA%A9%D8%A7-%D8%AF%D9%88-%D8%B1%D9%88%D8%B2%DB%81-%D8%A7%D8%AC%D9%84%D8%A7%D8%B3-%D9%82%D9%88%D9%85%DB%8C-%D9%85%D8%B3%D8%A7%D8%A6%D9%84 |access-date=2026-10-02 |website=حوزہ نیوز ایجنسی |publisher=حوزہ نیوز ایجنسی |language=ur}}</ref> Sannadkii 2021, Zangipuri waxa uu si fagaare ah uga jawaabay murankii ka dhashay qorshayaashii [[Syed Wasim Rizvi|Waseem Rizvi]] ee la xiriiray [[Quraanka]], sida uu qoray ''[[The Inquilab]]''.<ref name="inquilab2021" /> Hawzah News ayaa sidoo kale sheegtay in ''"Maulana Hasan Imam iyo culimo kale ay soo saareen bayaan muuqaal ah oo ay Waseem Rizvi iyo saaxiibbadiis ugu tilmaameen [[Diinta ka bixid|dad diinta ka baxay]], isla markaana ay ku baaqeen in bulshada laga go'doomiyo"''.<ref>{{Cite web |date=2021-04-26 |title=ہندوستان کے مختلف علاقوں کے علماء اور انجمنوں نے وسیم مرتد اور اس کے ساتھیوں کے سوشل بائیکاٹ کا اعلان کرتے ہوئے انہیں اسلام سے خارج قرار دیا |url=https://ur.hawzahnews.com/news/367998/%DB%81%D9%86%D8%AF%D9%88%D8%B3%D8%AA%D8%A7%D9%86-%DA%A9%DB%92-%D9%85%D8%AE%D8%AA%D9%84%D9%81-%D8%B9%D9%84%D8%A7%D9%82%D9%88%DA%BA-%DA%A9%DB%92-%D8%B9%D9%84%D9%85%D8%A7%D8%A1-%D8%A7%D9%88%D8%B1 |access-date=2026-10-02 |website=حوزہ نیوز ایجنسی |publisher=حوزہ نیوز ایجنسی |language=ur}}</ref> Zangipuri waxa kale oo uu dhaliilay Waseem, isaga oo yiri, ''“Kuwani waa aayado ka tirsan Quraanka, mana aha dukumentiyo ay leedahay Guddiga Awqaafta.”''<ref>{{Cite news|last=Times|first=Mibha|title=Protestors seek Waseems arrest for petition against removal of Quranic verses|url=https://mibhatimes.com/social/protestors-seek-waseems-arrest-for-petition-against-removal-of-quranic-verses/|url-status=live}}</ref> Warbixin ay ''[[The Inquilab]]'' daabacday bishii Maarso 2022 oo ku saabsanayd kulan la xiriiray [[xijaabka]] ayaa sidoo kale Zangipuri ku dartay culimadii diinta ee ka qaybgalay kulankaas.<ref name="hijabinq">{{cite news|date=19 March 2022|title=اگر لڑکیاں حجاب پہنیں گی تو اسکول اور کالج انتظامیہ کو اجازت دینے پر مجبور ہونا پڑے گا|language=Urdu|trans-title=If girls wear hijab, school and college administrations will be forced to give permission|work=Inquilab|url=https://www.inquilab.com/news/articles/if-the-girls-wear-hijab-the-school-and-college-administration-will-be-forced-to-give-permission-34717}}</ref> Sannadkii 2017, Zangipuri waxa lala xiriiriyay banaanbax ka dhacay Mira Road oo looga soo horjeeday hadallo uu jeediyay wariye [[Rohit Sardana]]. Muuqaallo kayd ah ayaa muujinaya isaga oo hoggaaminaya [[banaanbax]] isla markaana xubno ka tirsan bulshada Shiicada u raacaya Saldhigga Booliska Naya Nagar.<ref name="sardanatv">{{cite web|title=Shia Crowd Lead By Maulana Hasan Imam Rizvi Filed FIR In Mira Road Police Station Against Rohit Sardana On 2017|url=https://archive.org/details/shia-crowd-lead-by-maulana-hasan-imam-rizvi-filed-fir-in-mira-road-police-statio|website=Internet Archive}}</ref><ref name="sardanarally">{{cite web|title=2017, Rohit Sardana Protest Rally, Maulana Hasan Imam Rizvi|url=https://archive.org/details/2017-rohit-sardana-protest-rally-maulana-hasan-imam-rizvi|website=Internet Archive}}</ref> Warbixin dambe oo ay daabacday ''Veritas International Express'' ayaa ku tilmaantay wadaad Shiico oo sare, waxayna ugu yeertay "Hoggaamiyaha Shiicada ee Mira Road". Warbixintu waxay sheegtay in uu xubno ka tirsan bulshada Shiicada u hoggaamiyay [[Saldhigga booliska|Saldhigga Booliska]] Naya Nagar, taas oo la xiriirtay cabasho laga gudbiyay [[Rohit Sardana|Sardana]].<ref name="veritassardana">{{cite news|date=2 September 2026|title=Senior Shia Cleric and Chief of Shia Population of Mira Road Maulana Syed Hasan Imam Zangipuri files an FIR against Journalist Rohit Sardana|work=Veritas International Express|url=https://veritasinternationalexpress.mojonetwork.in/national-news/mira-road-shia-cleric-fir-against-journalist-rohit-sardana}}</ref> Warbixin uu ''[[The Times of India]]'' daabacay xilligaas ayaa si madax-bannaan u xaqiijisay in cabasho boolis laga gudbiyay Mira Road oo ku saabsanayd hadallada Sardana.<ref name="toiSardana">{{cite news|date=23 November 2017|title=Muslim groups see red over journo's tweet|work=The Times of India|url=https://timesofindia.indiatimes.com/city/mumbai/muslim-groups-see-red-over-journos-tweet/articleshow/61759448.cms}}</ref><ref name="interview2015">{{cite web|date=2015|title=Interview Of Maulana Hasan Imam Rizvi, 2015, Zainabia Channel|url=https://archive.org/details/interview-of-maulana-hasan-imam-rizvi-2015-zainabia-channel|website=Internet Archive}}</ref> == Sidoo kale eeg == [[Islaamka Shiicada]] [[Ayatollah]] == Tixraacyo == {{reflist}} [[Category:Ayatollah]] [[Category:1974 births]] [[Category:Living people]] [[Category:Shia Islam]] omeamd9z5yax7d4jrlt7m97veddkyet MediaWiki:Print.css 8 53975 311234 2026-10-29T08:54:44Z Isma4l 41797 Abuuray 311234 css text/css /* Do not print */ .ns-0 .metadata, /* items in mainspace marked as metadata */ .editlink, /* section edit links */ .mw-collapsible-toggle, /* Show/hide toggles for collapsible items. */ #mw-revision-nav, /* revision navigation on a permalink [[phab:T173057]] */ /* Add formatting to make sure that "external references" from templates like [[Template:Ref]] do not get URL expansion, not even when printed. The anchor itself has class "external autonumber" and the url expansion is inserted when printing using the ":after" pseudo-element of CSS. See mediawiki.skinning/content.tables-print.less */ .nourlexpansion a.external.text::after, .nourlexpansion a.external.autonumber::after { display: none !important; } /* Uncollapse collapsible things * See also [[phab:T152330]] */ .mw-parser-output .mw-collapsed, .mw-parser-output .mw-collapsed .mw-collapsible-content, .mw-parser-output .mw-collapsed > li, .mw-parser-output .mw-collapsed tr { /* fallback for browser versions that don't yet support revert * on the support graph that's only grade C/X, so review this at a later date */ display: initial !important; display: revert !important; /* revert works better for tables */ } /* On websites with siteSub visible, the margin on the firstHeading is not needed. */ #firstHeading { margin: 0; } /* We don't want very long URLs (that are added to the content in print) to widen the canvas */ .mw-parser-output a.external.text::after, .mw-parser-output a.external.autonumber::after { word-wrap: break-word; } dvj7nfm9pat4st2uaqqlpefcq6989r7 Template:Editnotices/Page/MediaWiki:Print.css 10 53976 311235 2026-10-29T08:56:16Z Isma4l 41797 Isma4l abuuray bogga [[Template:Editnotices/Page/MediaWiki:Print.css]] isagoo oo leh nooc nuxur aan caadi ahayn "wikitext" 311235 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 311236 311235 2026-10-29T08:56:31Z Isma4l 41797 /* */ 311236 wikitext text/x-wiki {{skinfile|the printing of all pages}} r39whabpq3o3czjmqw0c9pp1jhnt6lc Template:Editnotices/Page/MediaWiki:Vector.css 10 53977 311237 2026-10-29T08:57:59Z Isma4l 41797 Isma4l abuuray bogga [[Template:Editnotices/Page/MediaWiki:Vector.css]] isagoo oo leh nooc nuxur aan caadi ahayn "wikitext" 311237 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 311238 311237 2026-10-29T08:58:09Z Isma4l 41797 /* */ 311238 wikitext text/x-wiki {{skinfile|the vector skin ''only''}} 83j5xmfmi768d2kfei39s7yvf6mel0z MediaWiki:Filepage.css 8 53978 311239 2026-10-29T09:01:56Z Isma4l 41797 Abuuray 311239 css text/css /* CSS placed here is included on the file description page, also included on foreign client wikis */ /* Eventually this should move into TemplateStyles on Commons */ /* Cutoff of 500px to test the waters */ @media screen and (max-width : 500px) { .licensetpl { display:block; box-sizing: border-box; overflow-wrap: break-word; } .licensetpl > * { display: block; width: 100%; box-sizing: border-box; padding: 0 0.5em !important; } .licensetpl > * > tr { display: flex; flex: 1 1; flex-direction: column; flex-wrap: nowrap; width: 100%; box-sizing: border-box; } .licensetpl > * > tr > td, .licensetpl > * > tr > th { flex: 1 1; box-sizing: border-box; width: 100% !important; padding: 0 !important; margin: 0 !important; margin-bottom: 0.5em !important; } .licensetpl > * > tr > td:empty, .licensetpl > * > tr > * > img { display:none; } .fileinfotpl-type-information { display:block; box-sizing: border-box; border: 1px solid #a2a9b1; padding: 0 !important; overflow-wrap: break-word; } .fileinfotpl-type-information > * { display: block; width: 100%; box-sizing: border-box; padding: 0 !important; } .fileinfotpl-type-information > * > tr { display: flex; flex: 1 1; flex-direction: row; flex-wrap: wrap; width: 100%; box-sizing: border-box; } .fileinfotpl-type-information > * > tr > td { flex: 1 1; box-sizing: border-box; width: 100% !important; padding: 5px !important; margin: 0 !important; border-bottom: 1px solid #a2a9b1; text-align: left; } .fileinfotpl-type-information > * > tr > td:first-child { flex: 0 0 20vw; border-right: 1px solid #a2a9b1; } } /* Lots of crappy tables on Commons without classes etc */ table { box-sizing: border-box !important; } /* Workaround for [[:phab:T270741]] */ .filehistory td:last-child { word-break: break-word; min-width: 10em; } t2cm5mnee4mmuu0k9eiu9gg38hykqw2 MediaWiki:Modern.css 8 53979 311240 2026-10-29T09:14:07Z Isma4l 41797 Abuuray 311240 css text/css #firstHeading .mw-editsection a { color: white; } body.page-Bogga_Hore #t-cite, body.page-Bogga_Hore #lastmod, body.page-Bogga_Hore #siteSub { display: none !important; } p.error { font-weight: bold; } /* some headroom for #coordinates to go in without #siteSub */ #mw_contentholder { padding-top: .4em; } /* position coordinates */ #coordinates { position: absolute; z-index: 1; border: none; background: none; right: 0; top: 0.1em; float: right; margin: 0; padding: 0; padding-right: 1.17em; line-height: 1.5em; text-align: right; text-indent: 0; font-size: 85%; text-transform: none; white-space: nowrap; } /* important to keep the text predictably positioned */ #coordinates img { vertical-align: top; } .mw-topboxes { margin-top: -0.4em; } .mw-indicators { position: relative; } #mw-indicator-coordinates #coordinates { top: 67px; } /* Styling for tags in changes pages */ .mw-tag-markers { font-style: italic; font-size: 90%; } bw9moijuwya5hri0kwxnim4uw0r1wsu Template:Editnotices/Page/MediaWiki:Modern.css 10 53980 311241 2026-10-29T09:15:15Z Isma4l 41797 Isma4l abuuray bogga [[Template:Editnotices/Page/MediaWiki:Modern.css]] isagoo oo leh nooc nuxur aan caadi ahayn "wikitext" 311241 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 311242 311241 2026-10-29T09:15:26Z Isma4l 41797 /* */ 311242 wikitext text/x-wiki {{skinfile|the 'Modern' skin}} mcmmqp930gwyl7rud7989nvczhjsg1n MediaWiki:Cologneblue.css 8 53981 311243 2026-10-29T09:17:47Z Isma4l 41797 Abuuray 311243 css text/css /* Styling for tags in changes pages */ .mw-tag-markers { font-style: italic; font-size: 90%; } c9axsav4u4v4s7rjtgmmbj3l0t1q22p MediaWiki:Group-sysop.css 8 53982 311244 2026-10-29T09:26:30Z Isma4l 41797 Abuuray 311244 css text/css /* Protected pages have text area in light red, to prevent accidental editing by admins who didn't notice the header */ .mw-textarea-protected, .mw-textarea-protected + div .ace_content, .mw-textarea-protected + .CodeMirror, .mw-textarea-protected + .cm-editor, .ns-8 textarea, .ns-8 .ace_content, .ns-8 .CodeMirror, .ns-8 .cm-editor { background-color: hsl(0, 100%, 94%); } @media screen { html.skin-theme-clientpref-night .mw-textarea-protected, html.skin-theme-clientpref-night .mw-textarea-protected + div .ace_content, html.skin-theme-clientpref-night .mw-textarea-protected + .CodeMirror, html.skin-theme-clientpref-night .mw-textarea-protected + .cm-editor, html.skin-theme-clientpref-night .ns-8 textarea, html.skin-theme-clientpref-night .ns-8 .ace_content, html.skin-theme-clientpref-night .ns-8 .CodeMirror, html.skin-theme-clientpref-night .ns-8 .cm-editor { background-color: hsl(0, 100%, 10%); } } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os .mw-textarea-protected, html.skin-theme-clientpref-os .mw-textarea-protected + div .ace_content, html.skin-theme-clientpref-os .mw-textarea-protected + .CodeMirror, html.skin-theme-clientpref-os .mw-textarea-protected + .cm-editor, html.skin-theme-clientpref-os .ns-8 textarea, html.skin-theme-clientpref-os .ns-8 .ace_content, html.skin-theme-clientpref-os .ns-8 .CodeMirror, html.skin-theme-clientpref-os .ns-8 .cm-editor { background-color: hsl(0, 100%, 10%); } } /* The "return to Main page" link on [[Special:MovePage]] after deleting the target page makes no sense and is in the way. */ .page-Special_MovePage #mw-returnto { display: none; } /* Show hidden items that have class="sysop-show". */ div.sysop-show, p.sysop-show { display: block !important; } span.sysop-show, small.sysop-show { display: inline !important; } table.sysop-show { display: table !important; } li.sysop-show { display: list-item !important; } /* Avoid accidental delete's and move's */ .page-Bogga_Hore #ca-delete, .page-Bogga_Hore #ca-move { display: none !important; } sg1nchv15gp5iibd6d1skshkyqpakux Template:Editnotices/Page/MediaWiki:Group-sysop.css 10 53983 311245 2026-10-29T09:27:43Z Isma4l 41797 Isma4l abuuray bogga [[Template:Editnotices/Page/MediaWiki:Group-sysop.css]] isagoo oo leh nooc nuxur aan caadi ahayn "wikitext" 311245 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 311246 311245 2026-10-29T09:29:11Z Isma4l 41797 /* */ 311246 wikitext text/x-wiki {{skinfile|qaababka la arki karo oo keliya [[Wikipedia:Maamulka|maamulayaasha]]. waxaa si firfircoon looga soo raray [[MediaWiki:Common.js]]}} 8f5ihnj3ezvrqb46kkv3r7dc2oohmsv MediaWiki:Group-checkuser.css 8 53984 311247 2026-10-29T09:30:52Z Isma4l 41797 Abuuray 311247 css text/css /* CSS placed here will affect checkuser only */ /* Show hidden items that have class="checkuser-show". */ div.checkuser-show, p.checkuser-show { display: block !important; } span.checkuser-show, small.checkuser-show { display: inline !important; } table.checkuser-show { display: table !important; } li.checkuser-show { display: list-item !important; } c3jgflmpysewrvy0uewm7vcrd4475z9 311248 311247 2026-10-29T09:31:32Z Isma4l 41797 311248 css text/css /* /* Koodhka CSS ee halkan la dhigo wuxuu saameyn doonaa kaliya isticmaalayaasha CheckUser*/ /* Show hidden items that have class="checkuser-show". */ div.checkuser-show, p.checkuser-show { display: block !important; } span.checkuser-show, small.checkuser-show { display: inline !important; } table.checkuser-show { display: table !important; } li.checkuser-show { display: list-item !important; } jynk3hebwp3oelxwcvzkwf02ldqjc9p MediaWiki:Group-patroller.css 8 53985 311249 2026-10-29T09:33:02Z Isma4l 41797 Abuuray 311249 css text/css /* Show hidden items that have class="patroller-show". */ div.patroller-show, p.patroller-show { display: block !important; } span.patroller-show, small.patroller-show { display: inline !important; } table.patroller-show { display: table !important; } li.patroller-show { display: list-item !important; } .unconfirmed-show { display: none !important; } dxq5rxpi6fvhsjidzy5sbeujegy6aoz MediaWiki:Group-autoconfirmed.css 8 53986 311250 2026-10-29T09:34:07Z Isma4l 41797 Abuuray 311250 css text/css /* Show hidden items that have class="autoconfirmed-show". */ div.autoconfirmed-show, p.autoconfirmed-show { display: block !important; } span.autoconfirmed-show, small.autoconfirmed-show { display: inline !important; } table.autoconfirmed-show { display: table !important; } li.autoconfirmed-show { display: list-item !important; } .unconfirmed-show { display: none !important; } fdie8qno2w2cmw1xdyo10fd0wual6dy MediaWiki:Group-user.css 8 53987 311251 2026-10-29T09:35:21Z Isma4l 41797 Abuuray 311251 css text/css /* CSS-ka halkan la dhigay wuxuu saameyn doonaa oo keliya dadka diiwaangashan */ .anonymous-show { display: none !important; } div.user-show, p.user-show { display: block !important; } span.user-show, small.user-show { display: inline !important; } table.user-show { display: table !important; } li.user-show { display: list-item !important; } /* Increase the height of the image upload box */ #wpUploadDescription { height: 13em; } ofjgkb2wub8c99undb8gix6lhd4x2ca Template:Edit interface-protected 10 53988 311254 2026-10-29T11:28:22Z Isma4l 41797 Abuuray 311254 wikitext text/x-wiki <includeonly>{{#invoke:protected edit request|interface}}</includeonly><noinclude> {{Documentation|Template:Edit protected shared doc}} </noinclude> 6rw8hvv4rhwt5t23dxafn491ea7c5e8 Template:Edit semi-protected 10 53989 311255 2026-10-29T11:30:01Z Isma4l 41797 Abuuray 311255 wikitext text/x-wiki <includeonly>{{#invoke:protected edit request|semi}}</includeonly><noinclude> {{Documentation|Template:Edit protected shared doc}} </noinclude> hq17cjys0p3p4uvcc8fbbziq9gjz29u