// STARTFILE: main.js // ********************************************************************** // ** ** // ** changes to this file affect many users. ** // ** please discuss on the talk page before editing ** // ** ** // ********************************************************************** // ** ** // ** if you do edit this file, be sure that your editor recognizes it ** // ** as utf8, or the weird and wonderful characters in the namespaces ** // ** below will be completely broken. You can check with the show ** // ** changes button before submitting the edit. ** // ** test: مدیا מיוחד Мэдыя ** // ** ** // ********************************************************************** ////////////////////////////////////////////////// // Globals // // Trying to shove as many of these as possible into the pg (popup globals) object function pg(){} // dummy to stop errors window.pg = { re: {}, // regexps ns: {}, // namespaces string: {}, // translatable strings wiki: {}, // local site info misc: {}, // YUCK PHOOEY option: {}, // options, see newOption etc optionDefault: {}, // default option values flag: {}, // misc flags cache: {}, // page and image cache structures: {}, // navlink structures timer: {}, // all sorts of timers (too damn many) counter: {}, // .. and all sorts of counters current: {}, // state info endoflist: null }; window.pop = { // wrap various functions in here init: {}, util: {}, endoflist: null }; function popupsReady() { if (!window.pg) { return false; } if (!pg.flag) { return false; } if (!pg.flag.finishedLoading) { return false; } return true; } /// Local Variables: /// /// mode:c /// /// End: /// // ENDFILE: main.js // STARTFILE: actions.js function setupTooltips(container, remove, force, popData) { log('setupTooltips, container='+container+', remove='+remove); if (!container) { // // the main initial call if (getValueOf('popupOnEditSelection') && window.doSelectionPopup && document && document.editform && document.editform.wpTextbox1) { document.editform.wpTextbox1.onmouseup=doSelectionPopup; } // // article/content is a structure-dependent thing container = defaultPopupsContainer(); } if (!remove && !force && container.ranSetupTooltipsAlready) { return; } container.ranSetupTooltipsAlready = !remove; var anchors; anchors=container.getElementsByTagName('A'); setupTooltipsLoop(anchors, 0, 250, 100, remove, popData); } function defaultPopupsContainer() { if (getValueOf('popupOnlyArticleLinks')) { return document.getElementById('mw_content') || document.getElementById('content') || document.getElementById('article') || document; } return document; } function setupTooltipsLoop(anchors,begin,howmany,sleep, remove, popData) { log(simplePrintf('setupTooltipsLoop(%s,%s,%s,%s,%s)', arguments)); var finish=begin+howmany; var loopend = min(finish, anchors.length); var j=loopend - begin; log ('setupTooltips: anchors.length=' + anchors.length + ', begin=' + begin + ', howmany=' + howmany + ', loopend=' + loopend + ', remove=' + remove); var doTooltip= remove ? removeTooltip : addTooltip; // try a faster (?) loop construct if (j > 0) { do { var a=anchors[loopend - j]; if (typeof a==='undefined' || !a || !a.href) { log('got null anchor at index ' + loopend - j); continue; } doTooltip(a, popData); } while (--j); } if (finish < anchors.length) { setTimeout(function() { setupTooltipsLoop(anchors,finish,howmany,sleep,remove,popData);}, sleep); } else { if ( !remove && ! getValueOf('popupTocLinks')) { rmTocTooltips(); } pg.flag.finishedLoading=true; } } // eliminate popups from the TOC // This also kills any onclick stuff that used to be going on in the toc function rmTocTooltips() { var toc=document.getElementById('toc'); if (toc) { var tocLinks=toc.getElementsByTagName('A'); var tocLen = tocLinks.length; for (j=0; j ' + popupMaxWidth + ' ? "' +popupMaxWidth + 'px": "auto"'); } } catch (errors) { errlog( "Running on IE8 are we not?: " + errors ); } }; np.addHook(setMaxWidth, 'unhide', 'before'); } // if (window.addPopupShortcuts && window.rmPopupShortcuts) { np.addHook(addPopupShortcuts, 'unhide', 'after'); np.addHook(rmPopupShortcuts, 'hide', 'before'); } // } function mouseOverWikiLink(evt) { if (!window.popupsReady || !window.popupsReady()) { return; } if (!evt && window.event) {evt=window.event;} return mouseOverWikiLink2(this, evt); } function footnoteTarget(a) { var aTitle=Title.fromAnchor(a); // We want ".3A" rather than "%3A" or "?" here, so use the anchor property directly var anch = aTitle.anchor; if ( ! /^(cite_note-|_note-|endnote)/.test(anch) ) { return false; } var lTitle=Title.fromURL(location.href); if ( lTitle.toString(true) !== aTitle.toString(true) ) { return false; } var el=document.getElementById(anch); while ( el && typeof el.nodeName === 'string') { var nt = el.nodeName.toLowerCase(); if ( nt === 'li' ) { return el; } else if ( nt === 'body' ) { return false; } else if ( el.parentNode ) { el=el.parentNode; } else { return false; } } return false; } function footnotePreview(x, navpop) { setPopupHTML('
' + x.innerHTML, 'popupPreview', navpop.idNumber, getValueOf('popupSubpopups') ? function() { setupTooltips(document.getElementById('popupPreview' + navpop.idNumber)); } : null); } // var modid=0; // if(!window.opera) { window.opera={postError: console.log}; } function modifierKeyHandler(a) { return function(evt) { // opera.postError('modifierKeyHandler called' + (++modid)); // opera.postError(''+evt + modid); // for (var i in evt) { // opera.postError('' + modid + ' ' + i + ' ' + evt[i]); // } // opera.postError(''+evt.ctrlKey + modid); var mod=getValueOf('popupModifier'); if (!mod) { return true; } if (!evt && window.event) {evt=window.event;} // opera.postError('And now....'+modid); // opera.postError(''+evt+modid); // opera.postError(''+evt.ctrlKey+modid); var modPressed = modifierPressed(evt); var action = getValueOf('popupModifierAction'); // FIXME: probable bug - modifierPressed should be modPressed below? if ( action === 'disable' && modifierPressed ) { return true; } if ( action === 'enable' && !modifierPressed ) { return true; } mouseOverWikiLink2(a, evt); }; } function modifierPressed(evt) { var mod=getValueOf('popupModifier'); if (!mod) { return false; } if (!evt && window.event) {evt=window.event;} // opera.postError('And now....'+modid); // opera.postError(''+evt+modid); // opera.postError(''+evt.ctrlKey+modid); return ( evt && mod && evt[mod.toLowerCase() + 'Key'] ); } function dealWithModifier(a,evt) { if (!getValueOf('popupModifier')) { return false; } var action = getValueOf('popupModifierAction'); if ( action == 'enable' && !modifierPressed(evt) || action == 'disable' && modifierPressed(evt) ) { // if the modifier is needed and not pressed, listen for it until // we mouseout of this link. restoreTitle(a); var addHandler='addEventListener'; var rmHandler='removeEventListener'; var on=''; if (!document.addEventListener) { addHandler='attachEvent'; rmHandler='detachEvent'; on='on'; } if (!document[addHandler]) { // forget it return; } a.modifierKeyHandler=modifierKeyHandler(a); switch (action) { case 'enable': document[addHandler](on+'keydown', a.modifierKeyHandler, false); a[addHandler](on+'mouseout', function() { document[rmHandler](on+'keydown', a.modifierKeyHandler, false); }, true); break; case 'disable': document[addHandler](on+'keyup', a.modifierKeyHandler, false); } return true; } return false; } function mouseOverWikiLink2(a, evt) { if (dealWithModifier(a,evt)) { return; } if ( getValueOf('removeTitles') ) { removeTitle(a); } if ( a==pg.current.link && a.navpopup && a.navpopup.isVisible() ) { return; } pg.current.link=a; if (getValueOf('simplePopups') && pg.option.popupStructure===null) { // reset *default value* of popupStructure setDefault('popupStructure', 'original'); } var article=(new Title()).fromAnchor(a); // set global variable (ugh) to hold article (wikipage) pg.current.article = article; if (!a.navpopup) { // FIXME: this doesn't behave well if you mouse out of a popup // directly into a link with the same href if (pg.current.linksHash[a.href] && false) { a.navpopup = pg.current.linksHash[a.href]; } else { a.navpopup=newNavpopup(a, article); pg.current.linksHash[a.href] = a.navpopup; pg.current.links.push(a); } } if (a.navpopup.pending===null || a.navpopup.pending!==0) { // either fresh popups or those with unfinshed business are redone from scratch simplePopupContent(a, article); } a.navpopup.showSoonIfStable(a.navpopup.delay); getValueOf('popupInitialWidth'); clearInterval(pg.timer.checkPopupPosition); pg.timer.checkPopupPosition=setInterval(checkPopupPosition, 600); if(getValueOf('simplePopups')) { if (getValueOf('popupPreviewButton') && !a.simpleNoMore) { var d=document.createElement('div'); d.className='popupPreviewButtonDiv'; var s=document.createElement('span'); d.appendChild(s); s.className='popupPreviewButton'; s['on' + getValueOf('popupPreviewButtonEvent')] = function() { a.simpleNoMore=true; nonsimplePopupContent(a,article); }; s.innerHTML=popupString('show preview'); setPopupHTML(d, 'popupPreview', a.navpopup.idNumber); } return; } if (a.navpopup.pending!==0 ) { nonsimplePopupContent(a, article); } } // simplePopupContent: the content that is shown even when simplePopups is true function simplePopupContent(a, article) { /* FIXME hack */ a.navpopup.hasPopupMenu=false; a.navpopup.setInnerHTML(popupHTML(a)); fillEmptySpans({navpopup:a.navpopup}); if (getValueOf('popupDraggable')) { var dragHandle = getValueOf('popupDragHandle') || null; if (dragHandle && dragHandle != 'all') { dragHandle += a.navpopup.idNumber; } setTimeout(function(){a.navpopup.makeDraggable(dragHandle);}, 150); } // if (getValueOf('popupRedlinkRemoval') && a.className=='new') { setPopupHTML('
'+popupRedlinkHTML(article), 'popupRedlink', a.navpopup.idNumber); } //
} function debugData(navpopup) { if(getValueOf('popupDebugging') && navpopup.idNumber) { setPopupHTML('idNumber='+navpopup.idNumber + ', pending=' + navpopup.pending, 'popupError', navpopup.idNumber); } } function newNavpopup(a, article) { var navpopup = new Navpopup(); navpopup.fuzz=5; navpopup.delay=getValueOf('popupDelay')*1000; // increment global counter now navpopup.idNumber = ++pg.idNumber; navpopup.parentAnchor = a; navpopup.parentPopup = (a.popData && a.popData.owner); navpopup.article = article; registerHooks(navpopup); return navpopup; } function nonsimplePopupContent(a, article) { var diff=null, history=null; var params=parseParams(a.href); var oldid=(typeof params.oldid=='undefined' ? null : params.oldid); // if(getValueOf('popupPreviewDiffs') && window.loadDiff) { diff=params.diff; } if(getValueOf('popupPreviewHistory')) { history=(params.action=='history'); } // a.navpopup.pending=0; var x; if (x=footnoteTarget(a)) { footnotePreview(x, a.navpopup); // } else if ( diff || diff === 0 ) { loadDiff(article, oldid, diff, a.navpopup); } else if ( history ) { loadAPIPreview('history', article, a.navpopup); } else if ( pg.re.contribs.test(a.href) ) { loadAPIPreview('contribs', article, a.navpopup); } else if ( pg.re.backlinks.test(a.href) ) { loadAPIPreview('backlinks', article, a.navpopup); } else if ( // FIXME should be able to get all preview combinations with options article.namespaceId()==pg.nsImageId && ( getValueOf('imagePopupsForImages') || ! anchorContainsImage(a) ) ) { loadAPIPreview('imagepagepreview', article, a.navpopup); loadImage(article, a.navpopup); // } else { if (article.namespaceId() == pg.nsCategoryId && getValueOf('popupCategoryMembers')) { loadAPIPreview('category', article, a.navpopup); } else if ((article.namespaceId() == pg.nsUserId || article.namespaceId() == pg.nsUsertalkId) && getValueOf('popupUserInfo')) { loadAPIPreview('userinfo', article, a.navpopup); } startArticlePreview(article, oldid, a.navpopup); } } function pendingNavpopTask(navpop) { if (navpop && navpop.pending===null) { navpop.pending=0; } ++navpop.pending; debugData(navpop); } function completedNavpopTask(navpop) { if (navpop && navpop.pending) { --navpop.pending; } debugData(navpop); } function startArticlePreview(article, oldid, navpop) { navpop.redir=0; loadPreview(article, oldid, navpop); } function loadPreview(article, oldid, navpop) { pendingNavpopTask(navpop); if (!navpop.redir) { navpop.originalArticle=article; } if (!navpop.visible && getValueOf('popupLazyDownloads')) { var id=(navpop.redir) ? 'DOWNLOAD_PREVIEW_REDIR_HOOK' : 'DOWNLOAD_PREVIEW_HOOK'; navpop.addHook(function() { getWiki(article, insertPreview, oldid, navpop); return true; }, 'unhide', 'before', id); } else { getWiki(article, insertPreview, oldid, navpop); } } function loadPreviewFromRedir(redirMatch, navpop) { // redirMatch is a regex match var target = new Title().fromWikiText(redirMatch[2]); // overwrite (or add) anchor from original target // mediawiki does overwrite; eg [[User:Lupin/foo3#Done]] if ( navpop.article.anchor ) { target.anchor = navpop.article.anchor; } var trailingRubbish=redirMatch[4]; navpop.redir++; navpop.redirTarget=target; // if (window.redirLink) { var warnRedir = redirLink(target, navpop.article); setPopupHTML(warnRedir, 'popupWarnRedir', navpop.idNumber); } // navpop.article=target; fillEmptySpans({redir: true, redirTarget: target, navpopup:navpop}); return loadPreview(target, null, navpop); } function insertPreview(download) { if (!download.owner) { return; } var redirMatch = pg.re.redirect.exec(download.data); if (download.owner.redir===0 && redirMatch) { completedNavpopTask(download.owner); loadPreviewFromRedir(redirMatch, download.owner); return; } if (download.owner.visible || !getValueOf('popupLazyPreviews')) { insertPreviewNow(download); } else { var id=(download.owner.redir) ? 'PREVIEW_REDIR_HOOK' : 'PREVIEW_HOOK'; download.owner.addHook( function(){insertPreviewNow(download); return true;}, 'unhide', 'after', id ); } } function insertPreviewNow(download) { if (!download.owner) { return; } var wikiText=download.data; var navpop=download.owner; completedNavpopTask(navpop); var art=navpop.redirTarget || navpop.originalArticle; // makeFixDabs(wikiText, navpop); if (getValueOf('popupSummaryData') && window.getPageInfo) { var info=getPageInfo(wikiText, download); setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber); } var imagePage=''; if (art.namespaceId()==pg.nsImageId) { imagePage=art.toString(); } else { imagePage=getValidImageFromWikiText(wikiText); } if(imagePage) { loadImage(Title.fromWikiText(imagePage), navpop); } // if (getValueOf('popupPreviews')) { insertArticlePreview(download, art, navpop); } } function insertArticlePreview(download, art, navpop) { if (download && typeof download.data == typeof ''){ if (art.namespaceId()==pg.nsTemplateId && getValueOf('popupPreviewRawTemplates')) { // FIXME compare/consolidate with diff escaping code for wikitext var h='
' + download.data.entify().split('\\n').join('
\\n') + '
'; setPopupHTML(h, 'popupPreview', navpop.idNumber); } else { var p=prepPreviewmaker(download.data, art, navpop); p.showPreview(); } } } function prepPreviewmaker(data, article, navpop) { // deal with tricksy anchors var d=anchorize(data, article.anchorString()); var urlBase=joinPath([pg.wiki.articlebase, article.urlString()]); var p=new Previewmaker(d, urlBase, navpop); return p; } // Try to imitate the way mediawiki generates HTML anchors from section titles function anchorize(d, anch) { if (!anch) { return d; } var anchRe=RegExp('(?:=+\\s*' + literalizeRegex(anch).replace(/[_ ]/g, '[_ ]') + '\\s*=+|\\{\\{\\s*'+getValueOf('popupAnchorRegexp')+'\\s*(?:\\|[^|}]*)*?\\s*'+literalizeRegex(anch)+'\\s*(?:\\|[^}]*)?\}\})'); var match=d.match(anchRe); if(match && match.length > 0 && match[0]) { return d.substring(d.indexOf(match[0])); } // now try to deal with == foo [[bar|baz]] boom == -> #foo_baz_boom var lines=d.split('\n'); for (var i=0; i ************************************************* dom-drag.js 09.25.2001 www.youngpup.net ************************************************** 10.28.2001 - fixed minor bug where events sometimes fired off the handle, not the root. ************************************************* Pared down, some hooks added by [[User:Lupin]] Copyright Aaron Boodman. Saying stupid things daily since March 2001. */ /** Creates a new Drag object. This is used to make various DOM elements draggable. @constructor */ function Drag () { /** Condition to determine whether or not to drag. This function should take one parameter, an Event. To disable this, set it to null. @type Function */ this.startCondition = null; /** Hook to be run when the drag finishes. This is passed the final coordinates of the dragged object (two integers, x and y). To disables this, set it to null. @type Function */ this.endHook = null; } /** Gets an event in a cross-browser manner. @param {Event} e @private */ Drag.prototype.fixE = function(e) { if (typeof e == 'undefined') { e = window.event; } if (typeof e.layerX == 'undefined') { e.layerX = e.offsetX; } if (typeof e.layerY == 'undefined') { e.layerY = e.offsetY; } return e; }; /** Initialises the Drag instance by telling it which object you want to be draggable, and what you want to drag it by. @param {DOMElement} o The "handle" by which oRoot is dragged. @param {DOMElement} oRoot The object which moves when o is dragged, or o if omitted. */ Drag.prototype.init = function(o, oRoot) { var dragObj = this; this.obj = o; o.onmousedown = function(e) { dragObj.start.apply( dragObj, [e]); }; o.dragging = false; o.popups_draggable = true; o.hmode = true; o.vmode = true; o.root = oRoot && oRoot !== null ? oRoot : o ; if (isNaN(parseInt(o.root.style.left, 10))) { o.root.style.left = "0px"; } if (isNaN(parseInt(o.root.style.top, 10))) { o.root.style.top = "0px"; } o.root.onthisStart = function(){}; o.root.onthisEnd = function(){}; o.root.onthis = function(){}; }; /** Starts the drag. @private @param {Event} e */ Drag.prototype.start = function(e) { var o = this.obj; // = this; e = this.fixE(e); if (this.startCondition && !this.startCondition(e)) { return; } var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); o.root.onthisStart(x, y); o.lastMouseX = e.clientX; o.lastMouseY = e.clientY; var dragObj = this; o.onmousemoveDefault = document.onmousemove; o.dragging = true; document.onmousemove = function(e) { dragObj.drag.apply( dragObj, [e] ); }; document.onmouseup = function(e) { dragObj.end.apply( dragObj, [e] ); }; return false; }; /** Does the drag. @param {Event} e @private */ Drag.prototype.drag = function(e) { e = this.fixE(e); var o = this.obj; var ey = e.clientY; var ex = e.clientX; var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10 ); var nx, ny; nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); this.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; this.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; this.obj.lastMouseX = ex; this.obj.lastMouseY = ey; this.obj.root.onthis(nx, ny); return false; }; /** Ends the drag. @private */ Drag.prototype.end = function() { document.onmousemove=this.obj.onmousemoveDefault; document.onmouseup = null; this.obj.dragging = false; if (this.endHook) { this.endHook( parseInt(this.obj.root.style[this.obj.hmode ? "left" : "right"], 10), parseInt(this.obj.root.style[this.obj.vmode ? "top" : "bottom"], 10)); } }; // ENDFILE: domdrag.js // STARTFILE: structures.js // pg.structures.original={}; pg.structures.original.popupLayout=function () { return ['popupError', 'popupImage', 'popupTopLinks', 'popupTitle', 'popupData', 'popupOtherLinks', 'popupRedir', ['popupWarnRedir', 'popupRedirTopLinks', 'popupRedirTitle', 'popupRedirData', 'popupRedirOtherLinks'], 'popupMiscTools', ['popupRedlink'], 'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview', 'popupFixDab']; }; pg.structures.original.popupRedirSpans=function () { return ['popupRedir', 'popupWarnRedir', 'popupRedirTopLinks', 'popupRedirTitle', 'popupRedirData', 'popupRedirOtherLinks']; }; pg.structures.original.popupTitle=function (x) { log ('defaultstructure.popupTitle'); if (!getValueOf('popupNavLinks')) { return navlinkStringToHTML('<>',x.article,x.params); } return ''; }; pg.structures.original.popupTopLinks=function (x) { log ('defaultstructure.popupTopLinks'); if (getValueOf('popupNavLinks')) { return navLinksHTML(x.article, x.hint, x.params); } return ''; }; pg.structures.original.popupImage=function(x) { log ('original.popupImage, x.article='+x.article+', x.navpop.idNumber='+x.navpop.idNumber); return imageHTML(x.article, x.navpop.idNumber); }; pg.structures.original.popupRedirTitle=pg.structures.original.popupTitle; pg.structures.original.popupRedirTopLinks=pg.structures.original.popupTopLinks; function copyStructure(oldStructure, newStructure) { pg.structures[newStructure]={}; for (var prop in pg.structures[oldStructure]) { pg.structures[newStructure][prop]=pg.structures[oldStructure][prop]; } } copyStructure('original', 'nostalgia'); pg.structures.nostalgia.popupTopLinks=function(x) { var str=''; str += '<>'; // user links // contribs - log - count - email - block // count only if applicable; block only if popupAdminLinks str += 'if(user){
<>'; str+='if(wikimedia){*<>}'; str+='if(ipuser){}else{*<>}if(admin){*<>}}'; // editing links // talkpage -> edit|new - history - un|watch - article|edit // other page -> edit - history - un|watch - talk|edit|new var editstr='<>'; var editOldidStr='if(oldid){<>|<>|<>}else{' + editstr + '}'; var historystr='<>'; var watchstr='<>|<>'; str+='
if(talk){' + editOldidStr+'|<>' + '*' + historystr+'*'+watchstr + '*' + '<>|<>' + '}else{' + // not a talk page editOldidStr + '*' + historystr + '*' + watchstr + '*' + '<>|<>|<>' + '}'; // misc links str += '
<>*<>'; str += 'if(admin){
}else{*}<>'; // admin links str += 'if(admin){*<>|<>*' + '<>|<>}'; return navlinkStringToHTML(str, x.article, x.params); }; pg.structures.nostalgia.popupRedirTopLinks=pg.structures.nostalgia.popupTopLinks; /** -- fancy -- **/ copyStructure('original', 'fancy'); pg.structures.fancy.popupTitle=function (x) { return navlinkStringToHTML('<>',x.article,x.params); }; pg.structures.fancy.popupTopLinks=function(x) { var hist='<>|<>if(mainspace_en){|<>}'; var watch='<>|<>'; var move='<>'; return navlinkStringToHTML('if(talk){' + '<>|<>*' + hist + '*' + '<>|<>' + '*' + watch + '*' + move + '}else{<>*' + hist + '*<>|<>|<>' + '*' + watch + '*' + move+'}
', x.article, x.params); }; pg.structures.fancy.popupOtherLinks=function(x) { var admin='<>|<>*<>|<>'; var user='<>if(wikimedia){|<>}'; user+='if(ipuser){|<>}else{*<>}if(admin){*<>}'; var normal='<>*<>'; return navlinkStringToHTML('
if(user){' + user + '*}if(admin){'+admin+'if(user){
}else{*}}' + normal, x.article, x.params); }; pg.structures.fancy.popupRedirTitle=pg.structures.fancy.popupTitle; pg.structures.fancy.popupRedirTopLinks=pg.structures.fancy.popupTopLinks; pg.structures.fancy.popupRedirOtherLinks=pg.structures.fancy.popupOtherLinks; /** -- fancy2 -- **/ // hack for [[User:MacGyverMagic]] copyStructure('fancy', 'fancy2'); pg.structures.fancy2.popupTopLinks=function(x) { // hack out the
at the end and put one at the beginning return '
'+pg.structures.fancy.popupTopLinks(x).replace(RegExp('
$','i'),''); }; pg.structures.fancy2.popupLayout=function () { // move toplinks to after the title return ['popupError', 'popupImage', 'popupTitle', 'popupData', 'popupTopLinks', 'popupOtherLinks', 'popupRedir', ['popupWarnRedir', 'popupRedirTopLinks', 'popupRedirTitle', 'popupRedirData', 'popupRedirOtherLinks'], 'popupMiscTools', ['popupRedlink'], 'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview', 'popupFixDab']; }; /** -- menus -- **/ copyStructure('original', 'menus'); pg.structures.menus.popupLayout=function () { return ['popupError', 'popupImage', 'popupTopLinks', 'popupTitle', 'popupOtherLinks', 'popupRedir', ['popupWarnRedir', 'popupRedirTopLinks', 'popupRedirTitle', 'popupRedirData', 'popupRedirOtherLinks'], 'popupData', 'popupMiscTools', ['popupRedlink'], 'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview', 'popupFixDab']; }; function toggleSticky(uid) { var popDiv=document.getElementById('navpopup_maindiv'+uid); if (!popDiv) { return; } if (!popDiv.navpopup.sticky) { popDiv.navpopup.stick(); } else { popDiv.navpopup.unstick(); popDiv.navpopup.hide(); } } pg.structures.menus.popupTopLinks = function (x, shorter) { // FIXME maybe this stuff should be cached var s=[]; var dropdiv=''; var endspan=''; var hist='<>'; if (!shorter) { hist = '' + hist + '|<>if(mainspace_en){|<>}'; } var lastedit='<>'; var jsHistory='<><>'; var linkshere='<>'; var related='<>'; var search='<>if(wikimedia){|<>}' + '|<>'; var watch='<>|<>'; var protect='<>|' + '<>|<>'; var del='<>|<>|' + '<>'; var move='<>'; var nullPurge='<>|<>'; var viewOptions='<>|<>|<>'; var editRow='if(oldid){' + '<>|<>' + '<>|<>' + '}else{<>}'; var markPatrolled='if(rcid){<>}'; var newTopic='if(talk){<>}'; var protectDelete='if(admin){' + protect + del + '}'; if (getValueOf('popupActionsMenu')) { s.push( '<>*' + dropdiv + menuTitle('actions')); } else { s.push( dropdiv + '<>'); } s.push( ''); s.push( editRow + markPatrolled + newTopic + hist + lastedit ); if (!shorter) { s.push(jsHistory); } s.push( move + linkshere + related); if (!shorter) { s.push(nullPurge + search); } if (!shorter) { s.push(viewOptions); } s.push('
' + watch + protectDelete); s.push('
' + 'if(talk){<><>}' + 'else{<><>' + '<>}
' + enddiv); // user menu starts here var email='<>'; var contribs= 'if(wikimedia){}<>if(wikimedia){}' + 'if(admin){<>}'; s.push('if(user){*' + dropdiv + menuTitle('user')); s.push(''); + s.push('<>|<>'); s.push('<><>' + '<>'); if(!shorter) { s.push( 'if(ipuser){<>}else{' + email + '}' ); } else { s.push( 'if(ipuser){}else{' + email + '}' ); } s.push('
' + contribs + '<>'); s.push('if(wikimedia){<>}'); s.push('if(admin){<>|<>}'); s.push('<>' + getValueOf('popupExtraUserMenu')); s.push('
' + enddiv + '}'); // popups menu starts here if (getValueOf('popupSetupMenu') && !x.navpop.hasPopupMenu /* FIXME: hack */) { x.navpop.hasPopupMenu=true; s.push('*' + dropdiv + menuTitle('popupsMenu') + ''); s.push('<>'); s.push('<>'); s.push('<>'); s.push(''+enddiv); } return navlinkStringToHTML(s.join(''), x.article, x.params); }; function menuTitle(s) { return '' + popupString(s) + ''; } pg.structures.menus.popupRedirTitle=pg.structures.menus.popupTitle; pg.structures.menus.popupRedirTopLinks=pg.structures.menus.popupTopLinks; copyStructure('menus', 'shortmenus'); pg.structures.shortmenus.popupTopLinks=function(x) { return pg.structures.menus.popupTopLinks(x,true); }; pg.structures.shortmenus.popupRedirTopLinks=pg.structures.shortmenus.popupTopLinks; copyStructure('shortmenus', 'dabshortmenus'); pg.structures.dabshortmenus.popupLayout=function () { return ['popupError', 'popupImage', 'popupTopLinks', 'popupTitle', 'popupOtherLinks', 'popupRedir', ['popupWarnRedir', 'popupRedirTopLinks', 'popupRedirTitle', 'popupRedirData', 'popupRedirOtherLinks'], 'popupData', 'popupMiscTools', ['popupRedlink'], 'popupFixDab', 'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview']; }; copyStructure('menus', 'dabmenus'); pg.structures.dabmenus.popupLayout=pg.structures.dabshortmenus.popupLayout; //
pg.structures.lite={}; pg.structures.lite.popupLayout=function () { return ['popupTitle', 'popupPreview' ]; }; pg.structures.lite.popupTitle=function (x) { log (x.article + ': structures.lite.popupTitle'); //return navlinkStringToHTML('<>',x.article,x.params); return '
' + x.article.toString() + '
'; }; // ENDFILE: structures.js // STARTFILE: autoedit.js // function substitute(data,cmdBody) { // alert('sub\nfrom: '+cmdBody.from+'\nto: '+cmdBody.to+'\nflags: '+cmdBody.flags); var fromRe=RegExp(cmdBody.from, cmdBody.flags); return data.replace(fromRe, cmdBody.to); } function execCmds(data, cmdList) { for (var i=0; i'; headings[0].parentNode.insertBefore(div, headings[0]); } } function getRvSummary(template, json) { try { var o=getJsObj(json); var edit = anyChild(o.query.pages).revisions[0]; } catch (badness) {return false;} var timestamp = edit.timestamp.split(/[A-Z]/g).join(' ').replace(/^ *| *$/g, ''); return simplePrintf(template, [edit.revid, timestamp, edit.user]); } // // ENDFILE: autoedit.js // STARTFILE: downloader.js /** @fileoverview {@link Downloader}, a xmlhttprequest wrapper, and helper functions. */ /** Creates a new Downloader @constructor @class The Downloader class. Create a new instance of this class to download stuff. @param {String} url The url to download. This can be omitted and supplied later. */ function Downloader(url) { // Source: http://jibbering.com/2002/4/httprequest.html /** xmlhttprequest object which we're wrapping */ this.http = false; /*@cc_on @*/ /*@if (@_jscript_version >= 5) // JScript gives us Conditional compilation, // we can cope with old IE versions. // and security blocked creation of the objects. try { this.http = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { this.http = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { // this.http = false; } } @end @*/ if (! this.http && typeof XMLHttpRequest!='undefined') { this.http = new XMLHttpRequest(); } /** The url to download @type String */ this.url = url; /** A universally unique ID number @type integer */ this.id=null; /** Modification date, to be culled from the incoming headers @type Date @private */ this.lastModified = null; /** What to do when the download completes successfully @type Function @private */ this.callbackFunction = null; /** What to do on failure @type Function @private */ this.onFailure = null; /** Flag set on abort @type boolean */ this.aborted = false; /** HTTP method. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html for possibilities. @type String */ this.method='GET'; /** Async flag. @type boolean */ this.async=true; } new Downloader(); /** Submits the http request. */ Downloader.prototype.send = function (x) { if (!this.http) { return null; } return this.http.send(x); }; /** Aborts the download, setting the aborted field to true. */ Downloader.prototype.abort = function () { if (!this.http) { return null; } this.aborted=true; return this.http.abort(); }; /** Returns the downloaded data. */ Downloader.prototype.getData = function () {if (!this.http) { return null; } return this.http.responseText;}; /** Prepares the download. */ Downloader.prototype.setTarget = function () { if (!this.http) { return null; } this.http.open(this.method, this.url, this.async); }; /** Gets the state of the download. */ Downloader.prototype.getReadyState=function () {if (!this.http) { return null; } return this.http.readyState;}; pg.misc.downloadsInProgress = { }; /** Starts the download. Note that setTarget {@link Downloader#setTarget} must be run first */ Downloader.prototype.start=function () { if (!this.http) { return; } pg.misc.downloadsInProgress[this.id] = this; this.http.send(null); }; /** Gets the 'Last-Modified' date from the download headers. Should be run after the download completes. Returns null on failure. @return {Date} */ Downloader.prototype.getLastModifiedDate=function () { if(!this.http) { return null; } var lastmod=null; try { lastmod=this.http.getResponseHeader('Last-Modified'); } catch (err) {} if (lastmod) { return new Date(lastmod); } return null; }; /** Sets the callback function. @param {Function} f callback function, called as f(this) on success */ Downloader.prototype.setCallback = function (f) { if(!this.http) { return; } this.http.onreadystatechange = f; }; Downloader.prototype.getStatus = function() { if (!this.http) { return null; } return this.http.status; }; ////////////////////////////////////////////////// // helper functions /** Creates a new {@link Downloader} and prepares it for action. @param {String} url The url to download @param {integer} id The ID of the {@link Downloader} object @param {Function} callback The callback function invoked on success @return {String/Downloader} the {@link Downloader} object created, or 'ohdear' if an unsupported browser */ function newDownload(url, id, callback, onfailure) { var d=new Downloader(url); if (!d.http) { return 'ohdear'; } d.id=id; d.setTarget(); if (!onfailure) { onfailure=2; } var f = function () { if (d.getReadyState() == 4) { delete pg.misc.downloadsInProgress[this.id]; try { if ( d.getStatus() == 200 ) { d.data=d.getData(); d.lastModified=d.getLastModifiedDate(); callback(d); } else if (typeof onfailure == typeof 1) { if (onfailure > 0) { // retry newDownload(url, id, callback, onfailure - 1); } } else if ($.isFunction(onfailure)) { onfailure(d,url,id,callback); } } catch (somerr) { /* ignore it */ } } }; d.setCallback(f); return d; } /** Simulates a download from cached data. The supplied data is put into a {@link Downloader} as if it had downloaded it. @param {String} url The url. @param {integer} id The ID. @param {Function} callback The callback, which is invoked immediately as callback(d), where d is the new {@link Downloader}. @param {String} data The (cached) data. @param {Date} lastModified The (cached) last modified date. */ function fakeDownload(url, id, callback, data, lastModified, owner) { var d=newDownload(url,callback); d.owner=owner; d.id=id; d.data=data; d.lastModified=lastModified; return callback(d); } /** Starts a download. @param {String} url The url to download @param {integer} id The ID of the {@link Downloader} object @param {Function} callback The callback function invoked on success @return {String/Downloader} the {@link Downloader} object created, or 'ohdear' if an unsupported browser */ function startDownload(url, id, callback) { var d=newDownload(url, id, callback); if (typeof d == typeof '' ) { return d; } d.start(); return d; } /** Aborts all downloads which have been started. */ function abortAllDownloads() { for ( var x in pg.misc.downloadsInProgress ) { try { pg.misc.downloadsInProgress[x].aborted=true; pg.misc.downloadsInProgress[x].abort(); delete pg.misc.downloadsInProgress[x]; } catch (e) { } } } // ENDFILE: downloader.js // STARTFILE: livepreview.js // TODO: location is often not correct (eg relative links in previews) /** * InstaView - a Mediawiki to HTML converter in JavaScript * Version 0.6.1 * Copyright (C) Pedro Fayolle 2005-2006 * http://en.wikipedia.org/wiki/User:Pilaf * Distributed under the BSD license * * Changelog: * * 0.6.1 * - Fixed problem caused by \r characters * - Improved inline formatting parser * * 0.6 * - Changed name to InstaView * - Some major code reorganizations and factored out some common functions * - Handled conversion of relative links (i.e. [[/foo]]) * - Fixed misrendering of adjacent definition list items * - Fixed bug in table headings handling * - Changed date format in signatures to reflect Mediawiki's * - Fixed handling of [[:Image:...]] * - Updated MD5 function (hopefully it will work with UTF-8) * - Fixed bug in handling of links inside images * * To do: * - Better support for * - Full support for * - Parser-based (as opposed to RegExp-based) inline wikicode handling (make it one-pass and bullet-proof) * - Support for templates (through AJAX) * - Support for coloured links (AJAX) */ var Insta = {}; function setupLivePreview() { // options Insta.conf = { baseUrl: '', user: {}, wiki: { lang: pg.wiki.lang, interwiki: pg.wiki.interwiki, default_thumb_width: 180 }, paths: { articles: pg.wiki.articlePath + '/', // Only used for Insta previews with images. (not in popups) math: '/math/', images: '//upload.wikimedia.org/wikipedia/en/', // FIXME ( window.getImageUrlStart ? getImageUrlStart(pg.wiki.hostname) : ''), images_fallback: '//upload.wikimedia.org/wikipedia/commons/', }, locale: { user: mw.config.get('wgFormattedNamespaces')[pg.nsUserId], image: mw.config.get('wgFormattedNamespaces')[pg.nsImageId], category: mw.config.get('wgFormattedNamespaces')[pg.nsCategoryId], // shouldn't be used in popup previews, i think months: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] } }; // options with default values or backreferences with (Insta.conf) { user.name = user.name || 'Wikipedian'; user.signature = '[['+locale.user+':'+user.name+'|'+user.name+']]'; //paths.images = '//upload.wikimedia.org/wikipedia/' + wiki.lang + '/'; } // define constants Insta.BLOCK_IMAGE = new RegExp('^\\[\\[(?:File|Image|'+Insta.conf.locale.image+ '):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', 'i'); } Insta.dump = function(from, to) { if (typeof from == 'string') { from = document.getElementById(from); } if (typeof to == 'string') { to = document.getElementById(to); } to.innerHTML = this.convert(from.value); }; Insta.convert = function(wiki) { var ll = (typeof wiki == 'string')? wiki.replace(/\r/g,'').split(/\n/): wiki, // lines of wikicode o = '', // output p = 0, // para flag $r; // result of passing a regexp to $() // some shorthands function remain() { return ll.length; } function sh() { return ll.shift(); } // shift function ps(s) { o += s; } // push // similar to C's printf, uses ? as placeholders, ?? to escape question marks function f() { var i=1, a=arguments, f=a[0], o='', c, p; for (; i/g,">"); } // Wiki text parsing to html is a nightmare. // The below functions deliberately don't escape the ampersand since this would make it more difficult, // and we don't absolutely need to for how we need it. // This means that any unescaped ampersands in wikitext will remain unescaped and can cause invalid HTML. // Browsers should all be able to handle it though. // We also escape significant wikimarkup characters to prevent further matching on the processed text function htmlescape_text(s) { return s.replace(//g,">").replace(/:/g,":").replace(/\[/g,"[").replace(/]/g,"]"); } function htmlescape_attr(s) { return htmlescape_text(s).replace(/'/g,"'").replace(/"/g,"""); } function max(a,b) { return (a>b)?a:b; } function min(a,b) { return (a= ipos; i--) { var pi = prev.charAt(i); if (pi=='*') { ps(''); } else if (pi=='#') { ps(''); } // close a dl only if the new item is not a dl item (:, ; or empty) else switch (l_match[1].charAt(i)) { case'':case'*':case'#': ps('') } } // open new lists for (var i=ipos; i'); } else if (li=='#') { ps('
    '); } // open a new dl only if the prev item is not a dl item (:, ; or empty) else { switch(prev.charAt(i)) { case'':case'*':case'#': ps('
    ') } } } switch (l_match[1].charAt(l_match[1].length-1)) { case '*': case '#': ps('
  1. ' + parse_inline_nowiki(l_match[2])); break case ';': ps('
    '); var dt_match; // handle ;dt :dd format if (dt_match = l_match[2].match(/(.*?)(:.*?)$/)) { ps(parse_inline_nowiki(dt_match[1])) ll.unshift(dt_match[2]) } else ps(parse_inline_nowiki(l_match[2])) break; case ':': ps('
    ' + parse_inline_nowiki(l_match[2])) } prev=l_match[1] } // close remaining lists for (var i=prev.length-1; i>=0; i--) ps(f('', (prev.charAt(i)=='*')? 'ul': ((prev.charAt(i)=='#')? 'ol': 'dl'))) } function parse_table() { endl(f('', $(/^\{\|( .*)$/)? $r[1]: '')) for (;remain();) if ($('|')) switch (_(1)) { case '}': endl('
    '); return case '-': endl(f('', $(/\|-*(.*)/)[1])); break default: parse_table_data() } else if ($('!')) parse_table_data() else sh() } function parse_table_data() { var td_line, match_i // 1: "|+", '|' or '+' // 2: ?? // 3: attributes ?? // TODO: finish commenting this regexp var td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/) if (td_match[1] == '|+') ps('') if (td_match[1] != '|+') { // use || or !! as a cell separator depending on context // NOTE: when split() is passed a regexp make sure to use non-capturing brackets td_line = td_match[match_i].split((td_match[1] == '|')? '||': /(?:\|\||!!)/) ps(parse_inline_nowiki(td_line.shift())) while (td_line.length) ll.unshift(td_match[1] + td_line.pop()) } else ps(td_match[match_i]) var tc = 0, td = [] for (;remain(); td.push(sh())) if ($('|')) { if (!tc) break // we're at the outer-most level (no nested tables), skip to td parse else if (_(1)=='}') tc-- } else if (!tc && $('!')) break else if ($('{|')) tc++ if (td.length) ps(Insta.convert(td)) } function parse_pre() { ps('
    ')
    		do endl(parse_inline_nowiki(ll[0].substring(1)) + "\n"); while (remain() && $(' '))
    		ps('
    ') } function parse_block_image() { ps(parse_image(sh())) } function parse_image(str) { // // get what's in between "[[Image:" and "]]" var tag = str.substring(str.indexOf(':') + 1, str.length - 2); var width; var attr = [], filename, caption = ''; var thumb=0, frame=0, center=0; var align=''; if (tag.match(/\|/)) { // manage nested links var nesting = 0; var last_attr; for (var i = tag.length-1; i > 0; i--) { if (tag.charAt(i) == '|' && !nesting) { last_attr = tag.substr(i+1); tag = tag.substring(0, i); break; } else switch (tag.substr(i-1, 2)) { case ']]': nesting++; i--; break; case '[[': nesting--; i--; } } attr = tag.split(/\s*\|\s*/); attr.push(last_attr); filename = attr.shift(); var w_match; for (;attr.length; attr.shift()) if (w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/)) width = w_match[1] else switch(attr[0]) { case 'thumb': case 'thumbnail': thumb=true; case 'frame': frame=true; break; case 'none': case 'right': case 'left': center=false; align=attr[0]; break; case 'center': center=true; align='none'; break; default: if (attr.length == 1) caption = attr[0]; } } else filename = tag; var o=''; if (frame) { if (align=='') align = 'right'; o += f("
    ", align); if (thumb) { if (!width) width = Insta.conf.wiki.default_thumb_width; o += f("
    ?", 2+width*1, make_image(filename, caption, width)) + f("
    ?
    ", htmlescape_attr(Insta.conf.paths.articles + Insta.conf.locale.image + ':' + filename), parse_inline_nowiki(caption) ) } else { o += '
    ' + make_image(filename, caption) + f("
    ?
    ", parse_inline_nowiki(caption)) } o += '
    '; } else if (align != '') { o += f("
    ?
    ", align, make_image(filename, caption, width)); } else { return make_image(filename, caption, width); } return center? f("
    ?
    ", o): o; // } function parse_inline_nowiki(str) { var start, lastend=0 var substart=0, nestlev=0, open, close, subloop; var html=''; while (-1 != (start = str.indexOf('', substart))) { html += parse_inline_wiki(str.substring(lastend, start)); start += 8; substart = start; subloop = true; do { open = str.indexOf('', substart); close = str.indexOf('', substart); if (close<=open || open==-1) { if (close==-1) { return html + html_entities(str.substr(start)); } substart = close+9; if (nestlev) { nestlev--; } else { lastend = substart; html += html_entities(str.substring(start, lastend-9)); subloop = false; } } else { substart = open+8; nestlev++; } } while (subloop) } return html + parse_inline_wiki(str.substr(lastend)); } function make_image(filename, caption, width) { // // uppercase first letter in file name filename = filename.charAt(0).toUpperCase() + filename.substr(1); // replace spaces with underscores filename = filename.replace(/ /g, '_'); caption = strip_inline_wiki(caption); var md5 = hex_md5(filename); var source = md5.charAt(0) + '/' + md5.substr(0,2) + '/' + filename; if (width) width = "width='" + width + "px'"; var img = ""; return f("?", (caption!='')? "title=\"" + pg.escapeQuotesHTML(caption) + "\"" : '', pg.escapeQuotesHTML(Insta.conf.paths.articles + Insta.conf.locale.image + ':' + filename), img); // } function parse_inline_images(str) { // var start, substart=0, nestlev=0; var loop, close, open, wiki, html; while (-1 != (start=str.indexOf('[[', substart))) { if(str.substr(start+2).match(RegExp('^(Image|File|' + Insta.conf.locale.image + '):','i'))) { loop=true; substart=start; do { substart+=2; close=str.indexOf(']]',substart); open=str.indexOf('[[',substart); if (close<=open||open==-1) { if (close==-1) return str; substart=close; if (nestlev) { nestlev--; } else { wiki=str.substring(start,close+2); html=parse_image(wiki); str=str.replace(wiki,html); substart=start+html.length; loop=false; } } else { substart=open; nestlev++; } } while (loop) } else break; } // return str; } // the output of this function doesn't respect the FILO structure of HTML // but since most browsers can handle it I'll save myself the hassle function parse_inline_formatting(str) { var em,st,i,li,o=''; while ((i=str.indexOf("''",li))+1) { o += str.substring(li,i); li=i+2; if (str.charAt(i+2)=="'") { li++; st=!st; o+=st?'':''; } else { em=!em; o+=em?'':''; } } return o+str.substr(li); } function parse_inline_wiki(str) { var aux_match; str = parse_inline_images(str); str = parse_inline_formatting(str); // math while (aux_match = str.match(/<(?:)math>(.*?)<\/math>/i)) { var math_md5 = hex_md5(aux_match[1]); str = str.replace(aux_match[0], f("", Insta.conf.paths.math+math_md5)); } // Build a Mediawiki-formatted date string var date = new Date; var minutes = date.getUTCMinutes(); if (minutes < 10) minutes = '0' + minutes; var date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), Insta.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear()); // text formatting return str. // signatures replace(/~{5}(?!~)/g, date). replace(/~{4}(?!~)/g, Insta.conf.user.name+' '+date). replace(/~{3}(?!~)/g, Insta.conf.user.name). // [[:Category:...]], [[:Image:...]], etc... replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+'|Image|File|'+Insta.conf.locale.image+'|'+Insta.conf.wiki.interwiki+'):[^|]*?)\\]\\](\w*)','gi'), function($0,$1,$2){return f("?", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2));}). // remove straight category and interwiki tags replace(RegExp('\\[\\[(?:'+Insta.conf.locale.category+'|'+Insta.conf.wiki.interwiki+'):.*?\\]\\]','gi'),''). // [[:Category:...|Links]], [[:Image:...|Links]], etc... replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+'|Image|File|'+Insta.conf.locale.image+'|'+Insta.conf.wiki.interwiki+'):.*?)\\|([^\\]]+?)\\]\\](\\w*)','gi'), function($0,$1,$2,$3){return f("?", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3));}). // [[/Relative links]] replace(/\[\[(\/[^|]*?)\]\]/g, function($0,$1){return f("?", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($1)); }). // [[/Replaced|Relative links]] replace(/\[\[(\/.*?)\|(.+?)\]\]/g, function($0,$1,$2){return f("?", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($2)); }). // [[Common links]] replace(/\[\[([^|]*?)\]\](\w*)/g, function($0,$1,$2){return f("?", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2)); }). // [[Replaced|Links]] replace(/\[\[(.*?)\|([^\]]+?)\]\](\w*)/g, function($0,$1,$2,$3){return f("?", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3)); }). // [[Stripped:Namespace|Namespace]] replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, function($0,$1,$2,$3){return f("?", Insta.conf.paths.articles + htmlescape_attr($1) + htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($2)); }). // External links replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, function($0,$1,$2,$3,$4){return f("?", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($4)); }). replace(/\[http:\/\/(.*?)\]/g, function($0,$1){return f("[#]", htmlescape_attr($1)); }). replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, function($0,$1,$2,$3,$4){return f("?:?", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($1), htmlescape_text($2) + htmlescape_text($3)); }). replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^.,!?;: $])/g, function($0,$1,$2,$3,$4){return f("??:?", htmlescape_text($1), htmlescape_attr($2), htmlescape_attr($3) + htmlescape_attr($4), htmlescape_text($2), htmlescape_text($3) + htmlescape_text($4)); }). replace('__NOTOC__',''). replace('__NOEDITSECTION__',''); } /* */ function strip_inline_wiki(str) { return str .replace(/\[\[[^\]]*\|(.*?)\]\]/g,'$1') .replace(/\[\[(.*?)\]\]/g,'$1') .replace(/''(.*?)''/g,'$1'); } // begin parsing for (;remain();) if ($(/^(={1,6})(.*)\1(.*)$/)) { p=0 endl(f('??', $r[1].length, parse_inline_nowiki($r[2]), $r[1].length, $r[3])) } else if ($(/^[*#:;]/)) { p=0 parse_list() } else if ($(' ')) { p=0 parse_pre() } else if ($('{|')) { p=0 parse_table() } else if ($(/^----+$/)) { p=0 endl('
    ') } else if ($(Insta.BLOCK_IMAGE)) { p=0 parse_block_image() } else { // handle paragraphs if ($$('')) { if (p = (remain()>1 && ll[1]==(''))) endl('


    ') } else { if(!p) { ps('

    ') p=1 } ps(parse_inline_nowiki(ll[0]) + ' ') } sh(); } return o }; window.wiki2html=function(txt,baseurl) { Insta.conf.baseUrl=baseurl; return Insta.convert(txt); }; // ENDFILE: livepreview.js // STARTFILE: pageinfo.js // function popupFilterPageSize(data) { return formatBytes(data.length); } function popupFilterCountLinks(data) { var num=countLinks(data); return String(num) + ' ' + ((num!=1)?popupString('wikiLinks'):popupString('wikiLink')); } function popupFilterCountImages(data) { var num=countImages(data); return String(num) + ' ' + ((num!=1)?popupString('images'):popupString('image')); } function popupFilterCountCategories(data) { var num=countCategories(data); return String(num) + ' ' + ((num!=1)?popupString('categories'):popupString('category')); } function popupFilterLastModified(data,download) { var lastmod=download.lastModified; var now=new Date(); var age=now-lastmod; if (lastmod && getValueOf('popupLastModified')) { return (tprintf('%s old', [formatAge(age)])).replace(RegExp(' ','g'), ' '); } return ''; } function formatAge(age) { // coerce into a number var a=0+age, aa=a; var seclen = 1000; var minlen = 60*seclen; var hourlen = 60*minlen; var daylen = 24*hourlen; var weeklen = 7*daylen; var numweeks = (a-a%weeklen)/weeklen; a = a-numweeks*weeklen; var sweeks = addunit(numweeks, 'week'); var numdays = (a-a%daylen)/daylen; a = a-numdays*daylen; var sdays = addunit(numdays, 'day'); var numhours = (a-a%hourlen)/hourlen; a = a-numhours*hourlen; var shours = addunit(numhours,'hour'); var nummins = (a-a%minlen)/minlen; a = a-nummins*minlen; var smins = addunit(nummins, 'minute'); var numsecs = (a-a%seclen)/seclen; a = a-numsecs*seclen; var ssecs = addunit(numsecs, 'second'); if (aa > 4*weeklen) { return sweeks; } if (aa > weeklen) { return sweeks + ' ' + sdays; } if (aa > daylen) { return sdays + ' ' + shours; } if (aa > 6*hourlen) { return shours; } if (aa > hourlen) { return shours + ' ' + smins; } if (aa > 10*minlen) { return smins; } if (aa > minlen) { return smins + ' ' + ssecs; } return ssecs; } function addunit(num,str) { return '' + num + ' ' + ((num!=1) ? popupString(str+'s') : popupString(str)) ;} function runPopupFilters(list, data, download) { var ret=[]; for (var i=0; i 949) ? (Math.round(num/100)/10+popupString('kB')) : (num +' ' + popupString('bytes')) ; } // // ENDFILE: pageinfo.js // STARTFILE: titles.js /** @fileoverview Defines the {@link Title} class, and associated crufty functions. Title deals with article titles and their various forms. {@link Stringwrapper} is the parent class of Title, which exists simply to make things a little neater. */ /** Creates a new Stringwrapper. @constructor @class the Stringwrapper class. This base class is not really useful on its own; it just wraps various common string operations. */ function Stringwrapper() { /** Wrapper for this.toString().indexOf() @param {String} x @type integer */ this.indexOf=function(x){return this.toString().indexOf(x);}; /** Returns this.value. @type String */ this.toString=function(){return this.value;}; /** Wrapper for {@link String#parenSplit} applied to this.toString() @param {RegExp} x @type Array */ this.parenSplit=function(x){return this.toString().parenSplit(x);}; /** Wrapper for this.toString().substring() @param {String} x @param {String} y (optional) @type String */ this.substring=function(x,y){ if (typeof y=='undefined') { return this.toString().substring(x); } return this.toString().substring(x,y); }; /** Wrapper for this.toString().split() @param {String} x @type Array */ this.split=function(x){return this.toString().split(x);}; /** Wrapper for this.toString().replace() @param {String} x @param {String} y @type String */ this.replace=function(x,y){ return this.toString().replace(x,y); }; } /** Creates a new Title. @constructor @class The Title class. Holds article titles and converts them into various forms. Also deals with anchors, by which we mean the bits of the article URL after a # character, representing locations within an article. @param {String} value The initial value to assign to the article. This must be the canonical title (see {@link Title#value}. Omit this in the constructor and use another function to set the title if this is unavailable. */ function Title(val) { /** The canonical article title. This must be in UTF-8 with no entities, escaping or nasties. Also, underscores should be replaced with spaces. @type String @private */ this.value=null; /** The canonical form of the anchor. This should be exactly as it appears in the URL, i.e. with the .C3.0A bits in. @type String */ this.anchor=''; this.setUtf(val); } Title.prototype=new Stringwrapper(); /** Returns the canonical representation of the article title, optionally without anchor. @param {boolean} omitAnchor @fixme Decide specs for anchor @return String The article title and the anchor. */ Title.prototype.toString=function(omitAnchor) { return this.value + ( (!omitAnchor && this.anchor) ? '#' + this.anchorString() : '' ); }; Title.prototype.anchorString=function() { if (!this.anchor) { return ''; } var split=this.anchor.parenSplit(/((?:[.][0-9A-F]{2})+)/); var len=split.length; for (var j=1; j %25E5%25A3. this.setUtf(decodeURIComponent(unescape(extracted))); } else { this.setUtf(this.decodeNasties(extracted)); } } return this; }; Title.prototype.decodeNasties=function(txt) { var ret= this.decodeEscapes(decodeURI(txt)); ret = ret.replace(/[_ ]*$/, ''); return ret; }; Title.prototype.decodeEscapes=function(txt) { var split=txt.parenSplit(/((?:[%][0-9A-Fa-f]{2})+)/); var len=split.length; for (var i=1; i Title.prototype.toUserName=function(withNs) { if (this.namespaceId() != pg.nsUserId && this.namespaceId() != pg.nsUsertalkId) { this.value=null; return; } this.value = (withNs ? mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + ':' : '') + this.stripNamespace().split('/')[0]; }; Title.prototype.userName=function(withNs) { var t=(new Title(this.value)); t.toUserName(withNs); if (t.value) { return t; } return null; }; Title.prototype.toTalkPage=function() { // convert article to a talk page, or if we can't, return null // In other words: return null if this ALREADY IS a talk page // and return the corresponding talk page otherwise // // Per http://www.mediawiki.org/wiki/Manual:Namespace#Subject_and_talk_namespaces // * All discussion namespaces have odd-integer indices // * The discussion namespace index for a specific namespace with index n is n + 1 if (this.value===null) { return null; } var namespaceId = this.namespaceId(); if (namespaceId>=0 && namespaceId % 2 == 0) //non-special and subject namespace { var localizedNamespace = mw.config.get('wgFormattedNamespaces')[namespaceId+1]; if (typeof localizedNamespace!=='undefined') { if (localizedNamespace==='') return this.value = this.stripNamespace(); this.value = localizedNamespace.split(' ').join('_') + ':' + this.stripNamespace(); return this.value; } } this.value=null; return null; }; // // Return canonical, localized namespace Title.prototype.namespace=function() { return mw.config.get('wgFormattedNamespaces')[this.namespaceId()]; }; Title.prototype.namespaceId=function() { var n=this.value.indexOf(':'); if (n<0) { return 0; } //mainspace var namespaceId = mw.config.get('wgNamespaceIds')[this.value.substring(0,n).split(' ').join('_').toLowerCase()]; if (typeof namespaceId=='undefined') return 0; //mainspace return namespaceId; }; // Title.prototype.talkPage=function() { var t=new Title(this.value); t.toTalkPage(); if (t.value) { return t; } return null; }; Title.prototype.isTalkPage=function() { if (this.talkPage()===null) { return true; } return false; }; Title.prototype.toArticleFromTalkPage=function() { //largely copy/paste from toTalkPage above. if (this.value===null) { return null; } var namespaceId = this.namespaceId(); if (namespaceId>=0 && namespaceId % 2 == 1) //non-special and talk namespace { var localizedNamespace = mw.config.get('wgFormattedNamespaces')[namespaceId-1]; if (typeof localizedNamespace!=='undefined') { if (localizedNamespace==='') return this.value = this.stripNamespace(); this.value = localizedNamespace.split(' ').join('_') + ':' + this.stripNamespace(); return this.value; } } this.value=null; return null; }; Title.prototype.articleFromTalkPage=function() { var t=new Title(this.value); t.toArticleFromTalkPage(); if (t.value) { return t; } return null; }; Title.prototype.articleFromTalkOrArticle=function() { var t=new Title(this.value); if ( t.toArticleFromTalkPage() ) { return t; } return this; }; Title.prototype.isIpUser=function() { return pg.re.ipUser.test(this.userName()); }; // Title.prototype.stripNamespace=function(){ // returns a string, not a Title var n=this.value.indexOf(':'); if (n<0) { return this.value; } var namespaceId = this.namespaceId(); if (namespaceId===pg.nsMainspaceId) return this.value; return this.value.substring(n+1); }; Title.prototype.setUtf=function(value){ if (!value) { this.value=''; return; } var anch=value.indexOf('#'); if(anch < 0) { this.value=value.split('_').join(' '); this.anchor=''; return; } this.value=value.substring(0,anch).split('_').join(' '); this.anchor=value.substring(anch+1); this.ns=null; // wait until namespace() is called }; Title.prototype.setUrl=function(urlfrag) { var anch=urlfrag.indexOf('#'); this.value=safeDecodeURI(urlfrag.substring(0,anch)); this.anchor=value.substring(anch+1); }; Title.prototype.append=function(x){ this.setUtf(this.value + x); }; Title.prototype.urlString=function(x) { x || ( x={} ); var v=this.toString(true); if (!x.omitAnchor && this.anchor) { v+= '#' + this.urlAnchor(); } if (!x.keepSpaces) { v=v.split(' ').join('_'); } return encodeURI(v).split('&').join('%26').split('?').join('%3F').split('+').join('%2B'); }; Title.prototype.removeAnchor=function() { return new Title(this.toString(true)); }; Title.prototype.toUrl=function() { return pg.wiki.titlebase + this.urlString(); }; function paramValue(param, url) { var s=url.parenSplit(RegExp('[?&]' + literalizeRegex(param) + '=([^?&]*)')); if (!url) { return null; } return s[1] || null; } function parseParams(url) { var specialDiff = pg.re.specialdiff.exec(url); if (specialDiff!==null) { var split= specialDiff[1].split('/'); if (split.length==1) return {oldid:split[0], diff: 'prev'}; else if (split.length==2) return {oldid: split[0], diff: split[1]}; } var ret={}; if (url.indexOf('?')==-1) { return ret; } url = url.split('#')[0]; var s=url.split('?').slice(1).join(); var t=s.split('&'); for (var i=0; i function isIpUser(user) {return pg.re.ipUser.test(user);} function isDisambig(data, article) { if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } return ! article.isTalkPage() && pg.re.disambig.test(data); } function stubCount(data, article) { if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } var sectStub=0; var realStub=0; if (pg.re.stub.test(data)) { var s=data.parenSplit(pg.re.stub); for (var i=1; i function isPopupLink(a) { // NB for performance reasons, TOC links generally return true // they should be stripped out later if (!markNopopupSpanLinks.done) { markNopopupSpanLinks(); } if (a.inNopopupSpan) { return false; } // FIXME is this faster inline? if (a.onmousedown || a.getAttribute('nopopup')) { return false; } var h=a.href; if (h===document.location.href+'#') { return false; } if (!pg.re.basenames.test(h)) { return false; } if (!pg.re.urlNoPopup.test(h)) { return true; } return ( (pg.re.email.test(h) || pg.re.contribs.test(h) || pg.re.backlinks.test(h) || pg.re.specialdiff.test(h)) && h.indexOf('&limit=') == -1 ); } function markNopopupSpanLinks() { if( !getValueOf('popupOnlyArticleLinks')) fixVectorMenuPopups(); var s = $('.nopopups').toArray(); for (var i=0; i ////////////////////////////////////////////////// // Cookie handling // from http://www.quirksmode.org/js/cookies.html var Cookie= { create: function(name,value,days) { var expires; if (days) { var date = new Date(); date.setTime(date.getTime()+(days*24*60*60*1000)); expires = "; expires="+date.toGMTString(); } else { expires = ""; } document.cookie = name+"="+value+expires+"; path=/"; }, read: function(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') { c = c.substring(1,c.length); } if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); } } return null; }, erase: function(name) { Cookie.create(name,"",-1); } }; // // ENDFILE: cookies.js // STARTFILE: getpage.js ////////////////////////////////////////////////// // Wiki-specific downloading // // Schematic for a getWiki call // // getWiki->-getPageWithCaching // | // false | true // getPage<-[findPictureInCache]->-onComplete(a fake download) // \. // (async)->addPageToCache(download)->-onComplete(download) /** @todo {document} @param {Title} article @param {Function} onComplete @param {integer} oldid @param {Navapopup} owner */ function getWiki(article, onComplete, oldid, owner) { // set ctype=text/css to get around opera gzip bug var url = pg.wiki.titlebase; if (article.namespaceId() >= 0) url += article.removeAnchor().urlString(); if (oldid || oldid===0 || oldid==='0') url += '&oldid='+oldid; url += '&action=raw&ctype=text/css&maxage=0&smaxage=0'; getPageWithCaching(url, onComplete, owner); } // check cache to see if page exists function getPageWithCaching(url, onComplete, owner) { log('getPageWithCaching, url='+url); var i=findInPageCache(url); if (i > -1) { var d=fakeDownload(url, owner.idNumber, onComplete, pg.cache.pages[i].data, pg.cache.pages[i].lastModified, owner); } else { var d=getPage(url, onComplete, owner); if (d && owner && owner.addDownload) { owner.addDownload(d); d.owner=owner; } } } function getPage(url, onComplete, owner) { log('getPage'); var callback= function (d) { if (!d.aborted) {addPageToCache(d); onComplete(d);} }; return startDownload(url, owner.idNumber, callback); } function findInPageCache(url) { for (var i=0; i /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.2-alpha Copyright (C) Paul Johnston 1999 - 2005 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ /* * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings */ function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); } function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); } function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } function hex_hmac_md5(k, d) { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } function b64_hmac_md5(k, d) { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } function any_hmac_md5(k, d, e) { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } /* * Perform a simple self-test to see if the VM is working */ function md5_vm_test() { return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; } /* * Calculate the MD5 of a raw string */ function rstr_md5(s) { return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); } /* * Calculate the HMAC-MD5, of a key and some data (raw strings) */ function rstr_hmac_md5(key, data) { var bkey = rstr2binl(key); if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); } /* * Convert a raw string to a hex string */ function rstr2hex(input) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var output = ""; var x; for(var i = 0; i < input.length; i++) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt( x & 0x0F); } return output; } /* * Convert a raw string to a base-64 string */ function rstr2b64(input) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var output = ""; var len = input.length; for(var i = 0; i < len; i += 3) { var triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i+2) : 0); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > input.length * 8) output += b64pad; else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); } } return output; } /* * Convert a raw string to an arbitrary string encoding */ function rstr2any(input, encoding) { var divisor = encoding.length; var remainders = Array(); var i, q, x, quotient; /* Convert to an array of 16-bit big-endian values, forming the dividend */ var dividend = Array(input.length / 2); for(i = 0; i < dividend.length; i++) { dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); } /* * Repeatedly perform a long division. The binary array forms the dividend, * the length of the encoding is the divisor. Once computed, the quotient * forms the dividend for the next step. We stop when the dividend is zero. * All remainders are stored for later use. */ while(dividend.length > 0) { quotient = Array(); x = 0; for(i = 0; i < dividend.length; i++) { x = (x << 16) + dividend[i]; q = Math.floor(x / divisor); x -= q * divisor; if(quotient.length > 0 || q > 0) quotient[quotient.length] = q; } remainders[remainders.length] = x; dividend = quotient; } /* Convert the remainders to the output string */ var output = ""; for(i = remainders.length - 1; i >= 0; i--) output += encoding.charAt(remainders[i]); return output; } /* * Encode a string as utf-8. * For efficiency, this assumes the input is valid utf-16. */ function str2rstr_utf8(input) { var output = ""; var i = -1; var x, y; while(++i < input.length) { /* Decode utf-16 surrogate pairs */ x = input.charCodeAt(i); y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } /* Encode output as utf-8 */ if(x <= 0x7F) output += String.fromCharCode(x); else if(x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 0x80 | ( x & 0x3F)); else if(x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); else if(x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); } return output; } /* * Encode a string as utf-16 */ function str2rstr_utf16le(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); return output; } function str2rstr_utf16be(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); return output; } /* * Convert a raw string to an array of little-endian words * Characters >255 have their high-byte silently ignored. */ function rstr2binl(input) { var output = Array(input.length >> 2); for(var i = 0; i < output.length; i++) output[i] = 0; for(var i = 0; i < input.length * 8; i += 8) output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); return output; } /* * Convert an array of little-endian words to a string */ function binl2rstr(input) { var output = ""; for(var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); return output; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function binl_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i+10], 17, -42063); b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } return Array(a, b, c, d); } /* * These functions implement the four basic operations the algorithm uses. */ function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); } function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); } function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } // // ENDFILE: md5-2.2alpha.js // STARTFILE: parensplit.js ////////////////////////////////////////////////// // parenSplit // String.prototype.parenSplit should do what ECMAscript says String.prototype.split does, // interspersing paren matches (regex capturing groups) between the split elements. // i.e. 'abc'.split(/(b)/)) should return ['a','b','c'], not ['a','c'] if (String('abc'.split(/(b)/))!='a,b,c') { // broken String.split, e.g. konq, IE String.prototype.parenSplit=function (re) { re=nonGlobalRegex(re); var s=this; var m=re.exec(s); var ret=[]; while (m && s) { // without the following loop, we have // 'ab'.parenSplit(/a|(b)/) != 'ab'.split(/a|(b)/) for(var i=0; i function encode_utf8(rohtext) { // dient der Normalisierung des Zeilenumbruchs rohtext = rohtext.replace(/\r\n/g,"\n"); var utftext = ""; for(var n=0; n 1byte if (c<128) utftext += String.fromCharCode(c); // alle Zeichen von 127 bis 2047 => 2byte else if((c>127) && (c<2048)) { utftext += String.fromCharCode((c>>6)|192); utftext += String.fromCharCode((c&63)|128);} // alle Zeichen von 2048 bis 66536 => 3byte else { utftext += String.fromCharCode((c>>12)|224); utftext += String.fromCharCode(((c>>6)&63)|128); utftext += String.fromCharCode((c&63)|128);} } return utftext; } function getJsObj(json) { try { var json_ret = eval('(' + json + ')'); } catch (someError) { errlog('Something went wrong with getJsobj, json='+json); return 1; } if( json_ret['warnings'] ) { for( var w=0; w < json_ret['warnings'].length; w++ ) { log( json_ret['warnings'][w]['*'] ); } } else if ( json_ret['error'] ) { errlog( json_ret['error'].code + ': ' + json_ret['error'].info ); } return json_ret; } function anyChild(obj) { for (var p in obj) { return obj[p]; } return null; } // function decode_utf8(utftext) { var plaintext = ""; var i=0, c=0, c1=0, c2=0; // while-Schleife, weil einige Zeichen uebersprungen werden while(i191) && (c<224)) { c2 = utftext.charCodeAt(i+1); plaintext += String.fromCharCode(((c&31)<<6) | (c2&63)); i+=2;} else { c2 = utftext.charCodeAt(i+1); c3 = utftext.charCodeAt(i+2); plaintext += String.fromCharCode(((c&15)<<12) | ((c2&63)<<6) | (c3&63)); i+=3;} } return plaintext; } function upcaseFirst(str) { if (typeof str != typeof '' || str=='') return ''; return str.charAt(0).toUpperCase() + str.substring(1); } function findInArray(arr, foo) { if (!arr || !arr.length) { return -1; } var len=arr.length; for (var i=0; i').join('>'/*+shy*/).split('"').join('"'); }; function findThis(array, value) { if (typeof array.length == 'undefined') { return null; } for (var i=0; i -1 && j < subs.length ) { ret.push(subs[j]); } else { ret.push(cmd); } } } while (s.length > 0); return ret.join(''); } function max(a,b){return ab ? b : a;} function isString(x) { return (typeof x === 'string' || x instanceof String); } //function isNumber(x) { return (typeof x === 'number' || x instanceof Number); } function isRegExp(x) { return x instanceof RegExp; } function isArray (x) { return x instanceof Array; } function isObject(x) { return x instanceof Object; } function isFunction(x) { return !isRegExp(x) && ($.isFunction(x) || x instanceof Function); } function repeatString(s,mult) { var ret=''; for (var i=0; i', "g" ); text = text.replace( re, ">" ); return text;} pg.jsescape = function(s) { if (typeof s !== "string") throw "Invalid type in pg.jsescape"; var res = ""; //this can be optimized by copying substrings instead of char by char! for (var i=0; i' || c==="'") { var unicodeChar = c.charCodeAt(0).toString(16).toUpperCase(); res += "\\u" + (unicodeChar.length>1?"00":"000") + unicodeChar; } else { res += c; } } } return res; } // ENDFILE: tools.js // STARTFILE: dab.js // ////////////////////////////////////////////////// // Dab-fixing code // function retargetDab(newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) { log('retargetDab: newTarget='+newTarget + ' oldTarget=' + oldTarget); return changeLinkTargetLink( {newTarget: newTarget, text: newTarget.split(' ').join(' '), hint: tprintf('disambigHint', [newTarget]), summary: simplePrintf( getValueOf('popupFixDabsSummary'), [friendlyCurrentArticleName, newTarget ]), clickButton: getValueOf('popupDabsAutoClick'), minor: true, oldTarget: oldTarget, watch: getValueOf('popupWatchDisambiggedPages'), title: titleToEdit}); } function listLinks(wikitext, oldTarget, titleToEdit) { // mediawiki strips trailing spaces, so we do the same // testcase: http://en.wikipedia.org/w/index.php?title=Radial&oldid=97365633 var reg=RegExp('\\[\\[([^|]*?) *(\\||\\]\\])', 'gi'); var ret=[]; var splitted=wikitext.parenSplit(reg); // ^[a-z]+ should match interwiki links, hopefully (case-insensitive) // and ^[a-z]* should match those and [[:Category...]] style links too var omitRegex=RegExp('^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory'); var friendlyCurrentArticleName= oldTarget.toString(); var wikPos = getValueOf('popupDabWiktionary'); for (var i=1; i0 && !omitRegex.test(splitted[i])) { ret.push( retargetDab(splitted[i], oldTarget, friendlyCurrentArticleName, titleToEdit) ); } /* if */ } /* for loop */ ret = rmDupesFromSortedList(ret.sort()); if (wikPos) { var wikTarget='wiktionary:' + friendlyCurrentArticleName.replace( RegExp('^(.+)\\s+[(][^)]+[)]\\s*$'), '$1' ); var meth; if (wikPos.toLowerCase() == 'first') { meth = 'unshift'; } else { meth = 'push'; } ret[meth]( retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) ); } ret.push(changeLinkTargetLink( { newTarget: null, text: popupString('remove this link').split(' ').join(' '), hint: popupString("remove all links to this disambig page from this article"), clickButton: "wpDiff", oldTarget: oldTarget, summary: simplePrintf(getValueOf('popupRmDabLinkSummary'), [friendlyCurrentArticleName]), watch: getValueOf('popupWatchDisambiggedPages'), title: titleToEdit })); return ret; } function rmDupesFromSortedList(list) { var ret=[]; for (var i=0; i'; html+=list.join(', '); return html; } function makeFixDabs(wikiText, navpop) { if (getValueOf('popupFixDabs') && isDisambig(wikiText, navpop.article) && Title.fromURL(location.href).namespaceId() != pg.nsSpecialId && navpop.article.talkPage() ) { setPopupHTML(makeFixDab(wikiText, navpop), 'popupFixDab', navpop.idNumber); } } function popupRedlinkHTML(article) { return changeLinkTargetLink( { newTarget: null, text: popupString('remove this link').split(' ').join(' '), hint: popupString("remove all links to this page from this article"), clickButton: "wpDiff", oldTarget: article.toString(), summary: simplePrintf(getValueOf('popupRedlinkSummary'), [article.toString()])}); } // // ENDFILE: dab.js // STARTFILE: htmloutput.js function appendPopupContent(obj, elementId, popupId, onSuccess) { return setPopupHTML(obj, elementId, popupId, onSuccess, true); } // this has to use a timer loop as we don't know if the DOM element exists when we want to set the text function setPopupHTML (str, elementId, popupId, onSuccess, append) { if (elementId=='popupPreview') { } if (typeof popupId === 'undefined') { //console.error('popupId is not defined in setPopupHTML, html='+str.substring(0,100)); popupId = pg.idNumber; } var popupElement=document.getElementById(elementId+popupId); if (popupElement) { if (!append) { popupElement.innerHTML=''; } if (isString(str)) { popupElement.innerHTML+=str; } else { popupElement.appendChild(str); } if (onSuccess) { onSuccess(); } setTimeout(checkPopupPosition, 100); return true; } else { // call this function again in a little while... setTimeout(function(){ setPopupHTML(str,elementId,popupId,onSuccess); }, 600); } return null; } // function setPopupTrailer(str,id) {return setPopupHTML(str, 'popupData', id);} // function fillEmptySpans(args) { return fillEmptySpans2(args); } // args.navpopup is mandatory // optional: args.redir, args.redirTarget // FIXME: ye gods, this is ugly stuff function fillEmptySpans2(args) { // if redir is present and true then redirTarget is mandatory var redir=true; if (typeof args != 'object' || typeof args.redir == 'undefined' || !args.redir) { redir=false; } var a=args.navpopup.parentAnchor; var article, hint=null, oldid=null, params={}; if (redir && typeof args.redirTarget == typeof {}) { article=args.redirTarget; //hint=article.hintValue(); } else { article=(new Title()).fromAnchor(a); hint=a.originalTitle || article.hintValue(); params=parseParams(a.href); oldid=(getValueOf('popupHistoricalLinks')) ? params.oldid : null; rcid=params.rcid; } var x={ article:article, hint: hint, oldid: oldid, rcid: rcid, navpop:args.navpopup, params:params }; var structure=pg.structures[getValueOf('popupStructure')]; if (typeof structure != 'object') { setPopupHTML('popupError', 'Unknown structure (this should never happen): '+ pg.option.popupStructure, args.navpopup.idNumber); return; } var spans=flatten(pg.misc.layout); var numspans = spans.length; var redirs=pg.misc.redirSpans; for (var i=0; i 0 ) { ret = ret.parenSplit(RegExp('(]*?>$)')).join(makeEmptySpans(list[i], navpop)); } else if (typeof list[i] == typeof {} && list[i].nodeType ) { ret += emptySpanHTML(list[i].name, navpop.idNumber, list[i].nodeType); } } return ret; } function emptySpanHTML(name, id, tag, classname) { tag = tag || 'span'; if (!classname) { classname = emptySpanHTML.classAliases[name]; } classname = classname || name; if (name == getValueOf('popupDragHandle')) { classname += ' popupDragHandle'; } return simplePrintf('<%s id="%s" class="%s">', [tag, name + id, classname, tag]); } emptySpanHTML.classAliases={ 'popupSecondPreview': 'popupPreview' }; // generate html for popup image // // where n=idNumber function imageHTML(article, idNumber) { return simplePrintf('' + '' + '', [ idNumber ]); } function popTipsSoonFn(id, when, popData) { when || ( when=250 ); var popTips=function(){ setupTooltips(document.getElementById(id), false, true, popData); }; return function() { setTimeout( popTips, when, popData ); }; } function setPopupTipsAndHTML(html, divname, idnumber, popData) { setPopupHTML(html, divname, idnumber, getValueOf('popupSubpopups') ? popTipsSoonFn(divname + idnumber, null, popData) : null); } // ENDFILE: htmloutput.js // STARTFILE: mouseout.js ////////////////////////////////////////////////// // fuzzy checks function fuzzyCursorOffMenus(x,y, fuzz, parent) { if (!parent) { return null; } var uls=parent.getElementsByTagName('ul'); for (var i=0; i 0) return false; } // else {document.title+='.';} } return true; } function checkPopupPosition () { // stop the popup running off the right of the screen // FIXME avoid pg.current.link pg.current.link && pg.current.link.navpopup && pg.current.link.navpopup.limitHorizontalPosition(); } function mouseOutWikiLink () { if (!window.popupsReady || !window.popupsReady()) { return; } //console ('mouseOutWikiLink'); var a=this; if (a.navpopup==null) return; if ( ! a.navpopup.isVisible() ) { a.navpopup.banish(); return; } restoreTitle(a); Navpopup.tracker.addHook(posCheckerHook(a.navpopup)); } function posCheckerHook(navpop) { return function() { if (!navpop.isVisible()) { return true; /* remove this hook */ } if (Navpopup.tracker.dirty) { return false; } var x=Navpopup.tracker.x, y=Navpopup.tracker.y; var mouseOverNavpop = navpop.isWithin(x,y,navpop.fuzz, navpop.mainDiv) || !fuzzyCursorOffMenus(x,y,navpop.fuzz, navpop.mainDiv); // FIXME it'd be prettier to do this internal to the Navpopup objects var t=getValueOf('popupHideDelay'); if (t) { t = t * 1000; } if (!t) { if(!mouseOverNavpop) { if(navpop.parentAnchor) { restoreTitle( navpop.parentAnchor ); } navpop.banish(); return true; /* remove this hook */ } return false; } // we have a hide delay set var d=+(new Date()); if ( !navpop.mouseLeavingTime ) { navpop.mouseLeavingTime = d; return false; } if ( mouseOverNavpop ) { navpop.mouseLeavingTime=null; return false; } if (d - navpop.mouseLeavingTime > t) { navpop.mouseLeavingTime=null; navpop.banish(); return true; /* remove this hook */ } return false; }; } function runStopPopupTimer(navpop) { // at this point, we should have left the link but remain within the popup // so we call this function again until we leave the popup. if (!navpop.stopPopupTimer) { navpop.stopPopupTimer=setInterval(posCheckerHook(navpop), 500); navpop.addHook(function(){clearInterval(navpop.stopPopupTimer);}, 'hide', 'before'); } } // ENDFILE: mouseout.js // STARTFILE: previewmaker.js /** @fileoverview Defines the {@link Previewmaker} object, which generates short previews from wiki markup. */ /** Creates a new Previewmaker @constructor @class The Previewmaker class. Use an instance of this to generate short previews from Wikitext. @param {String} wikiText The Wikitext source of the page we wish to preview. @param {String} baseUrl The url we should prepend when creating relative urls. @param {Navpopup} owner The navpop associated to this preview generator */ function Previewmaker(wikiText, baseUrl, owner) { /** The wikitext which is manipulated to generate the preview. */ this.originalData=wikiText; this.setData(); this.baseUrl=baseUrl; this.owner=owner; this.maxCharacters=getValueOf('popupMaxPreviewCharacters'); this.maxSentences=getValueOf('popupMaxPreviewSentences'); } Previewmaker.prototype.setData=function() { var maxSize=max(10000, 2*this.maxCharacters); this.data=this.originalData.substring(0,maxSize); }; /** Remove HTML comments @private */ Previewmaker.prototype.killComments = function () { // this also kills one trailing newline, eg [[diamyo]] this.data=this.data.replace(RegExp('\\n?', 'g'), ''); }; /** @private */ Previewmaker.prototype.killDivs = function () { // say goodbye, divs (can be nested, so use * not *?) this.data=this.data.replace(RegExp('< *div[^>]* *>[\\s\\S]*?< */ *div *>', 'gi'), ''); }; /** @private */ Previewmaker.prototype.killGalleries = function () { this.data=this.data.replace(RegExp('< *gallery[^>]* *>[\\s\\S]*?< */ *gallery *>', 'gi'), ''); }; /** @private */ Previewmaker.prototype.kill = function(opening, closing, subopening, subclosing, repl) { var oldk=this.data; var k=this.killStuff(this.data, opening, closing, subopening, subclosing, repl); while (k.length < oldk.length) { oldk=k; k=this.killStuff(k, opening, closing, subopening, subclosing, repl); } this.data=k; }; /** @private */ Previewmaker.prototype.killStuff = function (txt, opening, closing, subopening, subclosing, repl) { var op=this.makeRegexp(opening); var cl=this.makeRegexp(closing, '^'); var sb=subopening ? this.makeRegexp(subopening, '^') : null; var sc=subclosing ? this.makeRegexp(subclosing, '^') : cl; if (!op || !cl) { alert('Navigation Popups error: op or cl is null! something is wrong.'); return; } if (!op.test(txt)) { return txt; } var ret=''; var opResult = op.exec(txt); ret = txt.substring(0,opResult.index); txt=txt.substring(opResult.index+opResult[0].length); var depth = 1; while (txt.length > 0) { var removal=0; if (depth==1 && cl.test(txt)) { depth--; removal=cl.exec(txt)[0].length; } else if (depth > 1 && sc.test(txt)) { depth--; removal=sc.exec(txt)[0].length; }else if (sb && sb.test(txt)) { depth++; removal=sb.exec(txt)[0].length; } if ( !removal ) { removal = 1; } txt=txt.substring(removal); if (depth==0) { break; } } return ret + (repl || '') + txt; }; /** @private */ Previewmaker.prototype.makeRegexp = function (x, prefix, suffix) { prefix = prefix || ''; suffix = suffix || ''; var reStr=''; var flags=''; if (isString(x)) { reStr=prefix + literalizeRegex(x) + suffix; } else if (isRegExp(x)) { var s=x.toString().substring(1); var sp=s.split('/'); flags=sp[sp.length-1]; sp[sp.length-1]=''; s=sp.join('/'); s=s.substring(0,s.length-1); reStr= prefix + s + suffix; } else { log ('makeRegexp failed'); } log ('makeRegexp: got reStr=' + reStr + ', flags=' + flags); return RegExp(reStr, flags); }; /** @private */ Previewmaker.prototype.killBoxTemplates = function () { // taxobox removal... in fact, there's a saudiprincebox_begin, so let's be more general // also, have float_begin, ... float_end this.kill(RegExp('[{][{][^{}\\s|]*?(float|box)[_ ](begin|start)', 'i'), /[}][}]\s*/, '{{'); // infoboxes etc // from [[User:Zyxw/popups.js]]: kill frames too this.kill(RegExp('[{][{][^{}\\s|]*?(infobox|elementbox|frame)[_ ]', 'i'), /[}][}]\s*/, '{{'); }; /** @private */ Previewmaker.prototype.killTemplates = function () { this.kill('{{', '}}', '{', '}', ' '); }; /** @private */ Previewmaker.prototype.killTables = function () { // tables are bad, too // this can be slow, but it's an inprovement over a browser hang // torture test: [[Comparison_of_Intel_Central_Processing_Units]] this.kill('{|', /[|]}\s*/, '{|'); this.kill(//i, /<\/table.*?>/i, //i); // remove lines starting with a pipe for the hell of it (?) this.data=this.data.replace(RegExp('^[|].*$', 'mg'), ''); }; /** @private */ Previewmaker.prototype.killImages = function () { var forbiddenNamespaceAliases = []; jQuery.each(mw.config.get('wgNamespaceIds'), function(_localizedNamespaceLc, _namespaceId) { if (_namespaceId!=pg.nsImageId && _namespaceId!=pg.nsCategoryId) return; forbiddenNamespaceAliases.push(_localizedNamespaceLc.split(' ').join('[ _]')); //todo: escape regexp fragments! }); // images and categories are a nono this.kill(RegExp('[[][[]\\s*(' + forbiddenNamespaceAliases.join('|') + ')\\s*:', 'i'), /\]\]\s*/, '[', ']'); }; /** @private */ Previewmaker.prototype.killHTML = function () { // kill ... this.kill(/]*?>/i, /<\/ref>/i); // let's also delete entire lines starting with <. it's worth a try. this.data=this.data.replace(RegExp('(^|\\n) *<.*', 'g'), '\n'); // and those pesky html tags, but not or

    var splitted=this.data.parenSplit(/(<[\w\W]*?(?:>|$|(?=<)))/); var len=splitted.length; for (var i=1; i': case '': case '
    ': case '
    ': break; default: splitted[i]=''; } } this.data=splitted.join(''); }; /** @private */ Previewmaker.prototype.killChunks = function() { // heuristics alert // chunks of italic text? you crazy, man? var italicChunkRegex=new RegExp ("((^|\\n)\\s*:*\\s*''[^']([^']|'''|'[^']){20}(.|\\n[^\\n])*''[.!?\\s]*\\n)+", 'g'); // keep stuff separated, though, so stick in \n (fixes [[Union Jack]]? this.data=this.data.replace(italicChunkRegex, '\n'); }; /** @private */ Previewmaker.prototype.mopup = function () { // we simply *can't* be doing with horizontal rules right now this.data=this.data.replace(RegExp('^-{4,}','mg'),''); // no indented lines this.data=this.data.replace(RegExp('(^|\\n) *:[^\\n]*','g'), ''); // replace __TOC__, __NOTOC__ and whatever else there is // this'll probably do this.data=this.data.replace(RegExp('^__[A-Z_]*__ *$', 'gmi'),''); }; /** @private */ Previewmaker.prototype.firstBit = function () { // dont't be givin' me no subsequent paragraphs, you hear me? /// first we "normalize" section headings, removing whitespace after, adding before var d=this.data; if (getValueOf('popupPreviewCutHeadings')) { this.data=this.data.replace(RegExp('\\s*(==+[^=]*==+)\\s*', 'g'), '\n\n$1 '); /// then we want to get rid of paragraph breaks whose text ends badly this.data=this.data.replace(RegExp('([:;]) *\\n{2,}', 'g'), '$1\n'); this.data=this.data.replace(RegExp('^[\\s\\n]*'), ''); stuff=(RegExp('^([^\\n]|\\n[^\\n\\s])*')).exec(this.data); if (stuff) { d = stuff[0]; } if (!getValueOf('popupPreviewFirstParOnly')) { d = this.data; } /// now put \n\n after sections so that bullets and numbered lists work d=d.replace(RegExp('(==+[^=]*==+)\\s*', 'g'), '$1\n\n'); } // Split sentences. Superfluous sentences are RIGHT OUT. // note: exactly 1 set of parens here needed to make the slice work d = d.parenSplit(RegExp('([!?.]+["'+"'"+']*\\s)','g')); // leading space is bad, mmkay? d[0]=d[0].replace(RegExp('^\\s*'), ''); var notSentenceEnds=RegExp('([^.][a-z][.] *[a-z]|etc|sic|Dr|Mr|Mrs|Ms|St|no|op|cit|\\[[^\\]]*|\\s[A-Zvclm])$', 'i'); d = this.fixSentenceEnds(d, notSentenceEnds); this.fullLength=d.join('').length; var maxChars=getValueOf('popupMaxPreviewCharacters') + this.extraCharacters; var n=this.maxSentences; var dd=this.firstSentences(d,n); do { dd=this.firstSentences(d,n); --n; } while ( dd.length > this.maxCharacters && n != 0 ); this.data = dd; }; /** @private */ Previewmaker.prototype.fixSentenceEnds = function(strs, reg) { // take an array of strings, strs // join strs[i] to strs[i+1] & strs[i+2] if strs[i] matches regex reg var abbrevRe=/\b[a-z][^a-z]*$/i; for (var i=0; ii+2) a[j-2]=strs[j]; } return this.fixSentenceEnds(a,reg); } // BUGGY STUFF - trying to fix up [[S. C. Johnson & Son]] preview if (false && abbrevRe.test(strs[i])) { var j=i, buf=''; do { buf=buf+strs[i]+strs[i+1]; i=i+2; } while (ihtml field. @private */ Previewmaker.prototype.makePreview = function() { if (this.owner.article.namespaceId()!=pg.nsTemplateId && this.owner.article.namespaceId()!=pg.nsImageId ) { this.killComments(); this.killDivs(); this.killGalleries(); this.killBoxTemplates(); if (getValueOf('popupPreviewKillTemplates')) { this.killTemplates(); } else { this.killMultilineTemplates(); } this.killTables(); this.killImages(); this.killHTML(); this.killChunks(); this.mopup(); this.firstBit(); this.killBadWhitespace(); } else { this.killHTML(); } this.html=wiki2html(this.data, this.baseUrl); // needs livepreview this.fixHTML(); this.stripLongTemplates(); }; /** @private */ Previewmaker.prototype.esWiki2HtmlPart = function(data) { var reLinks = /(?:\[\[([^|\]]*)(?:\|([^|\]]*))*]]([a-z]*))/gi; //match a wikilink reLinks.lastIndex = 0; //reset regex var match; var result = ""; var postfixIndex = 0; while ((match = reLinks.exec(data)) != null) //match all wikilinks { //FIXME: the way that link is built here isn't perfect. It is clickable, but popups preview won't recognize it in some cases. result += pg.escapeQuotesHTML(data.substring(postfixIndex, match.index)) + ''+pg.escapeQuotesHTML((match[2]?match[2]:match[1])+match[3])+""; postfixIndex = reLinks.lastIndex; } //append the rest result += pg.escapeQuotesHTML(data.substring(postfixIndex)); return result; }; Previewmaker.prototype.editSummaryPreview=function() { var reAes = /\/\* *(.*?) *\*\//g; //match the first section marker reAes.lastIndex = 0; //reset regex var match; match = reAes.exec(this.data); if (match) { //we have a section link. Split it, process it, combine it. var prefix = this.data.substring(0,match.index-1); var section = match[1]; var postfix = this.data.substring(reAes.lastIndex); var start = ""; var end = ""; if (prefix.length>0) start = this.esWiki2HtmlPart(prefix) + " " + start + "- "; if (postfix.length>0) end = ": " + end + this.esWiki2HtmlPart(postfix); var t=new Title().fromURL(this.baseUrl); t.anchorFromUtf(section); var sectionLink = Insta.conf.paths.articles + pg.escapeQuotesHTML(t.toString(true)) + '#' + pg.escapeQuotesHTML(t.anchor); return start + ' '+pg.escapeQuotesHTML(section) + end; } //else there's no section link, htmlify the whole thing. return this.esWiki2HtmlPart(this.data); }; // /** Test function for debugging preview problems one step at a time. */ function previewSteps(txt) { try { txt=txt || document.editform.wpTextbox1.value; } catch (err) { if (pg.cache.pages.length > 0) { txt=pg.cache.pages[pg.cache.pages.length-1].data; } else { alert('provide text or use an edit page'); } } txt=txt.substring(0,10000); var base=pg.wiki.articlebase + Title.fromURL(document.location.href).urlString(); var p=new Previewmaker(txt, base, pg.current.link.navpopup); if (this.owner.article.namespaceId() != pg.nsTemplateId) { p.killComments(); if (!confirm('done killComments(). Continue?\n---\n' + p.data)) { return; } p.killDivs(); if (!confirm('done killDivs(). Continue?\n---\n' + p.data)) { return; } p.killGalleries(); if (!confirm('done killGalleries(). Continue?\n---\n' + p.data)) { return; } p.killBoxTemplates(); if (!confirm('done killBoxTemplates(). Continue?\n---\n' + p.data)) { return; } if (getValueOf('popupPreviewKillTemplates')) { p.killTemplates(); if (!confirm('done killTemplates(). Continue?\n---\n' + p.data)) { return; } } else { p.killMultilineTemplates(); if (!confirm('done killMultilineTemplates(). Continue?\n---\n' + p.data)) { return; } } p.killTables(); if (!confirm('done killTables(). Continue?\n---\n' + p.data)) { return; } p.killImages(); if (!confirm('done killImages(). Continue?\n---\n' + p.data)) { return; } p.killHTML(); if (!confirm('done killHTML(). Continue?\n---\n' + p.data)) { return; } p.killChunks(); if (!confirm('done killChunks(). Continue?\n---\n' + p.data)) { return; } p.mopup(); if (!confirm('done mopup(). Continue?\n---\n' + p.data)) { return; } p.firstBit(); if (!confirm('done firstBit(). Continue?\n---\n' + p.data)) { return; } p.killBadWhitespace(); if (!confirm('done killBadWhitespace(). Continue?\n---\n' + p.data)) { return; } } p.html=wiki2html(p.data, base); // needs livepreview p.fixHTML(); if (!confirm('done fixHTML(). Continue?\n---\n' + p.html)) { return; } p.stripLongTemplates(); if (!confirm('done stripLongTemplates(). Continue?\n---\n' + p.html)) { return; } alert('finished preview - end result follows.\n---\n' + p.html); } // /** Works around livepreview bugs. @private */ Previewmaker.prototype.fixHTML = function() { if(!this.html) return; var ret = this.html; // fix question marks in wiki links // maybe this'll break some stuff :-( ret=ret.replace(RegExp('\(', 'popupPrePreviewSep', this.owner.idNumber); setPopupTipsAndHTML(this.html, 'popupPreview', this.owner.idNumber, { owner: this.owner }); var more = (this.fullLength > this.data.length) ? this.moreLink() : ''; setPopupHTML(more, 'popupPreviewMore', this.owner.idNumber); }; /** @private */ Previewmaker.prototype.moreLink=function() { var a=document.createElement('a'); a.className='popupMoreLink'; a.innerHTML=popupString('more...'); var savedThis=this; a.onclick=function() { savedThis.maxCharacters+=2000; savedThis.maxSentences+=20; savedThis.setData(); savedThis.showPreview(); } return a; } /** @private */ Previewmaker.prototype.stripLongTemplates = function() { // operates on the HTML! this.html=this.html.replace(RegExp('^.{0,1000}[{][{][^}]*?(<(p|br)( /)?>\\s*){2,}([^{}]*?[}][}])?', 'gi'), ''); this.html=this.html.split('\n').join(' '); // workaround for
     templates
    	this.html=this.html.replace(RegExp('[{][{][^}]*
    [^}]*[}][}]','gi'), '');
    };
    /**
       @private
    */
    Previewmaker.prototype.killMultilineTemplates = function() {
    	this.kill('{{{', '}}}');
    	this.kill(RegExp('\\s*[{][{][^{}]*\\n'), '}}', '{{');
    };
    // ENDFILE: previewmaker.js
    // STARTFILE: querypreview.js
    function loadAPIPreview(queryType, article, navpop) {
    	var art=new Title(article).urlString();
    	var url=pg.wiki.apiwikibase + '?format=json&action=query&';
    	var htmlGenerator=function(a,d){alert('invalid html generator');};
    	switch (queryType) {
    	case 'history':
    		url += 'meta=userinfo&uiprop=options&titles=' + art + '&prop=revisions&rvlimit=' +
    			getValueOf('popupHistoryPreviewLimit');
    		htmlGenerator=APIhistoryPreviewHTML;
    		break;
    	case 'category':
    		url += 'list=categorymembers&cmtitle=' + art;
    		htmlGenerator=APIcategoryPreviewHTML;
    		break;
    	case 'userinfo':
    	  var username = new Title( article ).userName();
    		var usernameart = encodeURIComponent( username );
    		if (pg.re.ipUser.test(username)) {
    			url += 'list=blocks&bkprop=range&bkip=' + usernameart;
    		} else {
    			url += 'list=users&usprop=blockinfo|groups|editcount|registration&ususers=' + usernameart + "&meta=globaluserinfo&guiprop=groups|unattached&guiuser="+ usernameart;
    		}
    		htmlGenerator=APIuserInfoPreviewHTML;
    		break;
    	case 'contribs':
    		var usernameart = encodeURIComponent( new Title( article ).userName() );
    		url += 'list=usercontribs&meta=userinfo&uiprop=options&ucuser=' + usernameart +
    			'&uclimit=' + getValueOf('popupContribsPreviewLimit');
    		htmlGenerator=APIcontribsPreviewHTML;
    		break;
    	case 'imagepagepreview':
    		var trail='';
    		if (getValueOf('popupImageLinks')) { trail = '&list=imageusage&iutitle=' + art; }
    		url += 'titles=' + art + '&prop=revisions|imageinfo&rvprop=content' + trail;
    		htmlGenerator=APIimagepagePreviewHTML;
    		break;
    	case 'backlinks':
    		url += 'list=backlinks&bltitle=' + art;
    		htmlGenerator=APIbacklinksPreviewHTML;
    		break;
    	}
    	pendingNavpopTask(navpop);
    	if( !mw.config.get('wgEnableAPI') ) {
    		/* The API is not available */
    		htmlGenerator=function(a,d){
    			return 'This function of navigation popups now requires a MediaWiki ' + 
    			'installation with the API enabled.'; };
    	}
    	var callback=function(d){
    		log( "callback of API functions was hit" );
    		showAPIPreview(queryType, htmlGenerator(article,d,navpop), navpop.idNumber, navpop, d);
    	};
    	if (pg.flag.isIE) {
    		url = url + '&*'; //to circumvent https://bugzilla.wikimedia.org/show_bug.cgi?id=28840
    	}
    	var go = function(){
    		getPageWithCaching(url, callback, navpop);
    		return true;
    	}
    	if (navpop.visible || !getValueOf('popupLazyDownloads')) { go(); }
    	else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_'+queryType+'_QUERY_DATA'); }
    }
    
    function linkList(list) {
    	list.sort(function(x,y) { return (x==y ? 0 : (x -1 ) {
    			// New format
    			return parseInt(tz.split('|')[1],10);
    		} else if ( tz.indexOf(':') > -1 ) {
    			// Old format
    			return( parseInt(tz,10)*60 + parseInt(tz.split(':')[1],10) );
    		}
    	}
    	return 0;
    }
    
    function editPreviewTable(article, h, reallyContribs, timeOffset) {
    	var html=[''];
    	var day=null;
    	var curart=article;
    	for (var i=0; im ';
    		var editDate=adjustDate(getDateFromTimestamp(h[i].timestamp), timeOffset);
    		var thisDay = dayFormat(editDate);
    		var thisTime = timeFormat(editDate);
    		if (thisDay==day) { thisDay=''; }
    		else { day=thisDay; }
    		if (thisDay) {
    			html.push( '' );
    		}
    		html.push('');
    		html.push('');
    		html.push('');
    		var col3url='', col3txt='';
    		if (!reallyContribs) {
    			var user=h[i]['user'];
    			if( typeof h[i]['userhidden'] == "undefined" ) {
    				if( pg.re.ipUser.test(user) ) {
    					col3url=pg.wiki.titlebase + mw.config.get('wgFormattedNamespaces')[pg.nsSpecialId] + ':Contributions&target=' + new Title(user).urlString();
    				} else {
    					col3url=pg.wiki.titlebase + mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + ':' + new Title(user).urlString();
    				}
    				col3txt=pg.escapeQuotesHTML(user);
    			} else {
    				col3url=getValueOf('popupRevDelUrl');
    				col3txt=pg.escapeQuotesHTML( popupString('revdel'));
    			}
    		} else {
    			col3url=pg.wiki.titlebase + curart.urlString();
    			col3txt=pg.escapeQuotesHTML(page);
    		}
    		html.push('');
    		var comment='';
    		var c=h[i].comment || h[i]['*'];
    		if (c) {
    			comment=new Previewmaker(c, new Title(curart).toUrl()).editSummaryPreview();
    		} else if (typeof h[i]['commenthidden'] != "undefined" ) {
    			comment=popupString('revdel');
    		}
    		html.push('');
    		html.push('');
    		html=[html.join('')];
    	}
    	html.push('
    ' + thisDay+'
    '); return html.join(''); } function getDateFromTimestamp(t) { var s=t.split(/[^0-9]/); switch(s.length) { case 0: return null; case 1: return new Date(s[0]); case 2: return new Date(s[0], s[1]-1); case 3: return new Date(s[0], s[1]-1, s[2]); case 4: return new Date(s[0], s[1]-1, s[2], s[3]); case 5: return new Date(s[0], s[1]-1, s[2], s[3], s[4]); case 6: return new Date(s[0], s[1]-1, s[2], s[3], s[4], s[5]); default: return new Date(s[0], s[1]-1, s[2], s[3], s[4], s[5], s[6]); } } function adjustDate(d, offset) { // offset is in minutes var o=offset * 60 * 1000; return new Date( +d + o); } function dayFormat(editDate, utc) { if (utc) { return map(zeroFill, [editDate.getUTCFullYear(), editDate.getUTCMonth()+1, editDate.getUTCDate()]).join('-'); } return map(zeroFill, [editDate.getFullYear(), editDate.getMonth()+1, editDate.getDate()]).join('-'); } function timeFormat(editDate, utc) { if (utc) { return map(zeroFill, [editDate.getUTCHours(), editDate.getUTCMinutes(), editDate.getUTCSeconds()]).join(':'); } return map(zeroFill, [editDate.getHours(), editDate.getMinutes(), editDate.getSeconds()]).join(':'); } function showAPIPreview(queryType, html, id, navpop, download) { // DJ: done var target='popupPreview'; switch (queryType) { case 'imagelinks': case 'category': case 'userinfo': target='popupPostPreview'; break; } setPopupTipsAndHTML(html, target, id); completedNavpopTask(navpop); } function APIbacklinksPreviewHTML(article, download, navpop) { try { var jsObj=getJsObj(download.data); var list=jsObj.query.backlinks; } catch (someError) { return 'backlinksPreviewHTML went wonky'; } var html=[]; if (!list) { return popupString('No backlinks found'); } for ( var i=0; i < list.length; i++ ) { var t=new Title(list[i]['title']); html.push('' + t + ''); } html=html.join(', '); if (jsObj['query-continue'] && jsObj['query-continue'].backlinks && jsObj['query-continue'].backlinks.blcontinue) { html += popupString(' and more'); } return html; } function APIsharedImagePagePreviewHTML(obj) { log( "APIsharedImagePagePreviewHTML" ); var popupid = obj['requestid']; if( obj['query'] && obj['query']['pages'] ) { var page=anyChild(obj['query']['pages']); var content=(page && page.revisions ) ? page.revisions[0]['*'] : null; if( content ) { /* Not entirely safe, but the best we can do */ var p=new Previewmaker(content, pg.current.link.navpopup.article, pg.current.link.navpopup); p.makePreview(); setPopupHTML( p.html, "popupSecondPreview", popupid ); } } } function APIimagepagePreviewHTML(article, download, navpop) { try { var jsObj=getJsObj(download.data); var page=anyChild(jsObj.query.pages); var content=(page && page.revisions ) ? page.revisions[0]['*'] : null; } catch (someError) { return 'API imagepage preview failed :('; } var ret=''; var alt=''; try{alt=navpop.parentAnchor.childNodes[0].alt;} catch(e){} if (alt) { ret = ret + '
    ' + popupString('Alt text:') + ' ' + pg.escapeQuotesHTML(alt); } if (content) { var p=prepPreviewmaker(content, article, navpop); p.makePreview(); if (p.html) { ret += '
    ' + p.html; } } if (content!==null && getValueOf('popupSummaryData')) { var info=getPageInfo(content, download); log(info); setPopupTrailer(info, navpop.idNumber); } if (page && page.imagerepository == "shared" ) { var art=new Title(article); var encart = encodeURIComponent( "File:" + art.stripNamespace() ); var shared_url = pg.wiki.apicommonsbase + '?format=json&callback=APIsharedImagePagePreviewHTML' + '&requestid=' + navpop.idNumber + '&action=query&prop=revisions&rvprop=content&titles=' + encart; if (pg.flag.isIE) { shared_url = shared_url + '&*'; //to circumvent https://bugzilla.wikimedia.org/show_bug.cgi?id=28840 } ret = ret +'
    ' + popupString( 'Image from Commons') + ': ' + popupString( 'Description page') + ''; mw.loader.load( shared_url ); } showAPIPreview('imagelinks', APIimagelinksPreviewHTML(article,download), navpop.idNumber, download); return ret; } function APIimagelinksPreviewHTML(article, download) { try { var jsobj=getJsObj(download.data); var list=jsobj.query.imageusage; if (!list) { return popupString('No image links found'); } } catch(someError) { return 'Image links preview generation failed :('; } var ret=[]; for (var i=0; i < list.length; i++) { ret.push(list[i]['title']); } if (ret.length === 0) { return popupString('No image links found'); } return '

    ' + popupString('File links') + '

    ' + linkList(ret); } function APIcategoryPreviewHTML(article, download) { try{ var jsobj=getJsObj(download.data); var list=jsobj.query.categorymembers; } catch(someError) { return 'Category preview failed :('; } var ret=[]; for (var p=0; p < list.length; p++) { ret.push(list[p]['title']); } if (ret.length === 0) { return popupString('Empty category'); } ret = '

    ' + tprintf('Category members (%s shown)', [ret.length]) + '

    ' +linkList(ret); if (jsobj['query-continue'] && jsobj['query-continue'].categorymembers && jsobj['query-continue'].categorymembers.cmcontinue) { ret += popupString(' and more'); } return ret; } function APIuserInfoPreviewHTML(article, download) { var ret=[]; try{ var queryobj=getJsObj(download.data).query; } catch(someError) { return 'Userinfo preview failed :('; } var user=anyChild(queryobj.users); if (user) { var globaluserinfo=queryobj.globaluserinfo; if (user.invalid == '') { ret.push( popupString( 'Invalid user') ); } else if (user.missing == '') { ret.push( popupString( 'Not a registered username') ); } if( user.blockedby ) ret.push('' + popupString('BLOCKED') + ''); if( globaluserinfo && (globaluserinfo.locked != null || globaluserinfo.hidden != null) ) { var lockedSulAccountIsAttachedToThis = true; for( var i=0; globaluserinfo.unattached && i < globaluserinfo.unattached.length; i++) { if ( globaluserinfo.unattached[i].wiki===mw.config.get('wgDBname') ) { lockedSulAccountIsAttachedToThis=false; break; } } if (lockedSulAccountIsAttachedToThis) { if (globaluserinfo.locked != null) ret.push('' + popupString('LOCKED') + ''); if (globaluserinfo.hidden != null) ret.push('' + popupString('HIDDEN') + ''); } } for( var i=0; (user.groups && i < user.groups.length); i++) { switch (user.groups[i]) { case '*': case 'user': case 'autoconfirmed': break; default: ret.push( pg.escapeQuotesHTML(user.groups[i]) ); } } for( var i=0; (globaluserinfo && globaluserinfo.groups && i < globaluserinfo.groups.length); i++) { ret.push( ''+pg.escapeQuotesHTML(globaluserinfo.groups[i])+'' ); } if( user.editcount || user.registration ) ret.push( pg.escapeQuotesHTML((user.editcount?user.editcount:'') + popupString(' edits since: ') + (user.registration?dayFormat(getDateFromTimestamp(user.registration)):'')) ); } if (queryobj.blocks) { ret.push( popupString( 'IP user') ); //we only request list=blocks for IPs for (var i=0; i' + popupString(queryobj.blocks[i].rangestart===queryobj.blocks[i].rangeend ? 'BLOCKED' : 'RANGEBLOCKED') + '
    ' ); } } ret = '
    ' + ret.join( ', ' ); return ret; } function APIcontribsPreviewHTML(article, download, navpop) { return APIhistoryPreviewHTML(article, download, navpop, true); } function APIhistoryPreviewHTML(article, download, navpop, reallyContribs) { try { var jsobj=getJsObj(download.data); var tz=jsobj.query.userinfo.options.timecorrection; if( reallyContribs ) var edits=jsobj.query.usercontribs; else var edits=anyChild(jsobj.query.pages)['revisions']; } catch (someError) { return 'History preview failed :-('; } var timeOffset = getTimeOffset(tz); Cookie.create('popTz', timeOffset, 1); var ret=editPreviewTable(article, edits, reallyContribs, timeOffset); return ret; } // // ENDFILE: querypreview.js // STARTFILE: debug.js //////////////////////////////////////////////////////////////////// // Debugging functions //////////////////////////////////////////////////////////////////// function log(){}; // dummy to stop errors function setupDebugging() { // if (window.popupDebug) { // popupDebug is set from .version window.log=function(x) { //if(gMsg!='')gMsg += '\n'; gMsg+=time() + ' ' + x; }; window.console.log(x); } window.errlog=function(x) { window.console.error(x); } log('Initializing logger'); } else { // window.log = function(x) {}; window.errlog = function(x) {}; // } // } // ENDFILE: debug.js // STARTFILE: images.js // load image of type Title. function loadImage(image, navpop) { if (typeof image.stripNamespace != 'function') { alert('loadImages bad'); } // API call to retrieve image info. if ( !getValueOf('popupImages') || !mw.config.get('wgEnableAPI') ) return; if ( !isValidImageName(image) ) return false; var art=image.urlString(); var url=pg.wiki.apiwikibase + '?format=json&action=query'; url += '&prop=imageinfo&iiprop=url|mime&iiurlwidth=' + getValueOf('popupImageSizeLarge');; url += '&titles=' + art; if (pg.flag.isIE) { url = url + '&*'; //to circumvent https://bugzilla.wikimedia.org/show_bug.cgi?id=28840 } pendingNavpopTask(navpop); var callback=function(d){ popupsInsertImage(navpop.idNumber, navpop, d); }; var go = function(){ getPageWithCaching(url, callback, navpop); return true; } if (navpop.visible || !getValueOf('popupLazyDownloads')) { go(); } else { navpop.addHook(go, 'unhide', 'after', 'DOWNLOAD_IMAGE_QUERY_DATA'); } } function popupsInsertImage(id, navpop, download) { log( "popupsInsertImage"); try { var jsObj=getJsObj(download.data); var imagepage=anyChild(jsObj.query.pages); if (typeof imagepage.imageinfo === 'undefined') return; var imageinfo = imagepage.imageinfo[0]; } catch (someError) { log( "popupsInsertImage failed :(" ); return; } var popupImage = document.getElementById("popupImg"+id); if (!popupImage) { log( "could not find insertion point for image"); return; } popupImage.width=getValueOf('popupImageSize'); popupImage.style.display='inline'; // Set the source for the image. if( imageinfo.thumburl ) popupImage.src=imageinfo.thumburl; else if( imageinfo.mime.indexOf("image") == 0 ){ popupImage.src=imageinfo.url; log( "a thumb could not be found, using original image" ); } else log( "fullsize imagethumb, but not sure if it's an image"); var a=document.getElementById("popupImageLink"+id); if (a === null) { return null; } // Determine the action of the surrouding imagelink. switch (getValueOf('popupThumbAction')) { case 'imagepage': if (pg.current.article.namespaceId()!=pg.nsImageId) { a.href=imageinfo.descriptionurl; // FIXME: unreliable pg.idNumber popTipsSoonFn('popupImage' + id)(); break; } // else fall through case 'sizetoggle': a.onclick=toggleSize; a.title=popupString('Toggle image size'); return; case 'linkfull': a.href = imageinfo.url; a.title=popupString('Open full-size image'); return; } } // Toggles the image between inline small and navpop fullwidth. // It's the same image, no actual sizechange occurs, only display width. function toggleSize() { var imgContainer=this; if (!imgContainer) { alert('imgContainer is null :/'); return;} img=imgContainer.firstChild; if (!img) { alert('img is null :/'); return;} if (!img.style.width || img.style.width=='') { img.style.width='100%'; } else { img.style.width=''; } } // Returns one title of an image from wikiText. function getValidImageFromWikiText(wikiText) { // nb in pg.re.image we're interested in the second bracketed expression // this may change if the regex changes :-( //var match=pg.re.image.exec(wikiText); var matched=null; var match; // strip html comments, used by evil bots :-( var t = removeMatchesUnless(wikiText, RegExp('()'), 1, RegExp('^'; } if ( !ret[ src[i] ] ) { ret[ src[i] ] = []; } try { ret[ src[i] ].push( i ); } catch (err) { diffBugAlert(src[i]); } } return ret; } function diff( o, n ) { // pass 1: make hashtable ns with new rows as keys var ns = makeDiffHashtable(n); // pass 2: make hashtable os with old rows as keys var os = makeDiffHashtable(o); // pass 3: pair unique new rows and matching unique old rows var i; for ( i in ns ) { if ( ns[i].length == 1 && os[i] && os[i].length == 1 ) { n[ ns[i][0] ] = { text: n[ ns[i][0] ], row: os[i][0], paired: true }; o[ os[i][0] ] = { text: o[ os[i][0] ], row: ns[i][0], paired: true }; } } // pass 4: pair matching rows immediately following paired rows (not necessarily unique) for ( i = 0; i < n.length - 1; i++ ) { if ( n[i].paired && ! n[i+1].paired && n[i].row + 1 < o.length && ! o[ n[i].row + 1 ].paired && n[i+1] == o[ n[i].row + 1 ] ) { n[i+1] = { text: n[i+1], row: n[i].row + 1, paired: true }; o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1, paired: true }; } } // pass 5: pair matching rows immediately preceding paired rows (not necessarily unique) for ( i = n.length - 1; i > 0; i-- ) { if ( n[i].paired && ! n[i-1].paired && n[i].row > 0 && ! o[ n[i].row - 1 ].paired && n[i-1] == o[ n[i].row - 1 ] ) { n[i-1] = { text: n[i-1], row: n[i].row - 1, paired: true }; o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1, paired: true }; } } return { o: o, n: n }; } // // ENDFILE: diff.js // STARTFILE: init.js function setSiteInfo() { if (window.popupLocalDebug) { pg.wiki.hostname = 'en.wikipedia.org'; } else { pg.wiki.hostname = location.hostname; // use in preference to location.hostname for flexibility (?) } pg.wiki.wikimedia=RegExp('(wiki([pm]edia|source|books|news|quote|versity)|wiktionary|mediawiki)[.]org').test(pg.wiki.hostname); pg.wiki.wikia=RegExp('[.]wikia[.]com$', 'i').test(pg.wiki.hostname); pg.wiki.isLocal=RegExp('^localhost').test(pg.wiki.hostname); pg.wiki.commons=( pg.wiki.wikimedia && pg.wiki.hostname != 'commons.wikimedia.org') ? 'commons.wikimedia.org' : null; pg.wiki.lang = mw.config.get('wgContentLanguage'); var port = location.port ? ':' + location.port : ''; pg.wiki.sitebase = pg.wiki.hostname + port; } function setTitleBase() { var protocol = ( window.popupLocalDebug ? 'http:' : location.protocol ); pg.wiki.articlePath = mw.config.get('wgArticlePath').replace(/\/\$1/, ""); // as in http://some.thing.com/wiki/Article pg.wiki.botInterfacePath = mw.config.get('wgScript'); pg.wiki.APIPath = mw.config.get('wgScriptPath') +"/api.php"; // default mediawiki setting is paths like http://some.thing.com/articlePath/index.php?title=foo var titletail = pg.wiki.botInterfacePath + '?title='; //var titletail2 = joinPath([pg.wiki.botInterfacePath, 'wiki.phtml?title=']); // other sites may need to add code here to set titletail depending on how their urls work pg.wiki.titlebase = protocol + '//' + pg.wiki.sitebase + titletail; //pg.wiki.titlebase2 = protocol + '//' + joinPath([pg.wiki.sitebase, titletail2]); pg.wiki.wikibase = protocol + '//' + pg.wiki.sitebase + pg.wiki.botInterfacePath; pg.wiki.apiwikibase = protocol + '//' + pg.wiki.sitebase + pg.wiki.APIPath; pg.wiki.articlebase = protocol + '//' + pg.wiki.sitebase + pg.wiki.articlePath; pg.wiki.commonsbase = protocol + '//' + pg.wiki.commons + pg.wiki.botInterfacePath; pg.wiki.apicommonsbase = protocol + '//' + pg.wiki.commons + pg.wiki.APIPath; pg.re.basenames = RegExp( '^(' + map( literalizeRegex, [ pg.wiki.titlebase, //pg.wiki.titlebase2, pg.wiki.articlebase ]).join('|') + ')' ); } ////////////////////////////////////////////////// // Global regexps function setMainRegex() { var reStart='[^:]*://'; var preTitles = literalizeRegex( mw.config.get('wgScriptPath') ) + '/(?:index[.]php|wiki[.]phtml)[?]title='; preTitles += '|' + literalizeRegex( pg.wiki.articlePath + '/' ); var reEnd='(' + preTitles + ')([^&?#]*)[^#]*(?:#(.+))?'; pg.re.main = RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd); } function setRegexps() { setMainRegex(); var sp=nsRe(pg.nsSpecialId); pg.re.urlNoPopup=RegExp('((title=|/)' + sp + '(?:%3A|:)|section=[0-9]|^#$)') ; pg.re.contribs =RegExp('(title=|/)' + sp + '(?:%3A|:)Contributions' + '(&target=|/|/' + mw.config.get('wgFormattedNamespaces')[pg.nsUserId]+':)(.*)') ; pg.re.email =RegExp('(title=|/)' + sp + '(?:%3A|:)EmailUser' + '(&target=|/|/(?:' + mw.config.get('wgFormattedNamespaces')[pg.nsUserId]+':)?)(.*)') ; pg.re.backlinks =RegExp('(title=|/)' + sp + '(?:%3A|:)WhatLinksHere' + '(&target=|/)([^&]*)'); pg.re.specialdiff=RegExp('/' + sp + '(?:%3A|:)Diff/([^?#]*)'); // var im=nsReImage(); // note: tries to get images in infobox templates too, e.g. movie pages, album pages etc // (^|\[\[)image: *([^|\]]*[^|\] ]) * // (^|\[\[)image: *([^|\]]*[^|\] ])([^0-9\]]*([0-9]+) *px)? // $4 = 120 as in 120px pg.re.image = RegExp('(^|\\[\\[)' + im + ': *([^|\\]]*[^|\\] ])' + '([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *' + '(' + getValueOf('popupImageVarsRegexp') + ')' + ' *= *(?:\\[\\[ *)?(?:' + im + ':)?' + '([^|]*?)(?:\\]\\])? *[|]? *\\n', 'img') ; pg.re.imageBracketCount = 6; pg.re.category = RegExp('\\[\\[' +nsRe(pg.nsCategoryId) + ': *([^|\\]]*[^|\\] ]) *', 'i'); pg.re.categoryBracketCount = 1; pg.re.ipUser=RegExp('^' + // IPv6 '(?::(?::|(?::[0-9A-Fa-f]{1,4}){1,7})|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){0,6}::|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){7})' + // IPv4 '|(((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}' + '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))$'); pg.re.stub= RegExp(getValueOf('popupStubRegexp'), 'im'); pg.re.disambig=RegExp(getValueOf('popupDabRegexp'), 'im'); // // FIXME replace with general parameter parsing function, this is daft pg.re.oldid=RegExp('[?&]oldid=([^&]*)'); pg.re.diff=RegExp('[?&]diff=([^&]*)'); } ////////////////////////////////////////////////// // miscellany function setupCache() { // page caching pg.cache.pages = []; } function setMisc() { pg.current.link=null; pg.current.links=[]; pg.current.linksHash={}; setupCache(); pg.timer.checkPopupPosition=null; pg.counter.loop=0; // ids change with each popup: popupImage0, popupImage1 etc pg.idNumber=0; // for myDecodeURI pg.misc.decodeExtras = [ {from: '%2C', to: ',' }, {from: '_', to: ' ' }, {from: '%24', to: '$'}, {from: '%26', to: '&' } // no , ]; } function leadingInteger(s){ var n=s.match(/^(\d*)/)[1]; if (n) { return +n; } return null; } function setBrowserHacks() { var useOriginal=false; // browser-specific hacks if (typeof window.opera != 'undefined') { //if (leadingInteger(opera.version()) < 9) { useOriginal=true; } // v9 beta still seems to have buggy css setDefault('popupNavLinkSeparator', ' · '); } else if (navigator.appName=='Konqueror') { setDefault('popupNavLinkSeparator', ' • '); pg.flag.isKonq=true; } else if ( navigator.vendor && navigator.vendor.toLowerCase().indexOf('apple computer')===0) { pg.flag.isSafari=true; var webkit=+navigator.userAgent.replace(RegExp('^.*AppleWebKit[/](\\d+).*', 'i'), '$1'); if (webkit < 420) { useOriginal=true; } } else if (navigator.appName.indexOf("Microsoft")!=-1) { setDefault('popupNavLinkSeparator', ' · '); var ver=+navigator.userAgent.replace(RegExp('^.*MSIE (\\d+).*'), '$1'); pg.flag.isIE=true; pg.flag.IEVersion=ver; } if (pg.flag.isIE && pg.flag.IEVersion < 8) { useOriginal=true; } if ((pg.flag.isIE && pg.flag.IEVersion < 7) || pg.flag.isKonq || (pg.flag.isSafari && webkit < 420)) { pg.flag.linksLikeIE6=true; } if (useOriginal && pg.structures.original) { setDefault('popupStructure','original'); } } // We need a callback since this might end up asynchronous because of // the mw.loader.using() call. function setupPopups( callback ) { mw.loader.using( 'mediawiki.user', function() { // NB translatable strings should be set up first (strings.js) // basics setupDebugging(); setSiteInfo(); setTitleBase(); setOptions(); // see options.js // namespaces etc setNamespaces(); setInterwiki(); // regexps setRegexps(); setRedirs(); // other stuff setBrowserHacks(); setMisc(); setupLivePreview(); // main deal here setupTooltips(); Navpopup.tracker.enable(); setupPopups.completed = true; if ( $.isFunction( callback ) ) { callback(); } }); } // ENDFILE: init.js // STARTFILE: navlinks.js // ////////////////////////////////////////////////// // navlinks... let the fun begin // function defaultNavlinkSpec() { var str=''; str += '<>'; if (getValueOf('popupLastEditLink')) { str += '*<>|<>|<>if(oldid){|<>|<>}'; } // user links // contribs - log - count - email - block // count only if applicable; block only if popupAdminLinks str += 'if(user){
    <>*<>'; str+='if(ipuser){*<>}if(wikimedia){*<>}'; str+='if(ipuser){}else{*<>}if(admin){*<>|<>}}'; // editing links // talkpage -> edit|new - history - un|watch - article|edit // other page -> edit - history - un|watch - talk|edit|new var editstr='<>'; var editOldidStr='if(oldid){<>|<>|<>}else{' + editstr + '}' var historystr='<>if(mainspace_en){|<>}'; var watchstr='<>|<>'; str+='
    if(talk){' + editOldidStr+'|<>' + '*' + historystr+'*'+watchstr + '*' + '<>|<>' + '}else{' + // not a talk page editOldidStr + '*' + historystr + '*' + watchstr + '*' + '<>|<>|<>' + '}'; // misc links str += '
    <>*<>*<>'; // admin links str += 'if(admin){
    <>|<>|<>*' + '<>|<>|<>}'; return str; } function navLinksHTML (article, hint, params) { //oldid, rcid) { var str = '' + defaultNavlinkSpec() + ''; // BAM return navlinkStringToHTML(str, article, params); } function expandConditionalNavlinkString(s,article,z,recursionCount) { var oldid=z.oldid, rcid=z.rcid, diff=z.diff; // nested conditionals (up to 10 deep) are ok, hopefully! (work from the inside out) if (typeof recursionCount!=typeof 0) { recursionCount=0; } var conditionalSplitRegex=RegExp( //(1 if \\( (2 2) \\) {(3 3)} (4 else {(5 5)} 4)1) '(;?\\s*if\\s*\\(\\s*([\\w]*)\\s*\\)\\s*\\{([^{}]*)\\}(\\s*else\\s*\\{([^{}]*?)\\}|))', 'i'); var splitted=s.parenSplit(conditionalSplitRegex); // $1: whole conditional // $2: test condition // $3: true expansion // $4: else clause (possibly empty) // $5: false expansion (possibly null) var numParens=5; var ret = splitted[0]; for (var i=1; i>')); var ret=[]; for (var i=0; i1) { t[sss[0]]=sss[1]; } else { // no assignment (no "="), so treat this as a title (overwriting the last one) t.text=popupString(sss[0]); } } t.article=article; var oldid=params.oldid, rcid=params.rcid, diff=params.diff; if (typeof oldid != 'undefined' && oldid != null) { t.oldid=oldid; } if (typeof rcid != 'undefined' && rcid != null) { t.rcid=rcid; } if (typeof diff != 'undefined' && diff != null) { t.diff=diff; } if (!t.text && t.id != 'mainlink') { t.text=popupString(t.id); } ret.push(t); } else { // plain HTML ret.push(splitted[i]); } } return ret; } function navlinkSubstituteHTML(s) { return s.split('*').join(getValueOf('popupNavLinkSeparator')) .split('').join('') .split('').join('').join(''); } function navlinkDepth(magic,s) { return s.split('<' + magic + '>').length - s.split('').length; } // navlinkString: * becomes the separator // <> becomes a foo-link with attribute bar='baz' // and visible text 'fubar' // if(test){...} and if(test){...}else{...} work too (nested ok) function navlinkStringToHTML(s,article,params) { //limitAlert(navlinkStringToHTML, 5, 'navlinkStringToHTML\n' + article + '\n' + (typeof article)); var p=navlinkStringToArray(s,article,params); var html=''; var menudepth = 0; // nested menus not currently allowed, but doesn't do any harm to code for it var menurowdepth = 0; var wrapping = null; for (var i=0; i 0 && menurowdepth === 0) { html += ''; } else { html+=p[i].html(); } } } return html; } function navlinkTag() { this.type='navlinkTag'; } navlinkTag.prototype.html=function () { this.getNewWin(); this.getPrintFunction(); var html=''; var opening, closing; var tagType='span'; if (!tagType) { opening = ''; closing = ''; } else { opening = '<' + tagType + ' class="popup_' + this.id + '">'; closing = ''; } if (typeof this.print!='function') { errlog ('Oh dear - invalid print function for a navlinkTag, id='+this.id); } else { html=this.print(this); if (typeof html != typeof '') {html='';} else if (typeof this.shortcut!='undefined') html=addPopupShortcut(html, this.shortcut); } return opening + html + closing; }; navlinkTag.prototype.getNewWin=function() { getValueOf('popupLinksNewWindow'); if (typeof pg.option.popupLinksNewWindow[this.id] === 'undefined') { this.newWin=null; } this.newWin=pg.option.popupLinksNewWindow[this.id]; } navlinkTag.prototype.getPrintFunction=function() { //think about this some more // this.id and this.article should already be defined if (typeof this.id!=typeof '' || typeof this.article!=typeof {} ) { return; } var html=''; var a,t; this.noPopup=1; switch (this.id) { case 'contribs': case 'history': case 'whatLinksHere': case 'userPage': case 'monobook': case 'userTalk': case 'talk': case 'article': case 'lastEdit': this.noPopup=null; } switch (this.id) { case 'email': case 'contribs': case 'block': case 'unblock': case 'userlog': case 'userSpace': case 'deletedContribs': this.article=this.article.userName(); } switch (this.id) { case 'userTalk': case 'newUserTalk': case 'editUserTalk': case 'userPage': case 'monobook': case 'editMonobook': case 'blocklog': this.article=this.article.userName(true); // fall through; no break case 'pagelog': case 'deletelog': case 'protectlog': delete this.oldid; } if (this.id=='editMonobook' || this.id=='monobook') { this.article.append('/monobook.js'); } if (this.id != 'mainlink') { // FIXME anchor handling should be done differently with Title object this.article=this.article.removeAnchor(); // if (typeof this.text=='undefined') this.text=popupString(this.id); } switch (this.id) { case 'undelete': this.print=specialLink; this.specialpage='Undelete'; this.sep='/'; break; case 'whatLinksHere': this.print=specialLink; this.specialpage='Whatlinkshere'; break; case 'relatedChanges': this.print=specialLink; this.specialpage='Recentchangeslinked'; break; case 'move': this.print=specialLink; this.specialpage='Movepage'; break; case 'contribs': this.print=specialLink; this.specialpage='Contributions'; break; case 'deletedContribs':this.print=specialLink; this.specialpage='Deletedcontributions'; break; case 'email': this.print=specialLink; this.specialpage='EmailUser'; this.sep='/'; break; case 'block': this.print=specialLink; this.specialpage='Blockip'; this.sep='&ip='; break; case 'unblock': this.print=specialLink; this.specialpage='Ipblocklist'; this.sep='&action=unblock&ip='; break; case 'userlog': this.print=specialLink; this.specialpage='Log'; this.sep='&user='; break; case 'blocklog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=block&page='; break; case 'pagelog': this.print=specialLink; this.specialpage='Log'; this.sep='&page='; break; case 'protectlog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=protect&page='; break; case 'deletelog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=delete&page='; break; case 'userSpace': this.print=specialLink; this.specialpage='PrefixIndex'; this.sep='&namespace=2&prefix='; break; case 'search': this.print=specialLink; this.specialpage='Search'; this.sep='&fulltext=Search&search='; break; case 'unwatch': case 'watch': this.print=magicWatchLink; this.action=this.id+'&autowatchlist=1&autoimpl=' + popupString('autoedit_version') + '&actoken='+autoClickToken(); break; case 'history': case 'historyfeed': case 'unprotect': case 'protect': this.print=wikiLink; this.action=this.id; break; case 'delete': this.print=wikiLink; this.action='delete'; if (this.article.namespaceId()==pg.nsImageId) { var img=this.article.stripNamespace(); this.action+='&image='+img; } break; case 'markpatrolled': case 'edit': // editOld should keep the oldid, but edit should not. delete this.oldid; // fall through case 'view': case 'purge': case 'render': this.print=wikiLink; this.action=this.id; break; case 'raw': this.print=wikiLink; this.action='raw&ctype=text/css'; break; case 'new': this.print=wikiLink; this.action='edit§ion=new'; break; case 'mainlink': if (typeof this.text=='undefined') { this.text=this.article.toString().entify(); } if (getValueOf('popupSimplifyMainLink') && isInStrippableNamespace(this.article)) { var s=this.text.split('/'); this.text=s[s.length-1]; if (this.text=='' && s.length > 1) { this.text=s[s.length-2]; } } this.print=titledWikiLink; if (typeof this.title=='undefined' && pg.current.link && typeof pg.current.link.href != 'undefined') { this.title=safeDecodeURI((pg.current.link.originalTitle)?pg.current.link.originalTitle:this.article); if (typeof this.oldid != 'undefined' && this.oldid) { this.title=tprintf('Revision %s of %s', [this.oldid, this.title]); } } this.action='view'; break; case 'userPage': case 'article': case 'monobook': case 'editMonobook': case 'editArticle': delete this.oldid; //alert(this.id+'\n'+this.article + '\n'+ typeof this.article); this.article=this.article.articleFromTalkOrArticle(); //alert(this.id+'\n'+this.article + '\n'+ typeof this.article); this.print=wikiLink; if (this.id.indexOf('edit')==0) { this.action='edit'; } else { this.action='view';} break; case 'userTalk': case 'talk': this.article=this.article.talkPage(); delete this.oldid; this.print=wikiLink; this.action='view'; break; case 'arin': this.print=arinLink; break; case 'count': this.print=editCounterLink; break; case 'google': this.print=googleLink; break; case 'editors': this.print=editorListLink; break; case 'globalsearch': this.print=globalSearchLink; break; case 'lastEdit': this.print=titledDiffLink; this.title=popupString('Show the last edit'); this.from='prev'; this.to='cur'; break; case 'oldEdit': this.print=titledDiffLink; this.title=popupString('Show the edit made to get revision') + ' ' + this.oldid; this.from='prev'; this.to=this.oldid; break; case 'editOld': this.print=wikiLink; this.action='edit'; break; case 'undo': this.print=wikiLink; this.action='edit&undo='; break; case 'markpatrolled': this.print=wikiLink; this.action='markpatrolled'; case 'revert': this.print=wikiLink; this.action='revert'; break; case 'nullEdit': this.print=wikiLink; this.action='nullEdit'; break; case 'diffCur': this.print=titledDiffLink; this.title=tprintf('Show changes since revision %s', [this.oldid]); this.from=this.oldid; this.to='cur'; break; case 'editUserTalk': case 'editTalk': delete this.oldid; this.article=this.article.talkPage(); this.action='edit'; this.print=wikiLink; break; case 'newUserTalk': case 'newTalk': this.article=this.article.talkPage(); this.action='edit§ion=new'; this.print=wikiLink; break; case 'lastContrib': case 'sinceMe': this.print=magicHistoryLink; break; case 'togglePreviews': this.text=popupString(pg.option.simplePopups ? 'enable previews' : 'disable previews'); case 'disablePopups': case 'purgePopups': this.print=popupMenuLink; break; default: this.print=function () {return 'Unknown navlink type: '+this.id+''}; } }; // // end navlinks ////////////////////////////////////////////////// //
    // ENDFILE: navlinks.js // STARTFILE: shortcutkeys.js // function popupHandleKeypress(evt) { var keyCode = window.event ? window.event.keyCode : ( evt.keyCode ? evt.keyCode : evt.which); if (!keyCode || !pg.current.link || !pg.current.link.navpopup) { return; } if (keyCode==27) { // escape killPopup(); return false; // swallow keypress } var letter=String.fromCharCode(keyCode); var links=pg.current.link.navpopup.mainDiv.getElementsByTagName('A'); var startLink=0; var i,j; if (popupHandleKeypress.lastPopupLinkSelected) { for (i=0; i... and add a property // not sophisticated at all, easily broken var i=html.indexOf('>'); if (i<0) { return html; } return html.substring(0,i) + ' ' + property + html.substring(i); } function addPopupShortcut(html, key) { if (!getValueOf('popupShortcutKeys')) { return html; } var ret= addLinkProperty(html, 'popupkey="'+key+'"'); if (key==' ') { key=popupString('spacebar'); } return ret.replace(RegExp('^(.*?)(title=")(.*?)(".*)$', 'i'),'$1$2$3 ['+key+']$4'); } // // ENDFILE: shortcutkeys.js // STARTFILE: diffpreview.js // function loadDiff(article, oldid, diff, navpop) { navpop.diffData={}; var oldRev, newRev; switch (diff) { case 'cur': switch ( oldid ) { case null: case '': case 'prev': // eg newmessages diff link oldRev='0&direction=prev'; newRev=0; break; default: oldRev = oldid; newRev = ( oldid || 0 ) + '&direction=cur'; } break; case 'prev': oldRev = ( oldid || 0 ) + '&direction=prev'; newRev = oldid; break; case 'next': oldRev = oldid; newRev = oldid + '&direction=next'; break; default: oldRev = oldid || 0; newRev = diff || 0; break; } oldRev = oldRev || 0; newRev = newRev || 0; var go = function() { pendingNavpopTask(navpop); getWiki(article, doneDiffNew, newRev, navpop); pendingNavpopTask(navpop); getWiki(article, doneDiffOld, oldRev, navpop); var tz = Cookie.read('popTz'); if ( mw.config.get('wgEnableAPI') && getValueOf('popupAdjustDiffDates') && tz===null) { pendingNavpopTask(navpop); getPageWithCaching(pg.wiki.apiwikibase + '?format=json&action=query&meta=userinfo&uiprop=options', function(d) { completedNavpopTask(navpop); setTimecorrectionCookie(d); if (diffDownloadsComplete(navpop)) { insertDiff(navpop); } }, navpop); } return true; // remove hook once run } if (navpop.visible || !getValueOf('popupLazyDownloads')) { go(); } else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_DIFFS'); } } function setTimecorrectionCookie(d) { try { var jsobj=getJsObj(d.data); var tz=jsobj.query.userinfo.options.timecorrection; } catch (someError) { logerr( 'setTimecorretion failed' ); return; } Cookie.create( 'popTz', getTimeOffset(tz), 1); } function doneDiff(download, isOld) { if (!download.owner || !download.owner.diffData) { return; } var navpop=download.owner; var label= (isOld) ? 'Old' : 'New'; var otherLabel=(isOld) ? 'New' : 'Old'; navpop.diffData[label]=download; completedNavpopTask(download.owner); if (diffDownloadsComplete(navpop)) { insertDiff(navpop); } } function diffDownloadsComplete(navpop) { if ( Cookie.read('popTz')===null) { return false; } return navpop.diffData.Old && navpop.diffData.New; } function doneDiffNew(download) { doneDiff(download, false); } function doneDiffOld(download) { doneDiff(download, true); } function rmBoringLines(a,b,context) { if (typeof context == 'undefined') { context=2; } // this is fairly slow... i think it's quicker than doing a word-based diff from the off, though var aa=[], aaa=[]; var bb=[], bbb=[]; var i, j; // first, gather all disconnected nodes in a and all crossing nodes in a and b for (i=0; i 0) { // it's a row we need if (b[i].paired) { bbb.push(b[i].text); } // joined; partner should be in aa else { bbb.push(b[i]); } } } for (i=0; i 0) { // it's a row we need if (a[i].paired) { aaa.push(a[i].text); } // joined; partner should be in aa else { aaa.push(a[i]); } } } return { a: aaa, b: bbb}; } function stripOuterCommonLines(a,b,context) { var i=0; while (i=0 && k>=0 && a[j]==b[k] ) { --j; --k; } return { a: a.slice(max(0,i - 1 - context), min(a.length+1, j + context+1)), b: b.slice(max(0,i - 1 - context), min(b.length+1, k + context+1)) }; } function insertDiff(navpop) { // for speed reasons, we first do a line-based diff, discard stuff that seems boring, then do a word-based diff // FIXME: sometimes this gives misleading diffs as distant chunks are squashed together var oldlines=navpop.diffData.Old.data.split('\n'); var newlines=navpop.diffData.New.data.split('\n'); var inner=stripOuterCommonLines(oldlines,newlines,getValueOf('popupDiffContextLines')); oldlines=inner.a; newlines=inner.b; var truncated=false; getValueOf('popupDiffMaxLines'); if (oldlines.length > pg.option.popupDiffMaxLines || newlines.length > pg.option.popupDiffMaxLines) { // truncate truncated=true; inner=stripOuterCommonLines(oldlines.slice(0,pg.option.popupDiffMaxLines), newlines.slice(0,pg.option.popupDiffMaxLines), pg.option.popupDiffContextLines); oldlines=inner.a; newlines=inner.b; } var lineDiff=diff(oldlines, newlines); var lines2=rmBoringLines(lineDiff.o, lineDiff.n); var oldlines2=lines2.a; var newlines2=lines2.b; var simpleSplit = !String.prototype.parenSplit.isNative; var html='
    '; if (getValueOf('popupDiffDates')) { html += diffDatesTable(navpop.diffData.Old, navpop.diffData.New); html += '
    '; } html += shortenDiffString( diffString(oldlines2.join('\n'), newlines2.join('\n'), simpleSplit), getValueOf('popupDiffContextCharacters') ).join('
    '); setPopupTipsAndHTML(html.split('\n').join('
    ') + (truncated ? '
    '+popupString('Diff truncated for performance reasons')+'' : '') , 'popupPreview', navpop.idNumber); } function diffDatesTable( oldDl, newDl ) { var html=''; html += diffDatesTableRow( newDl, tprintf('New revision')); html += diffDatesTableRow( oldDl, tprintf('Old revision')); html += ''; return html; } function diffDatesTableRow( dl, label ) { var txt=''; if (!dl) { txt=popupString('Something went wrong :-('); } else if (!dl.lastModified) { txt= (/^\s*$/.test(dl.data)) ? popupString('Empty revision, maybe non-existent') : popupString('Unknown date'); } else { var datePrint=getValueOf('popupDiffDatePrinter'); if (typeof dl.lastModified[datePrint] == 'function') { if (getValueOf('popupAdjustDiffDates')) { var off; if (off=Cookie.read('popTz')) { var d2=adjustDate(dl.lastModified, off); txt = dayFormat(d2, true) + ' ' + timeFormat(d2, true); } } else { txt = dl.lastModified[datePrint](); } } else { txt = tprintf('Invalid %s %s', ['popupDiffDatePrinter', datePrint]); } } var revlink = generalLink({url: dl.url.replace(/&.*?(oldid=[0-9]+(?:&direction=[^&]*)?).*/, '&$1'), text: label, title: label}); return simplePrintf('%s%s', [ revlink, txt ]); } //
    // ENDFILE: diffpreview.js // STARTFILE: links.js // ///////////////////// // LINK GENERATION // ///////////////////// // titledDiffLink --> titledWikiLink --> generalLink // wikiLink --> titledWikiLink --> generalLink // editCounterLink --> generalLink function titledDiffLink(l) { // article, text, title, from, to) { return titledWikiLink({article: l.article, action: l.to + '&oldid=' + l.from, newWin: l.newWin, noPopup: l.noPopup, text: l.text, title: l.title, /* hack: no oldid here */ actionName: 'diff'}); } function wikiLink(l) { //{article:article, action:action, text:text, oldid, newid}) { if (! (typeof l.article == typeof {} && typeof l.action == typeof '' && typeof l.text==typeof '')) return null; if (typeof l.oldid == 'undefined') { l.oldid=null; } var savedOldid = l.oldid; if (!/^(edit|view|revert|render)$|^raw/.test(l.action)) { l.oldid=null; } var hint=popupString(l.action + 'Hint'); // revertHint etc etc etc var oldidData=[l.oldid, safeDecodeURI(l.article)]; var revisionString = tprintf('revision %s of %s', oldidData); log('revisionString='+revisionString); switch (l.action) { case 'edit§ion=new': hint = popupString('newSectionHint'); break; case 'edit&undo=': if (l.diff && l.diff != 'prev' && savedOldid ) { l.action += l.diff + '&undoafter=' + savedOldid; } else if (savedOldid) { l.action += savedOldid; } hint = popupString('undoHint'); break; case 'raw&ctype=text/css': hint=popupString('rawHint'); break; case 'revert': if ( !mw.config.get('wgEnableAPI') ) { alert( 'This function of navigation popups now requires a MediaWiki ' + 'installation with the API enabled.'); break; } var p=parseParams(pg.current.link.href); l.action='edit&autoclick=wpSave&actoken=' + autoClickToken() + '&autoimpl=' + popupString('autoedit_version') + '&autosummary=' + revertSummary(l.oldid, p.diff); if (p.diff=='prev') { l.action += '&direction=prev'; revisionString = tprintf('the revision prior to revision %s of %s', oldidData); } if (getValueOf('popupRevertSummaryPrompt')) { l.action += '&autosummaryprompt=true'; } if (getValueOf('popupMinorReverts')) { l.action += '&autominor=true'; } log('revisionString is now '+revisionString); break; case 'nullEdit': l.action='edit&autoclick=wpSave&actoken=' + autoClickToken() + '&autoimpl=' + popupString('autoedit_version') + '&autosummary=null'; break; case 'historyfeed': l.action='history&feed=rss'; break; case 'markpatrolled': l.action='markpatrolled&rcid='+l.rcid; } if (hint) { if (l.oldid) { hint = simplePrintf(hint, [revisionString]); } else { hint = simplePrintf(hint, [safeDecodeURI(l.article)]); } } else { hint = safeDecodeURI(l.article + '&action=' + l.action) + (l.oldid) ? '&oldid='+l.oldid : ''; } return titledWikiLink({article: l.article, action: l.action, text: l.text, newWin:l.newWin, title: hint, oldid: l.oldid, noPopup: l.noPopup, onclick: l.onclick}); } function revertSummary(oldid, diff) { var ret=''; if (diff == 'prev') { ret=getValueOf('popupQueriedRevertToPreviousSummary'); } else { ret = getValueOf('popupQueriedRevertSummary'); } return ret + '&autorv=' + oldid; } function titledWikiLink(l) { // possible properties of argument: // article, action, text, title, oldid, actionName, className, noPopup // oldid = null is fine here // article and action are mandatory args if (typeof l.article == 'undefined' || typeof l.action=='undefined') { errlog('got undefined article or action in titledWikiLink'); return null; } var base = pg.wiki.titlebase + l.article.urlString(); var url=base; if (typeof l.actionName=='undefined' || !l.actionName) { l.actionName='action'; } // no need to add &action=view, and this confuses anchors if (l.action != 'view') { url = base + '&' + l.actionName + '=' + l.action; } if (typeof l.oldid!='undefined' && l.oldid) { url+='&oldid='+l.oldid; } var cssClass=pg.misc.defaultNavlinkClassname; if (typeof l.className!='undefined' && l.className) { cssClass=l.className; } return generalNavLink({url: url, newWin: l.newWin, title: (typeof l.title != 'undefined') ? l.title : null, text: (typeof l.text!='undefined')?l.text:null, className: cssClass, noPopup:l.noPopup, onclick:l.onclick}); } function getLastContrib(wikipage, newWin) { getHistoryInfo(wikipage, function(x){processLastContribInfo(x,{page: wikipage, newWin: newWin})}); } function processLastContribInfo(info, stuff) { if(!info.edits || !info.edits.length) { alert('Popups: an odd thing happened. Please retry.'); return; } if(!info.firstNewEditor) { alert(tprintf('Only found one editor: %s made %s edits', [info.edits[0].editor,info.edits.length])); return; } var newUrl=pg.wiki.titlebase + new Title(stuff.page).urlString() + '&diff=cur&oldid='+info.firstNewEditor.oldid; displayUrl(newUrl, stuff.newWin); } function getDiffSinceMyEdit(wikipage, newWin) { getHistoryInfo(wikipage, function(x){processDiffSinceMyEdit(x,{page: wikipage, newWin: newWin})}); } function processDiffSinceMyEdit(info, stuff) { if(!info.edits || !info.edits.length) { alert('Popups: something fishy happened. Please try again.'); return; } var friendlyName=stuff.page.split('_').join(' '); if(!info.myLastEdit) { alert(tprintf('Couldn\'t find an edit by %s\nin the last %s edits to\n%s', [info.userName, getValueOf('popupHistoryLimit'), friendlyName])); return; } if(info.myLastEdit.index==0) { alert(tprintf("%s seems to be the last editor to the page %s", [info.userName, friendlyName])); return; } var newUrl=pg.wiki.titlebase + new Title(stuff.page).urlString() + '&diff=cur&oldid='+ info.myLastEdit.oldid; displayUrl(newUrl, stuff.newWin); } function displayUrl(url, newWin){ if(newWin) { window.open(url); } else { document.location=url; } } function purgePopups() { processAllPopups(true); setupCache(); // deletes all cached items (not browser cached, though...) pg.option={}; abortAllDownloads(); } function processAllPopups(nullify, banish) { for (var i=0; pg.current.links && i \s*([Cc]omputer[_ ](?:%2528|\()archaic(?:%2528|\)))\s* // autoedit=s~\[\[([Cc]ad)\]\]~[[Computer-aided%20design|$1]]~g;s~\[\[([Cc]AD)[|]~[[Computer-aided%20design|~g var title=x.title || mw.config.get('wgPageName').split('_').join(' '); var lk=titledWikiLink({article: new Title(title), newWin:x.newWin, action: 'edit', text: x.text, title: x.hint, className: 'popup_change_title_link' }); var cmd=''; if (x.newTarget) { // escape '&' and other nasties var t=x.newTarget; var s=literalizeRegex(x.newTarget); cmd += 's~\\[\\['+currentArticleRegexBit+'\\]\\]~[['+t+'|$1]]~g;'; cmd += 's~\\[\\['+currentArticleRegexBit+'[|]~[['+t+'|~g;'; cmd += 's~\\[\\['+s + '\\|' + s + '\\]\\]~[[' + t + ']]~g'; } else { cmd += 's~\\[\\['+currentArticleRegexBit+'\\]\\]~$1~g;'; cmd += 's~\\[\\['+currentArticleRegexBit+'[|](.*?)\\]\\]~$2~g'; } // Build query cmd = 'autoedit=' + encodeURIComponent ( cmd ); cmd += '&autoclick='+ encodeURIComponent( x.clickButton ) + '&actoken=' + encodeURIComponent( autoClickToken() ); cmd += ( x.minor == null ) ? '' : '&autominor='+ encodeURIComponent( x.minor ); cmd += ( x.watch == null ) ? '' : '&autowatch='+ encodeURIComponent( x.watch ); cmd += '&autosummary='+encodeURIComponent(x.summary); cmd += '&autoimpl='+encodeURIComponent( popupString('autoedit_version') ); return appendParamsToLink(lk, cmd); } function redirLink(redirMatch, article) { // NB redirMatch is in wikiText var ret=''; if (getValueOf('popupAppendRedirNavLinks') && getValueOf('popupNavLinks')) { ret += '
    '; if (getValueOf('popupFixRedirs') && typeof autoEdit != 'undefined' && autoEdit) { log('redirLink: newTarget=' + redirMatch); ret += addPopupShortcut( changeLinkTargetLink( {newTarget: redirMatch, text: popupString('Redirects'), hint: popupString('Fix this redirect'), summary: simplePrintf(getValueOf('popupFixRedirsSummary'), [article.toString(), redirMatch ]), oldTarget: article.toString(), clickButton: getValueOf('popupRedirAutoClick'), minor: true, watch: getValueOf('popupWatchRedirredPages')}) , 'R'); ret += popupString(' to '); } else ret += popupString('Redirects') + popupString(' to '); return ret; } else return '
    ' + popupString('Redirects') + popupString(' to ') + titledWikiLink({article: new Title().fromWikiText(redirMatch), action: 'view', /* FIXME: newWin */ text: safeDecodeURI(redirMatch), title: popupString('Bypass redirect')}); } function arinLink(l) { if (!saneLinkCheck(l)) { return null; } if ( ! l.article.isIpUser() || ! pg.wiki.wikimedia) return null; var uN=l.article.userName(); return generalNavLink({url:'http://ws.arin.net/cgi-bin/whois.pl?queryinput=' + encodeURIComponent(uN), newWin:l.newWin, title: tprintf('Look up %s in ARIN whois database', [uN]), text: l.text, noPopup:1}); } function toolDbName(cookieStyle) { var ret = mw.config.get('wgDBname'); if (!cookieStyle) { ret+= '_p'; } return ret; } function saneLinkCheck(l) { if (typeof l.article != typeof {} || typeof l.text != typeof '') { return false; } return true; } function editCounterLink(l) { if(!saneLinkCheck(l)) return null; if (! pg.wiki.wikimedia) return null; var uN=l.article.userName(); var tool=getValueOf('popupEditCounterTool'); var url; var soxredToolUrl='//tools.wmflabs.org/supercount/index.php?user=$1&project=$2.$3'; switch(tool) { case 'custom': url=simplePrintf(getValueOf('popupEditCounterUrl'), [ encodeURIComponent(uN), toolDbName() ]); break; case 'kate': case 'interiot': default: var theWiki=pg.wiki.hostname.split('.'); url=simplePrintf(soxredToolUrl, [ encodeURIComponent(uN), theWiki[0], theWiki[1] ]); } return generalNavLink({url:url, title: tprintf('editCounterLinkHint', [uN]), newWin:l.newWin, text: l.text, noPopup:1}); } function globalSearchLink(l) { if(!saneLinkCheck(l)) return null; var base='http://vs.aka-online.de/cgi-bin/globalwpsearch.pl?timeout=120&search='; var article=l.article.urlString({keepSpaces:true}); return generalNavLink({url:base + article, newWin:l.newWin, title: tprintf('globalSearchHint', [safeDecodeURI(l.article)]), text: l.text, noPopup:1}); } function googleLink(l) { if(!saneLinkCheck(l)) return null; var base='http://www.google.com/search?q='; var article=l.article.urlString({keepSpaces:true}); return generalNavLink({url:base + '%22' + article + '%22', newWin:l.newWin, title: tprintf('googleSearchHint', [safeDecodeURI(l.article)]), text: l.text, noPopup:1}); } function editorListLink(l) { if(!saneLinkCheck(l)) return null; var article= l.article.articleFromTalkPage() || l.article; var theWiki=pg.wiki.hostname.split('.'); var base='//tools.wmflabs.org/xtools/articleinfo/index.php?&uselang=' + mw.config.get('wgUserLanguage') + 'lang=' + theWiki[0] + '&wiki=' + theWiki[1] + '&begin=&end=&article=' return generalNavLink({url:base+article.urlString(), title: tprintf('editorListHint', [article]), newWin:l.newWin, text: l.text, noPopup:1}); } function generalNavLink(l) { l.className = (l.className==null) ? 'popupNavLink' : l.className; return generalLink(l); } ////////////////////////////////////////////////// // magic history links // function getHistoryInfo(wikipage, whatNext) { log('getHistoryInfo'); getHistory(wikipage, whatNext ? function(d){whatNext(processHistory(d));} : processHistory); } // FIXME eliminate pg.idNumber ... how? :-( function getHistory(wikipage, onComplete) { log('getHistory'); if( !mw.config.get('wgEnableAPI') ) { alert( 'This function of navigation popups now requires a MediaWiki ' + 'installation with the API enabled.'); return false; } var url = pg.wiki.apiwikibase + '?format=json&action=query&prop=revisions&titles=' + new Title(wikipage).urlString() + '&rvlimit=' + getValueOf('popupHistoryLimit'); log('getHistory: url='+url); if (pg.flag.isIE) { url = url + '&*'; //to circumvent https://bugzilla.wikimedia.org/show_bug.cgi?id=28840 } return startDownload(url, pg.idNumber+'history', onComplete); } function processHistory(download) { var jsobj = getJsObj(download.data); try { window.x=jsobj; var p=jsobj['query']['pages'] for (var pageid in p) { var revisions=p[pageid]['revisions']; // we only get the first one break; } } catch (someError) { log('Something went wrong with JSON business'); return finishProcessHistory([]); } var edits=[]; for (var i=0; i // ENDFILE: links.js // STARTFILE: options.js ////////////////////////////////////////////////// // options // check for cookies and existing value, else use default function defaultize(x) { var val=null; if (x!='popupCookies') { defaultize('popupCookies'); if (pg.option.popupCookies && (val=Cookie.read(x))) { pg.option[x]=val; return; } } if (pg.option[x]===null || typeof pg.option[x]=='undefined') { if (typeof window[x] != 'undefined' ) pg.option[x]=window[x]; else pg.option[x]=pg.optionDefault[x]; } } function newOption(x, def) { pg.optionDefault[x]=def; } function setDefault(x, def) { return newOption(x, def); } function getValueOf(varName) { defaultize(varName); return pg.option[varName]; } function useDefaultOptions() { // for testing for (var p in pg.optionDefault) { pg.option[p]=pg.optionDefault[p]; if (typeof window[p]!='undefined') { delete window[p]; } } } function setOptions() { // user-settable parameters and defaults var userIsSysop = false; if ( mw.config.get('wgUserGroups') ) { for ( var g = 0; g < mw.config.get('wgUserGroups').length; ++g ) { if ( mw.config.get('wgUserGroups')[g] == "sysop" ) userIsSysop = true } } // Basic options newOption('popupDelay', 0.5); newOption('popupHideDelay', 0.5); newOption('simplePopups', false); newOption('popupStructure', 'shortmenus'); // see later - default for popupStructure is 'original' if simplePopups is true newOption('popupActionsMenu', true); newOption('popupSetupMenu', true); newOption('popupAdminLinks', userIsSysop); newOption('popupShortcutKeys', false); newOption('popupHistoricalLinks', true); newOption('popupOnlyArticleLinks', true); newOption('removeTitles', true); newOption('popupMaxWidth', 350); newOption('popupInitialWidth', false); // integer or false newOption('popupSimplifyMainLink', true); newOption('popupAppendRedirNavLinks', true); newOption('popupTocLinks', false); newOption('popupSubpopups', true); newOption('popupDragHandle', false /* 'popupTopLinks'*/); newOption('popupLazyPreviews', true); newOption('popupLazyDownloads', true); newOption('popupAllDabsStubs', false); newOption('popupDebugging', false); newOption('popupAdjustDiffDates', true); newOption('popupActiveNavlinks', true); newOption('popupModifier', false); // ctrl, shift, alt or meta newOption('popupModifierAction', 'enable'); // or 'disable' newOption('popupDraggable', true); // // images newOption('popupImages', true); newOption('imagePopupsForImages', true); newOption('popupNeverGetThumbs', false); //newOption('popupImagesToggleSize', true); newOption('popupThumbAction', 'imagepage'); //'sizetoggle'); newOption('popupImageSize', 60); newOption('popupImageSizeLarge', 200); // redirs, dabs, reversion newOption('popupFixRedirs', false); newOption('popupRedirAutoClick', 'wpDiff'); newOption('popupFixDabs', false); newOption('popupDabsAutoClick', 'wpDiff'); newOption('popupRevertSummaryPrompt', false); newOption('popupMinorReverts', false); newOption('popupRedlinkRemoval', false); newOption('popupWatchDisambiggedPages', null); newOption('popupWatchRedirredPages', null); newOption('popupDabWiktionary', 'last'); // navlinks newOption('popupNavLinks', true); newOption('popupNavLinkSeparator', ' ⋅ '); newOption('popupLastEditLink', true); newOption('popupEditCounterTool', 'soxred'); newOption('popupEditCounterUrl', ''); newOption('popupExtraUserMenu', ''); // // previews etc newOption('popupPreviews', true); newOption('popupSummaryData', true); newOption('popupMaxPreviewSentences', 5); newOption('popupMaxPreviewCharacters', 600); newOption('popupLastModified', true); newOption('popupPreviewKillTemplates', true); newOption('popupPreviewRawTemplates', true); newOption('popupPreviewFirstParOnly', true); newOption('popupPreviewCutHeadings', true); newOption('popupPreviewButton', false); newOption('popupPreviewButtonEvent', 'click'); // // diffs newOption('popupPreviewDiffs', true); newOption('popupDiffMaxLines', 100); newOption('popupDiffContextLines', 2); newOption('popupDiffContextCharacters', 40); newOption('popupDiffDates', true); newOption('popupDiffDatePrinter', 'toLocaleString'); // edit summaries. God, these are ugly. newOption('popupFixDabsSummary', popupString('defaultpopupFixDabsSummary') ); newOption('popupExtendedRevertSummary', popupString('defaultpopupExtendedRevertSummary') ); newOption('popupTimeOffset', null); newOption('popupRevertSummary', popupString('defaultpopupRevertSummary') ); newOption('popupRevertToPreviousSummary', popupString('defaultpopupRevertToPreviousSummary') ); newOption('popupQueriedRevertSummary', popupString('defaultpopupQueriedRevertSummary') ); newOption('popupQueriedRevertToPreviousSummary', popupString('defaultpopupQueriedRevertToPreviousSummary') ); newOption('popupFixRedirsSummary', popupString('defaultpopupFixRedirsSummary') ); newOption('popupRedlinkSummary', popupString('defaultpopupRedlinkSummary') ); newOption('popupRmDabLinkSummary', popupString('defaultpopupRmDabLinkSummary') ); // // misc newOption('popupCookies', false); newOption('popupHistoryLimit', 50); // newOption('popupFilters', [popupFilterStubDetect, popupFilterDisambigDetect, popupFilterPageSize, popupFilterCountLinks, popupFilterCountImages, popupFilterCountCategories, popupFilterLastModified]); newOption('extraPopupFilters', []); newOption('popupOnEditSelection', 'cursor'); newOption('popupPreviewHistory', true); newOption('popupImageLinks', true); newOption('popupCategoryMembers', true); newOption('popupUserInfo', true); newOption('popupHistoryPreviewLimit', 25); newOption('popupContribsPreviewLimit',25); newOption('popupRevDelUrl', '//en.wikipedia.org/wiki/Wikipedia:Revision_deletion'); // // new windows newOption('popupNewWindows', false); newOption('popupLinksNewWindow', {'lastContrib': true, 'sinceMe': true}); // regexps newOption('popupDabRegexp', '(\\{\\{\\s*disambig(?!uation needed)|disambig(uation|)\\s*\\}\\}|disamb\\s*\\}\\}|dab\\s*\\}\\})|\\{\\{\\s*(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index)(\\s*[|][^}]*)?\\s*[}][}]|is a .*disambiguation.*page'); newOption('popupAnchorRegexp', 'anchors?'); //how to identify an anchors template newOption('popupStubRegexp', '(sect)?stub[}][}]|This .*-related article is a .*stub'); newOption('popupImageVarsRegexp', 'image|image_(?:file|skyline|name|flag|seal)|cover|badge|logo'); } // ENDFILE: options.js // STARTFILE: strings.js // ////////////////////////////////////////////////// // Translatable strings ////////////////////////////////////////////////// // // See instructions at // http://en.wikipedia.org/wiki/Wikipedia:Tools/Navigation_popups/Translation pg.string = { ///////////////////////////////////// // summary data, searching etc. ///////////////////////////////////// 'article': 'article', 'category': 'category', 'categories': 'categories', 'image': 'image', 'images': 'images', 'stub': 'stub', 'section stub': 'section stub', 'Empty page': 'Empty page', 'kB': 'kB', 'bytes': 'bytes', 'day': 'day', 'days': 'days', 'hour': 'hour', 'hours': 'hours', 'minute': 'minute', 'minutes': 'minutes', 'second': 'second', 'seconds': 'seconds', 'week': 'week', 'weeks': 'weeks', 'search': 'search', 'SearchHint': 'Find English Wikipedia articles containing %s', 'web': 'web', 'global': 'global', 'globalSearchHint': 'Search across Wikipedias in different languages for %s', 'googleSearchHint': 'Google for %s', ///////////////////////////////////// // article-related actions and info // (some actions also apply to user pages) ///////////////////////////////////// 'actions': 'actions', ///// view articles and view talk 'popupsMenu': 'popups', 'togglePreviewsHint': 'Toggle preview generation in popups on this page', 'enable previews': 'enable previews', 'disable previews': 'disable previews', 'toggle previews': 'toggle previews', 'show preview': 'show preview', 'reset': 'reset', 'more...': 'more...', 'disable': 'disable popups', 'disablePopupsHint': 'Disable popups on this page. Reload page to re-enable.', 'historyfeedHint': 'RSS feed of recent changes to this page', 'purgePopupsHint': 'Reset popups, clearing all cached popup data.', 'PopupsHint': 'Reset popups, clearing all cached popup data.', 'spacebar': 'space', 'view': 'view', 'view article': 'view article', 'viewHint': 'Go to %s', 'talk': 'talk', 'talk page': 'talk page', 'this revision': 'this revision', 'revision %s of %s': 'revision %s of %s', 'Revision %s of %s': 'Revision %s of %s', 'the revision prior to revision %s of %s': 'the revision prior to revision %s of %s', 'Toggle image size': 'Click to toggle image size', 'del': 'del', ///// delete, protect, move 'delete': 'delete', 'deleteHint': 'Delete %s', 'undeleteShort': 'un', 'UndeleteHint': 'Show the deletion history for %s', 'protect': 'protect', 'protectHint': 'Restrict editing rights to %s', 'unprotectShort': 'un', 'unprotectHint': 'Allow %s to be edited by anyone again', 'move': 'move', 'move page': 'move page', 'MovepageHint': 'Change the title of %s', 'edit': 'edit', ///// edit articles and talk 'edit article': 'edit article', 'editHint': 'Change the content of %s', 'edit talk': 'edit talk', 'new': 'new', 'new topic': 'new topic', 'newSectionHint': 'Start a new section on %s', 'null edit': 'null edit', 'nullEditHint': 'Submit an edit to %s, making no changes ', 'hist': 'hist', ///// history, diffs, editors, related 'history': 'history', 'historyHint': 'List the changes made to %s', 'last': 'last', 'lastEdit': 'lastEdit', 'mark patrolled': 'mark patrolled', 'markpatrolledHint': 'Mark this edit as patrolled', 'show last edit': 'most recent edit', 'Show the last edit': 'Show the effects of the most recent change', 'lastContrib': 'lastContrib', 'last set of edits': 'latest edits', 'lastContribHint': 'Show the net effect of changes made by the last editor', 'cur': 'cur', 'diffCur': 'diffCur', 'Show changes since revision %s': 'Show changes since revision %s', '%s old': '%s old', // as in 4 weeks old 'oldEdit': 'oldEdit', 'purge': 'purge', 'purgeHint': 'Demand a fresh copy of %s', 'raw': 'source', 'rawHint': 'Download the source of %s', 'render': 'simple', 'renderHint': 'Show a plain HTML version of %s', 'Show the edit made to get revision': 'Show the edit made to get revision', 'sinceMe': 'sinceMe', 'changes since mine': 'diff my edit', 'sinceMeHint': 'Show changes since my last edit', 'Couldn\'t find an edit by %s\nin the last %s edits to\n%s': 'Couldn\'t find an edit by %s\nin the last %s edits to\n%s', 'eds': 'eds', 'editors': 'editors', 'editorListHint': 'List the users who have edited %s', 'related': 'related', 'relatedChanges': 'relatedChanges', 'related changes': 'related changes', 'RecentchangeslinkedHint': 'Show changes in articles related to %s', 'editOld': 'editOld', ///// edit old version, or revert 'rv': 'rv', 'revert': 'revert', 'revertHint': 'Revert to %s', 'defaultpopupRedlinkSummary': 'Removing link to empty page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupFixDabsSummary': 'Disambiguate [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupFixRedirsSummary': 'Redirect bypass from [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupExtendedRevertSummary': 'Revert to revision dated %s by %s, oldid %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupRevertToPreviousSummary': 'Revert to the revision prior to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupRevertSummary': 'Revert to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupQueriedRevertToPreviousSummary': 'Revert to the revision prior to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupQueriedRevertSummary': 'Revert to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'defaultpopupRmDabLinkSummary': 'Remove link to dab page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', 'Redirects': 'Redirects', // as in Redirects to ... ' to ': ' to ', // as in Redirects to ... 'Bypass redirect': 'Bypass redirect', 'Fix this redirect': 'Fix this redirect', 'disambig': 'disambig', ///// add or remove dab etc. 'disambigHint': 'Disambiguate this link to [[%s]]', 'Click to disambiguate this link to:': 'Click to disambiguate this link to:', 'remove this link': 'remove this link', 'remove all links to this page from this article': 'remove all links to this page from this article', 'remove all links to this disambig page from this article': 'remove all links to this disambig page from this article', 'mainlink': 'mainlink', ///// links, watch, unwatch 'wikiLink': 'wikiLink', 'wikiLinks': 'wikiLinks', 'links here': 'links here', 'whatLinksHere': 'whatLinksHere', 'what links here': 'what links here', 'WhatlinkshereHint': 'List the pages that are hyperlinked to %s', 'unwatchShort': 'un', 'watchThingy': 'watch', // called watchThingy because {}.watch is a function 'watchHint': 'Add %s to my watchlist', 'unwatchHint': 'Remove %s from my watchlist', 'Only found one editor: %s made %s edits': 'Only found one editor: %s made %s edits', '%s seems to be the last editor to the page %s': '%s seems to be the last editor to the page %s', 'rss': 'rss', ///////////////////////////////////// // diff previews ///////////////////////////////////// 'Diff truncated for performance reasons': 'Diff truncated for performance reasons', 'Old revision': 'Old revision', 'New revision': 'New revision', 'Something went wrong :-(': 'Something went wrong :-(', 'Empty revision, maybe non-existent': 'Empty revision, maybe non-existent', 'Unknown date': 'Unknown date', ///////////////////////////////////// // other special previews ///////////////////////////////////// 'Empty category': 'Empty category', 'Category members (%s shown)': 'Category members (%s shown)', 'No image links found': 'No image links found', 'File links': 'File links', 'No image found': 'No image found', 'Image from Commons': 'Image from Commons', 'Description page': 'Description page', 'Alt text:': 'Alt text:', 'revdel':'Hidden revision', ///////////////////////////////////// // user-related actions and info ///////////////////////////////////// 'user': 'user', ///// user page, talk, email, space 'user page': 'user page', 'user talk': 'user talk', 'edit user talk': 'edit user talk', 'leave comment': 'leave comment', 'email': 'email', 'email user': 'email user', 'EmailuserHint': 'Send an email to %s', 'space': 'space', // short form for userSpace link 'PrefixIndexHint': 'Show pages in the userspace of %s', 'count': 'count', ///// contributions, log 'edit counter': 'edit counter', 'editCounterLinkHint': 'Count the contributions made by %s', 'contribs': 'contribs', 'contributions': 'contributions', 'deletedContribs': 'deleted contributions', 'DeletedcontributionsHint': 'List deleted edits made by %s', 'ContributionsHint': 'List the contributions made by %s', 'log': 'log', 'user log': 'user log', 'userLogHint': 'Show %s\'s user log', 'arin': 'ARIN lookup', ///// ARIN lookup, block user or IP 'Look up %s in ARIN whois database': 'Look up %s in the ARIN whois database', 'unblockShort': 'un', 'block': 'block', 'block user': 'block user', 'IpblocklistHint': 'Unblock %s', 'BlockipHint': 'Prevent %s from editing', 'block log': 'block log', 'blockLogHint': 'Show the block log for %s', 'protectLogHint': 'Show the protection log for %s', 'pageLogHint': 'Show the page log for %s', 'deleteLogHint': 'Show the deletion log for %s', 'Invalid %s %s': 'The option %s is invalid: %s', 'No backlinks found': 'No backlinks found', ' and more': ' and more', 'undo': 'undo', 'undoHint': 'undo this edit', 'Download preview data': 'Download preview data', 'Invalid or IP user': 'Invalid or IP user', 'Not a registered username': 'Not a registered username', 'BLOCKED': 'BLOCKED', ' edits since: ': ' edits since: ', ///////////////////////////////////// // Autoediting ///////////////////////////////////// 'Enter a non-empty edit summary or press cancel to abort': 'Enter a non-empty edit summary or press cancel to abort', 'Failed to get revision information, please edit manually.\n\n': 'Failed to get revision information, please edit manually.\n\n', 'The %s button has been automatically clicked. Please wait for the next page to load.': 'The %s button has been automatically clicked. Please wait for the next page to load.', 'Could not find button %s. Please check the settings in your javascript file.': 'Could not find button %s. Please check the settings in your javascript file.', ///////////////////////////////////// // Popups setup ///////////////////////////////////// 'Open full-size image': 'Open full-size image', 'zxy': 'zxy', 'autoedit_version': 'np20140416' }; function popupString(str) { if (typeof popupStrings != 'undefined' && popupStrings && popupStrings[str]) { return popupStrings[str]; } if (pg.string[str]) { return pg.string[str]; } return str; } function tprintf(str,subs) { if (typeof subs != typeof []) { subs = [subs]; } return simplePrintf(popupString(str), subs); } // // ENDFILE: strings.js //////////////////////////////////////////////////////////////////// // Run things //////////////////////////////////////////////////////////////////// // For some reason popups requires a fully loaded page jQuery.ready(...) causes problems for some. // The old addOnloadHook did something similar to the below if (document.readyState=="complete") autoEdit(); //will setup popups else $( window ).on( 'load', autoEdit ); // Support for MediaWiki's live preview, VisualEditor's saves and Echo's flyout. ( function () { var once = true; function dynamicContentHandler( $content ) { // Try to detect the hook fired on initial page load and disregard // it, we already hook to onload (possibly to different parts of // page - it's configurable) and running twice might be bad. Ugly… if ( $content.attr( 'id' ) == 'mw-content-text' ) { if ( once ) { once = false; return; } } function doIt () { $content.each( function () { this.ranSetupTooltipsAlready = false; setupTooltips( this ); } ); }; if ( !setupPopups.completed ) { setupPopups( doIt ); } else { doIt(); } } // This hook is also fired after page load. mw.hook( 'wikipage.content' ).add( dynamicContentHandler ); mw.hook( 'ext.echo.overlay.beforeShowingOverlay' ).add( function($overlay){ dynamicContentHandler( $overlay.find(".mw-echo-state") ); }); } )();