Utilisateur:ContributorQ/scripts/TemplatesToolbar.js
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;
Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.// TemplatesToolbar.js
// A wikiEditor toolbar's add-on: a "Utilisateur:UserName/common.js" add-on which add two dropdownlist
// and some buttons in the toolbar, allowing quick template insertion and selection's wikification.
// Creation: 27/04/2017. (Version 6.0, 15/04/2022).
// Distributed under the terms of the GNU GPLv2 license: http://www.gnu.org/licenses/gpl-2.0.html
// Copyleft (c) ContributorQ (2017-2027).
// This experimental code applies only in the articles' namespace, under edit mode.
//<nowiki>
if ( $.inArray( mediaWiki.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
( function ( mw, $ ) {
// Init the library object "mw.libs" providing routines for any script.
// See: https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.
mw.libs = Object.assign( mw.libs, {
// The months of the year in french.
frMonths: [ 'janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre' ],
// Digits in french.
frDigits: [ 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize' ],
// Separator for templates' parameters.
tmplSeparator: '|',
// Assemble a wiki template.
fillTemplate: function ( templateName, paramValues ) {
var template = '';
if ( templateName ) {
template = '{{' + templateName;
if ( paramValues && paramValues.length > 0 ) {
template += this.tmplSeparator + paramValues.join( this.tmplSeparator );
}
return template + '}}';
}
return template;
},
// Get the current date in french (eg: "24 mai 2017").
getCurrentDate: function () {
var d = new Date();
return mw.format( '$1 $2 $3', d.getDate(),
this.frMonths[ d.getMonth() ].toLowerCase(), // The getMonth() method returns the month (from 0 to 11) for the specified date, according to local time.
d.getFullYear() );
}
} );
////////////////////////////////// Main code ///////////////////////////////////////
var customizeToolbar = function () {
var $wikiEditor = $( '#wpTextbox1' ), //Get the editor element.
basicToolbarButton = {
type: 'button',
icon: 'none'
},
toolbarButtonArray = {},
toolbarButtonGroups = {},
toolbarButtonIds = [],
groupsCount = 1,
toolbarButtonsCount = 0,
divGroup,
buttonsPerGroup = 13, // Number of options on each row of the toolbar.
/* Template descriptor's parameters. ********************
* linkTitle: link's title in the templates toolbar.
* name: exact name of the template.
* suffix: a suffix specific to the template (e.g.: "e" in the "s" template).
* paramsCount: the number of parameters of the template (-1 for any, 1 for only one, 0 when the "addTmpl" function is defined).
* cleanSelection : an optional function to format the selection before applying the template.
* addTmpl : an optional function to apply a specific template.
* addTmplDeferred : an option to defer the call to the optional "addTmpl" finction if defined.
* global: a function is globally applied to the whole text.
* globalAction: a routine applied to a selected texte or globally to the whole text.
*********************************************************/
tmplDescriptors = [
{ linkTitle: '- [[ ]]', name: '', tooltip: "Déwikification d'un lien interne.", suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return removeInternalLink( txt, false ); }, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ {{ }}', name: '', tooltip: 'Surround by "{{" and "}}".', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addWikiTemplateTags( txt ); }, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ {{ | }}', name: '', tooltip: 'Surround by "{{" and "}}" and replace the middle blank or " " by a "|".', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addWikiTemplateTagsAndMiddlePipe( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '- "|"', name: '', tooltip: 'Replace "|" in "date" and "unité" templates (ex.: "{{date|24|juin|2001}}" becomes "{{date|24 juin 2001}}").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return removePipes( selection ); } },
{ linkTitle: '+ {{s-|}}', name: '', tooltip: 'Format century (ex.: "XIe siècle" becomes "{{s-|XI}}" or "XIe et XIIe siècles" becomes "{{s2-|XI|XII}}").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addCenturyTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ {{p.}}', name: '', tooltip: 'Replace a "p.(/page) nnn" expression by "{{p.|nnn}} (note: "p", "pp" or "pp." are converted to "p.").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addPageTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Dt', name: 'date', tooltip: 'Add a {{date|}} template globally or on a selected text (ex.: "1er mai [[1981]]" becomes "{{date|1 mai [[1981}}")".', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return addDateTemplate( selection, this.name ); } },
{ linkTitle: 'Unité', name: 'unité', tooltip: 'Add a {{unité|}} template.', suffix: '', paramsCount: 1, cleanSelection: function ( txt ) { return cleanBeforeAddingUnitTemplate( txt ); }, addTmpl: null, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Dunité', name: 'dunité', tooltip: 'Add a {{dunité|}} template.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addDunitTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'FrmNum', name: '', tooltip: 'Add "formatnum:" template.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return formatNum( txt ); }, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ Nobr', name: '', tooltip: 'Add "{{nobr|...}}" globally or on a selected text.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return addNoBrTemplate( selection ); } },
{ linkTitle: 'Lg (en)', name: 'langue|en', tooltip: 'Add a {{langue|en|}} template.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Lg (ja)', name: 'langue|ja', tooltip: 'Add a {{langue|ja|}} template.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Hre', name: 'heure', tooltip: 'Add a {{heure|}} template.', suffix: '', paramsCount: -1, cleanSelection: function ( txt ) { return removeHourSymbol( txt ); }, addTmpl: null, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Hre (durée)', name: 'heure', tooltip: 'Add a {{heure|}} template.', suffix: 'durée=oui', paramsCount: -1, cleanSelection: function ( txt ) { return removeHourSymbol( txt ); }, addTmpl: null, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '« »', name: '', tooltip: 'Add « ... » or replace "..." by « ... ».', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addFrenchQuotes( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '"«...»"', name: '', tooltip: "Change ''«...»'' into « ''...'' ».", suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return arrangeQuotes( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ {{incise|', name: '', tooltip: 'Encapsulate a selected texte in the "{{incise|...}}" template.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addInciseTemplate( txt ); }, asButton: false, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'frmNum ► unité', name: '', tooltip: 'Replace "{{formatnum:N}} ABC" expression by {{unité|N ABC}}.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return replaceFormatnumByUnit( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '{{...}} ► {{...|}}', name: '', tooltip: 'Replace "{{...}} ABC" expression by "{{...|ABC}}" (ex.: "{{10e}} tour" becomes "{{10e|tour}}" ; "{{p.}}20" becomes "{{p.|20}}").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return compactTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'A ► a', name: '', tooltip: 'Toggle a selected text to lower case.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return toggleTextToLowerCase( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Trim', name: '', tooltip: 'Remove useless spaces around | and =, and before }}.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return removeUselessSpaces( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ <ref>', name: '', tooltip: 'Add "<ref>...</ref>" tags.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addReferenceTags( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'To ref.', name: '', tooltip: 'Frame an external link with <ref>...</ref> tags.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return convertToReference( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'To Off.', name: '', tooltip: 'Convert a formal reference of an official website to a templated one.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return convertToOfficelTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Art. conn. ►', name: '', tooltip: 'Extract a list of related articles from a string contening some internal links.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return makeRelatedArticlesList( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'List ►', name: '', tooltip: 'Format a wiki list according to french typographical conventions.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return formatList( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Gallery ►', name: '', tooltip: 'Format a wiki gallery...', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return formatGallery( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Frm [[:lg:', name: '', tooltip: 'Format an interlanguage link. E.g.: "[[:en:Abc" to "{{lien|langue=en|trad=Abc...".', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return formatInterlangLink( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'File ►', name: '', tooltip: 'Globally clean [[File:]] wiki code.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return normalizeFilesTmpl( selection ); } },
{ linkTitle: '+ "." to <ref>', name: '', tooltip: 'Insert a final "." to a reference when missing.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return addFinalPeriodToReference( selection ); } },
{ linkTitle: 'Titles ►', name: '', tooltip: 'Add spaces globally in the titles when needed (ex.: "==ABC==" becomes "== ABC ==").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return formatSectionTitle( selection ); } },
{ linkTitle: '- bold', name: '', tooltip: 'Remove the wiki bold tags.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return removeBoldTags( selection ); } },
{ linkTitle: '- italic', name: '', tooltip: 'Remove the italic tags.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return removeItalicTags( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Century ►', name: '', tooltip: 'Globally clean century statements.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return updateCenturyTmpl( selection ); } },
{ linkTitle: '{{av JC}}', name: '', tooltip: 'Format globally any "av. J.-C." expression.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: false, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return formatAvJC( selection ); } },
{ linkTitle: 'Clean réf.', name: '', tooltip: 'Include extra templates in main template (ex.: "{{en}} {{Lien web|" becomes "{{Lien web|langue=en|").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return normalizeReference( selection ); } },
{ linkTitle: 'Remove tmpl', name: '', tooltip: 'Remove a template (ex.: "{{unité|14|heures}}" becomes "14 heures").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return clearTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: '+ Chem. tmpl', name: '', tooltip: 'Add a "formule chimique" template (ex. : "C<sub>7</sub>H<sub>5</sub>O" devient "{{formule chimique|C|7|H|5|O}}").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return addFormuleChimiqueTemplate( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'nb ► nobr', name: '', tooltip: 'Replace "unité" by nobr "unité" templates (ex.: "{{unité|3|fois}}" becomes "{{nobr|3 foiss}}").', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: function ( txt ) { return substituteNobrForNb( txt ); }, asButton: true, addTmplDeferred: false, global: false, globalAction: null },
{ linkTitle: 'Spec.', name: '', tooltip: 'Special function executing code temporarily useful. Current action: arrange artilce about swedish localities.', suffix: '', paramsCount: 1, cleanSelection: null, addTmpl: null, asButton: true, addTmplDeferred: false, global: true, globalAction: function ( selection ) { return specialFunction( selection ); } }
],
// Set whether an action is globally applied.
globalAction = false,
// A function to translate in french some "file" template parameters' names.
normalizeFilesTmpl = function ( editorText ) {
var startFileTmplIdx = 0, startLinkTagIdx = 0, endLinkTagIdx = 0, backStartLinkTagIdx = 0, oldTemplate, newTemplate;
editorText = editorText.replace( /\[\[(file|image|fichier):/ig, '[[Fichier:' ).replace( /\s{1,3}\]\]/ig, ']]' ).replace( /\s?\|\s/g, '|' ) ;
// Add a "." just before the template's end tag.
while ( startLinkTagIdx >= 0 ) {
startLinkTagIdx = editorText.indexOf( '[[Fichier:', endLinkTagIdx );
startFileTmplIdx = startLinkTagIdx;
if ( startLinkTagIdx >= 0 ) {
do {
endLinkTagIdx = editorText.indexOf( ']]', startLinkTagIdx + 2 );
if ( endLinkTagIdx >= 0 ) {
backStartLinkTagIdx = editorText.lastIndexOf( '[[', endLinkTagIdx );
if ( backStartLinkTagIdx > startLinkTagIdx ) {
// An internal link found.
startLinkTagIdx = endLinkTagIdx;
}
else {
// Clean the current template.
oldTemplate = editorText.slice( startFileTmplIdx, endLinkTagIdx + 2 );
newTemplate = cleanFileTemplate( oldTemplate );
editorText = editorText.replace( oldTemplate, newTemplate );
}
}
} while ( startLinkTagIdx == endLinkTagIdx );
endLinkTagIdx = endLinkTagIdx - ( oldTemplate.length - newTemplate.length );
}
}
return editorText;
},
// Insert a string into another string.
insert = function ( originalString, stringToInsert, position ) {
// Add a "." just before the template's end tag.
if ( originalString && stringToInsert ) {
if ( position > 0 && position <= originalString.length - 1 ) {
return originalString.slice( 0, position )
+ stringToInsert
+ originalString.slice( position );
}
}
return originalString;
},
// Clean a file template.
cleanFileTemplate = function ( template ) {
var tmplEndToken;
if ( template && template.startsWith( '[[Fichier:' ) && template.endsWith( ']]' ) ) {
// Translate parameters and remove useless ones.
template = template.replace( '|left', '|gauche' )
.replace( /\|thumb(nail)?/i, '|vignette' )
.replace( '|upright', '|redresse' )
.replace( /\|(droite|right)/i, '' );
// Remove useless image's width.
template = template.replace( /\|(\d{3})px/i, function ( match, capture1 ) {
var imgWidth = Number( capture1 );
if ( imgWidth >= 120 && imgWidth <= 240 ) {
return '';
}
return match;
} );
// Get the last parameter's value.
tmplEndToken = template.slice( template.lastIndexOf( '|' ), template.length - 2 );
if ( tmplEndToken.charAt( tmplEndToken.length - 1 ) != '.' ) {
// Add a "." just before the template's end tag.
if ( tmplEndToken.search( /^\|(vignette|gauche|redresse|link=|\d{1,3}p?x)/m ) == -1 ) {
template = insert( template, '.', template.length - 2 );
}
}
}
return template;
},
// Adjust the "century" template.
updateCenturyTmpl = function ( editorText ) {
return editorText.replace( /(\{\{s(\smini)?-?\|[IVX]{1,5})\|e\}\}/ig, '$1}}' )
.replace( /\{\{([IVX]{2,5})e siècle\}\}/ig, '{{s|$1}}' )
.replace( /(\{\{s2-?\|[IVX]{1,5})\|e\|([IVX]{1,5})\|e\}\}/ig, '$1|$2}}' );
},
// Insert a "." before "</ref>" when needed.
addFinalPeriodToReference = function ( editorText ) {
return editorText.replace( /<ref>\s{1,4}/g, '<ref>' )
.replace( /([^\.])\s{0,4}<\/ref>/g, '$1.</ref>' )
.replace( /\.\s?\.<\/ref>/g, '.</ref>' )
.replace( /\.(\}\}|\]).<\/ref>/g, '$1.</ref>' );
},
// Replace "unité" or "nombre" name's template by "nobr" (ex.: "{{unité|24|jours}}" becomes "{{nobr|24 jours}}".
substituteNobrForNb = function ( txt ) {
if ( txt.search( /\{\{(unité|nombre|nb)\s{0,4}\|/i ) == -1 ) { // Template's name checking.
return txt;
}
var tmplTxt = clearTemplate( txt ), // Ex.: "{{nb|2|ans}}" becomes "2 ans".
spaceIndex = tmplTxt.indexOf( ' ' );
if ( spaceIndex > 0 ) {
let valuePart = tmplTxt.slice( 0, spaceIndex );
if ( valuePart.search( /[\.,]/ ) == -1 ) {
if ( spaceIndex > 3 ) { // More than three digits number.
return txt;
}
}
else {
let valueParts = valuePart.split( /[\.,]/ );
if ( valueParts.length > 2 ) {
return txt; // Abnormal case.
}
else {
if ( valueParts[0].length > 3 || valueParts[1].length > 3 ) {
return txt; // More than three digits number.
}
txt = txt.replace( /[\.]/, ',' );
}
}
}
if ( spaceIndex <= 2 ) { // One or two digits number.
value = Number( tmplTxt[0] + tmplTxt[1].trim() );
if ( value <= 16 ) {
return mw.libs.frDigits[ value - 1 ] + tmplTxt.slice( spaceIndex );
}
}
return txt.replace( /\{\{(unité|nombre|nb)\s{0,4}\|/i, '{{nobr@' )
.replace( /\|/ig, ' ' )
.replace( /nobr@/, 'nobr|' );
},
// Include extra templates in main template (ex.: "{{en}} {{Lien web|" becomes "{{Lien web|langue=en|").
normalizeReference = function ( editorText ) {
var pattern = /(\{\{pdf\}\})?\s{0,4}((\{\{[a-z]{2}\}\}\s{0,4}){1,5})\{\{(lien\s?web|ouvrage|article|lien brisé|chapitre)\s{0,4}\|/ig;
return editorText.replace( pattern, function ( match, capture1, capture2, capture3, capture4 ) {
var result;
capture2 = capture2.trim();
capture2 = capture2.slice( 2, capture2.length - 2 ).replace( /\}\}\s{0,4}\{\{/g, '+' );
result = '{{' + capture4 + '|langue=' + capture2 + '|';
if ( capture1 && capture1.search( /pdf/i ) >= 0 ) {
result += 'format=pdf|';
}
return result;
} )
.replace( /((\{\{[a-z]{2}\}\}\s{0,4}){0,5})(\{\{pdf\}\})\s{0,4}\{\{(lien web|ouvrage|article|chapitre)\s{0,4}\|/ig, function ( match, capture1, capture2, capture3, capture4 ) {
var result;
if ( capture1 ) {
capture1 = capture1.trim();
capture1 = capture1.slice( 2, capture1.length - 2 ).replace( /\}\}\s{0,4}\{\{/g, '+' );
result = '{{' + capture4 + '|langue=' + capture1 + '|format=pdf|';
}
else {
result = '{{' + capture4 + '|format=pdf|';
}
return result;
} )
.replace( /\|\s{0,4}(date|consulté le)\s{0,4}=\s{0,4}((1\{\{)|(\{\{1))er\}\}/ig, '|$1=1' )
.replace( /\|\s{0,4}(date|consulté le)\s{0,4}=\s{0,4}(\{\{date[^\}]+\}\})/ig, function ( match, capture1, capture2 ) {
return '|' + capture1 + '=' + clearTemplate( capture2 ).replace( '1er ', '1 ' );
} )
.replace( /(\|langue=[a-z]{2})\|\s{0,4}langue\s{0,4}=\s{0,4}[a-z]{2}/gi, '$1' ); // Remove duplicates.
},
// Special function executing code temporarily useful.
// Current action: arrange artilce about swedish localities.
specialFunction = function ( editorText ) {
return editorText.replace( 'per km<sup>2</sup>', 'per {{unité|km2}}' )
.replace( '|taille=30', '' )
.replace( /unité\|(\d{2,3})\|/i, 'nobr|$1 ' );
},
// Replace "|" in "date" and "unité" templates (ex.: "{{date|24|juin|2001}}" becomes "{{date|24 juin 2001}}".
removePipes = function ( editorText ) {
// Replace the "nombre" template, a redirect to the "unité" template.
if ( editorText.search( /\{\{(nombre|nb)/gi ) >= 0 ) {
editorText = editorText.replace( /\{\{(nombre|nb)/gi, '{{unité' );
}
// Replace "1er" by "1" in each "date" template.
if ( editorText.search( /\{\{\s?date-?\|\s?((\{\{1er\}\})|(1\{\{er\}\})|(1er))/gi ) >= 0 ) {
editorText = editorText.replace( /\{\{\s?(date-?)\|\s?((\{\{1er\}\})|(1\{\{er\}\})|(1er))/gi, '{{$1|1' );
}
// In case of a selected text.
if ( globalAction === false && !editorText.endsWith( '}}}}' ) ) {
// Add a "," so that the pattern will be below recognised.
editorText += ',';
}
// Replace "|" in "unité" or "date" templates.
return editorText.replace( /(\{\{\s?(unité|date-?)\|)([^\}]+\}\})([\s\.,\/\)<]|\}\})/ig,
function ( match, capture1, capture2, capture3, capture4 ) {
var matchIsDate = false, result;
// No "|" to remove.
if ( capture3.indexOf( '|' ) < 0 ) {
// In case of a selected text.
if ( globalAction === false && capture4 == ',' ) {
// Discard the added ",".
match = match.slice( 0, match.length - 1 );
}
return match;
}
if (capture2.toLowerCase().startsWith( 'date' ) ) {
matchIsDate = true;
if ( capture3.indexOf( '=' ) >= 0 ) {
// At least one extra option is defined.
return match;
}
else if ( capture3.indexOf( 'en ' ) >= 0
|| capture3.indexOf( 'dans ' ) >= 0
|| capture3.indexOf( 'au ' ) >= 0 ) {
// A qualification is defined.
return match;
}
}
else {
if ( capture3.indexOf( '°C' ) >= 0 ) {
// A temperature.
return match;
}
// Swith to french number notation for the "unité" template and ajust exponent if any.
capture3 = capture3.trim().replace( /(,(\d{3}))?,(\d{3})\.(\d{1,6})\s?\|/, '$2$3,$4|' )
.replace( /(\d{1,9})\.(\d{1,6})\s?\|/, '$1,$2|' )
.replace( /\{\{(-?[1-3])\}\}/, ' $1' );
}
// Spare "|" in an internal link.
if ( capture3.search( /\|[^\[\]\|]+\]\]/i ) >= 0 ) {
capture3 = capture3.replace( /\|([^\[\]\|]+\]\])/i, '@Z@$1' );
}
// In case of a selected text.
if ( globalAction === false && capture4 == ',' ) {
// Discard the added ",".
result = capture1 + capture3.replace( /\s?\|\s?/g, ' ' ).trim().replace( /@Z@/, '|' );
if ( matchIsDate ) {
return result;
}
return result.replace( /\s(\d\}\})/, '$1' );
}
result = capture1 + capture3.replace( /\s?\|\s?/g, ' ' ).trim().replace( /@Z@/, '|' ) + capture4;
if ( matchIsDate ) {
return result;
}
return result.replace( /\s(\d\}\})/, '$1' );
} );
},
// Add "{{nobr|...}}" globally or on a selected text.
addNoBrTemplate = function ( editorText ) {
// Control the main captures of the replace calls below.
var ctrlCapture = function ( capture ) {
var captureToken,
discardedWords = [ 'à', 'et', 'ou', 'en', 'au', 'du', 'de', "d'", 'pour', 'dans' ];
// Avoid to format dates and strings like "XX et/à/ou/de".
if ( capture ) {
captureToken = capture.split( ' ' )[1];
if ( captureToken && ( mw.libs.frMonths.indexOf( captureToken.toLowerCase() ) === -1
&& discardedWords.indexOf( captureToken ) === -1 ) ) {
return true;
}
return false;
}
},
getNewText = function ( match, capture ) {
if ( ctrlCapture( capture ) ) {
return match.replace( capture, '{{nobr|' + capture + '}}' );
}
return match;
};
// In case of a selected text.
if ( globalAction === false ) {
return '{{nobr|' + editorText + '}}';
}
// In case of the whole text.
// Ex.: replace " 0 à 24 ans " by " 0 à {{nobr|24 ans}} ".
editorText = editorText.replace( /([>\*,:;a-zàé]\s|['\(])(?:\d{1,3}|\d{1,3},\d{1,3})\s(à|et|ou|en|au|du|de)\s((?:\d{1,3}|\d{1,3},\d{1,3})\s[éèêïîû/a-z]+)([\s\.,<'\)])/ig,
function ( match, capture1, capture2, capture3, capture4 ) {
return getNewText( match, capture3 );
} );
// Ex.: replace " 24 km " by " {{nobr|24 km}} ".
editorText = editorText.replace( /([>\*,:;a-zàé]\s|['\(]|\d{1,3}-)((?:\d{1,3}|\d{1,3},\d{1,3})\s[éèêïîû/a-z]+)([\s\.,<'\)])/ig,
function ( match, capture1, capture2, capture3 ) {
return getNewText( match, capture2 );
} );
return editorText;
},
// Remove "'''" tags.
removeBoldTags = function ( editorText ) {
return editorText.replace( /([^'])'''([a-z\d])'''([^'])/ig, '$1$2$3' )
.replace( /([^'])'''([^'])/ig, '$1$2' )
.replace( /([ld])''''([^'])/ig, "$1'$2" )
.replace( /'''''([^'])/ig, "''$1" );
},
// Remove "''" tags.
removeItalicTags = function ( txt ) {
if ( txt && txt.startsWith( "''" ) && txt.endsWith( "''" ) ) {
txt = txt.slice( 2, txt.length - 2 );
}
return txt;
},
// Remove template's markers (ex.: "{{unité|14|heures}}" becomes "14 heures").
clearTemplate = function ( txt ) {
if ( txt && txt.startsWith( '{{' ) && txt.endsWith( '}}' ) ) {
if ( txt.indexOf( '|' ) >= 0 ) {
if ( txt.startsWith( '{{lang' ) ) {
txt = txt.replace( /\|/, '' );
}
return txt.slice( txt.indexOf( '|' ) + 1, txt.length - 2 ).replace( /\|/g, ' ' );
}
return txt.slice( 2, txt.length - 2 );
}
return txt;
},
// Add globally spaces in sections's titles when needed (ex.: "==ABC==" becomes "== ABC ==").
formatSectionTitle = function ( editorText ) {
return editorText.replace( /^(={2,5})([^\s=])/igm, '$1 $2' )
.replace( /([^\s=])(={2,5})$/igm, '$1 $2' );
},
// Format globally any "av. J.-C." expression.
formatAvJC = function ( editorText ) {
return editorText.replace( /av\.?\s?J\.?-?C\.?/ig, '{{av JC}}' );
},
// Selection cleaner function for the "heure" template.
removeHourSymbol = function ( txt ) {
if ( txt ) {
return txt.replace( /\s?h(eure)?s?(\set)?\s?/i, ' ' )
.replace( /\s?min(ute)?s?(\set)?\s?/i, ' ' );
}
return txt;
},
// Selection cleaner function for the "unité" template.
cleanBeforeAddingUnitTemplate = function ( txt ) {
if ( txt ) {
// Remove the HTML space.
txt = removeSpaceInNumber( txt );
if ( txt.indexOf( 'm²' ) > 0 ) {
txt = txt.replace( 'm²', 'm2' );
}
else if ( txt.indexOf( '<sup>2</sup>' ) > 0 ) {
txt = txt.replace( '<sup>2</sup>', '2' );
}
}
return txt;
},
// Remove useless spaces in a string containing some numbers.
removeSpaceInNumber = function ( txt ) {
if ( txt ) {
// Remove the HTML space.
txt = txt.replace( ' ', ' ' );
if ( txt.search( /\d\s\d/gi ) >= 0 ) {
return txt.replace( /(\d)\s(\d)/gi, '$1$2' );
}
}
return txt;
},
// Convert an external link to a wiki reference.
convertToReference = function ( txt ) {
var protocolIdx, titleIdx, title;
// External link example: [http://www.site.fr/mapage.html ma page].
if ( txt && txt.startsWith( '[' ) && txt.endsWith( ']' ) ) {
protocolIdx = txt.indexOf( '://' );
if ( protocolIdx > 0 ) {
// Get the link's title.
titleIdx = txt.indexOf( ' ', protocolIdx );
if ( titleIdx > 0 ) {
title = txt.substring( titleIdx + 1, txt.length - 1 ).trim();
if ( title ) {
return title + '<ref>' + txt + '.</ref>';
}
}
}
}
return txt;
},
// Convert a formal reference of an official website to a templated one.
convertToOfficelTemplate = function ( txt ) {
var protocolIdx, titleIdx, url, urlIdx, languageCode = '', languageCodeIdx;
// Example: * {{ja}} [http://www.town.koya.wakayama.jp/ Site officiel de Kōya].
if ( txt && txt.startsWith( '*' ) && txt.endsWith( ']' ) ) {
protocolIdx = txt.indexOf( '://' );
if ( protocolIdx > 0 ) {
// Get the url.
titleIdx = txt.indexOf( ' ', protocolIdx );
urlIdx = txt.lastIndexOf( 'h', protocolIdx );
if ( titleIdx > 0 && urlIdx > 0 ) {
url = txt.substring( urlIdx, titleIdx );
if ( url ) {
languageCodeIdx = txt.search( /\{\{[a-z]{2}\}\}/ );
if ( languageCodeIdx > 0 ) {
languageCode = txt.slice( languageCodeIdx + 2, languageCodeIdx + 4 );
}
return '* {{Site officiel|langue=' + languageCode + '|url=' + url + '}}';
}
}
}
}
return txt;
},
// Internal link dewikification.
removeInternalLink = function ( txt, pageName ) {
if ( txt && txt.startsWith( '[[' ) && txt.endsWith( ']]' ) ) {
txt = txt.slice( 2, txt.length - 2 );
if ( txt.indexOf( '|' ) > 0 ) {
if ( pageName ) {
return txt.slice( 0, txt.indexOf( '|' ) );
}
return txt.slice( txt.indexOf( '|' ) + 1 );
}
}
return txt;
},
// Remove useless spaces in a selected text (typically: " | ", " }}" and " = ".
removeUselessSpaces = function ( txt ) {
if ( txt ) {
if ( /(\s{1,8}\|\s{1,8})|(\s{1,8}\|)|(\|\s{1,8})/.test( txt ) ) {
txt = txt.replace( /(\s{1,8}\|\s{1,8})|(\s{1,8}\|)|(\|\s{1,8})/g, '|' );
}
if ( /(\s{1,8}\|\s{1,8})|(\s{1,8}=)|(=\s{1,8})/.test( txt ) ) {
txt = txt.replace( /(\s{1,8}=\s{1,8})|(\s{1,8}=)|(=\s{1,8})/g, '=' );
}
if ( /\s{1,8}\}\}/.test( txt ) ) {
return txt.replace( /\s{1,8}\}\}/, '}}' );
}
}
return txt;
},
// Replace a "formatnum" template by an "Unité" one, when relevant.
replaceFormatnumByUnit = function ( txt ) {
if ( txt ) {
if ( txt.toLowerCase().startsWith( '{{nombre|' ) ) {
txt = txt.replace( '{{nombre|', '{{formatnum:' );
}
if ( txt.indexOf( 'm²' ) > 0 ) {
txt = txt.replace( 'm²', 'm2' );
}
}
if ( txt && txt.toLowerCase().startsWith( '{{formatnum:' ) ) {
// Switch to decimal french notation.
txt = txt.replace( ' ', ' ' ).replace( /(\d)\.(\d)/g, '$1,$2' );
// {{unité|10000 à 15000 tonnes}} pour {{formatnum:10000}} à {{Unité|15000 tonnes}}
if ( txt.search( /\s(à|entre|et|ou)\s/i ) >= 0 ) {
txt = '{{unité|' + txt.replace( /(\{\{formatnum:)|(\{\{(unité|nombre)\|)/ig, '' )
.replace( /\}\}/g, '' ).replace( ' ', ' ') + '}}';
}
else {
//Ex.: "{{formatnum:5000}} euros" into "{{unité|5000 euros}}".
txt = txt.split( ':' )[1].replace( /\}\}\s{1,3}/, ' ' );
// Format the current text with the "Unité" template.
txt = '{{unité|' + txt + '}}';
}
if ( txt.split( '|' ).length >= 3 ) {
return removePipes( txt );
}
}
return txt;
},
// Add a "formule chimique" template (ex. : "C<sub>7</sub>H<sub>5</sub>O" devient "{{formule chimique|C|7|H|5|O}}").
addFormuleChimiqueTemplate = function ( txt ) {
if ( txt && txt.indexOf( '<sub>' ) > 0 ) {
txt = '{{formule chimique|' + txt.replace( /<\/?sub>/g, '|' ) + '}}';
txt = txt.replace( '|}}', '}}' ).replace( '=', '{{=}}' );
}
return txt;
},
// Replace a "{{...}} ABC" expression by "{{...|ABC}}".
compactTemplate = function ( txt ) {
if ( txt && txt.startsWith( '{{' ) ) {
//Ex.: "{{2e}} étape" into "{{2e|étape}}".
return txt.replace( /\}\}\s{0,2}/, '|' ).concat( '}}' );
}
return txt;
},
// Replace a "p.(/page) nnn" expression by "{{p.|nnn}} (note: "p", "pp" or "pp." are converted to "p.").
addPageTemplate = function ( txt ) {
if ( txt && txt.startsWith( 'p' ) ) {
//Ex.: "p. 254" into "{{p.|254}}".
return txt.replace( /page(s)?/, 'p.' ).replace( /pp?\.?\s{0,2}/i, '{{p.|' ).concat( '}}' );
}
return txt;
},
// format a list according to french typographical conventions.
formatList = function ( txt ) {
if ( txt && txt.startsWith( '*' ) ) {
txt = txt.replace( /^\*\s{0,2}([^\s])/mg, function ( match, capture1 ) {
return '* ' + capture1.toLowerCase();
} ).replace( /\s{0,3}[\.,;\s]\s{0,3}$/mg, ' ;' )
.replace( /([^\.,;\n])$/mg, '$1 ;' );
return txt.substr( 0, txt.lastIndexOf( ' ;' ) ) + '.';
}
return txt;
},
// Extract a list of related articles from a string contening some internal links.
makeRelatedArticlesList = function ( txt ) {
if ( txt ) {
var startLinkTagIdx = 0, endLinkTagIdx = 0, internalLink, linksList = '';
// Add a "." just before the template's end tag.
while ( startLinkTagIdx >= 0 ) {
startLinkTagIdx = txt.indexOf( '[[', endLinkTagIdx );
if ( startLinkTagIdx >= 0 ) {
endLinkTagIdx = txt.indexOf( ']]', startLinkTagIdx + 2 );
if ( endLinkTagIdx >= 0 ) {
internalLink = txt.substring( startLinkTagIdx, endLinkTagIdx + 2 );
internalLink = removeInternalLink( internalLink, true );
internalLink = internalLink.slice( 0, 1 ).toUpperCase() + internalLink.slice( 1 );
linksList += '\n* [[' + internalLink + ']]';
}
}
}
if ( linksList ) {
return linksList.replace( '\n', '' );
}
}
return txt;
},
// format a gallery according to french typographical conventions and wiki standards.
formatGallery = function ( txt ) {
if ( txt ) {
txt = txt.replace( /\s{1,3}$/mg, '' )
.replace( /\s?\|\s/mg, '|' );
if ( txt.search( /center\s?>/i ) >= 0 ) {
txt = txt.replace( /\.?\s{0,3}<\/center\s?>/gi, '.</center>' );
}
txt = txt.replace( /([^>\.])$/mg, '$1.' );
}
return txt;
},
// Format an interlanguage link (e.g.: "[[:en:Abc|Cba" to "{{lien|langue=en|trad=Abc|fr=Cba...").
formatInterlangLink = function ( txt ) {
if ( txt && txt.startsWith( '[[:' ) && txt.endsWith( ']]' ) ) {
// No alternate text to the wiki link.
if ( txt.indexOf( '|' ) < 0 ) {
return txt.replace( /\[\[:([a-z]{2}):/, '{lien|langue=$1|trad=' ).replace( ']]', '}}' );
}
txt.replace( /\[\[:([a-z]{2}):([^\|]+)\|([^\]]+)\]\]/i,
function ( match, capture1, capture2, capture3 ) {
txt = '{{lien|langue=' + capture1 + '|trad=' + capture2;
if ( capture2.toLowerCase() != capture3.toLowerCase() ) {
txt = txt + '|fr=' + capture3;
}
txt = txt + '}}';
} );
}
return txt;
},
// Format century.
addCenturyTemplate = function ( txt ) {
var centuries = '', first =true;
if ( txt && txt.search( /\set\s/i ) >= 0 ) {
// Handle two centuries in one template (ex.: "XIe et XIIe siècles" becomes "{{s2-|XI|XII}}").
if ( txt && txt.search( /[IXV]/ ) >= 0 ) {
txt.replace( /[IXV]{1,6}/g,
function ( match ) {
if ( first ) {
centuries = '{{s2-|' + match + '|';
first = false;
}
else {
centuries += match + '}}';
}
} );
}
txt = centuries;
}
else if ( txt && txt.search( /[IXV]/ ) >= 0 ) {
// Handle one century (ex.: "XIe siècle" becomes "{{s-|XI}}").
txt.replace( /[IXV]{1,6}/,
function ( match ) {
txt = '{{s-|' + match + '}}';
} );
}
return txt;
},
// Add "date" template to a selected text or globally (ex.: "1er mai [[1981]]" becomes "{{date|1 mai [[1981}}").
addDateTemplate = function ( editorText, templateName ) {
var datePattern = /(\s|\()(\{\{1er\}\}|[1-9]|[1-3][0-9])\s[adfjmnos][aceéouv][cinprtûv][beilmnorstv]{0,6}\s[1-9][0-9]{2,3}/gi,
alterDatePattern = /(\d\d?)(\/|-)(\d\d?)(\/|-)(\d{2,4})/;
// In case of a selected text.
if ( globalAction === false ) {
if ( editorText ) {
// Clean dates like "31/05/1940" or "05/12/2010".
if ( editorText.search( /(\d\d?)[\/-](\d\d?)[\/-](\d{4})/i ) >= 0 ) {
editorText = editorText.replace( /(\d\d?)[\/-](\d\d?)[\/-](\d{4})/i, function ( match, capture1, capture2, capture3 ) {
return capture1 + ' ' + mw.libs.frMonths[ parseInt( capture2 ) - 1 ] + ' ' + capture3;
} );
}
// Clean dates like "{{1er}} octobre 1940".
if ( editorText.search( /(\{\{1er\}\})|(1er)/i ) >= 0 ) {
editorText = editorText.replace( /(\{\{1er\}\})|(1er)/i, '1' );
}
// Remove wiki link tags for the year.
if ( editorText.search( /\[\[(\d{4})\]\]/ ) >= 0 ) {
editorText = editorText.replace( /\[\[(\d{4})\]\]/, '$1' );
}
// Clean dates like "{{1er}} octobre 1940".
if ( editorText.search( alterDatePattern ) >= 0 ) {
editorText = editorText.replace( alterDatePattern, function ( match, capture1, capture2, capture3, capture4, capture5 ) {
return capture1 + ' ' + mw.libs.frMonths[ parseInt( capture3 ) - 1 ] + ' ' + capture5;
} );
}
editorText = toggleTextToLowerCase( editorText );
return mw.libs.fillTemplate( templateName, [ editorText ] );
}
}
else if ( editorText ) {
editorText = editorText.replace( datePattern, function ( match ) {
var newText = toggleTextToLowerCase( match.replace( /(\{\{1er\}\})|(1er)/i, '1' ) );
return " " + mw.libs.fillTemplate( templateName, [ newText.slice( 1 ) ] );
} );
}
return editorText;
},
// Add "formatnum" template to a selected text.
formatNum = function ( txt ) {
if ( txt ) {
// Format the number.
txt = txt.replace( /\s/g, '' ).replace( ',', '.' );
if ( $.isNumeric( txt ) ) {
return '{{formatnum:' + txt + '}}';
}
}
return txt;
},
// Add "Dunit" template to a selected text (ex.: "20 × 15 m" becomes "{{dunité|20|15|m}}").
// NB: expressions ending with an squared, cubed, etc. unit like "10 × 10 km2" is not handled...
addDunitTemplate = function ( txt ) {
var lastChar, unit;
if ( txt && txt.search( /\s?[Xx×]\s?/ ) > 0 ) {
// Format numbers.
txt = txt.replace( /(\d)\s(\d)/g, '$1$2' );
txt = '{{dunité|' + txt.replace( /\s?[Xx×]\s?/, '|' );
lastChar = txt.slice( txt.length - 1 );
// No unit at then end of the string.
if ( $.isNumeric( lastChar ) ) {
return txt + '}}';
}
// A unit is available at the end of the string.
unit = txt.slice( txt.lastIndexOf( ' ' ) ).trim();
txt += '}}';
return txt.replace( ' ' + unit + '}}', '|' + unit + '}}' );
}
},
// Toggle a selected text to lower case.
toggleTextToLowerCase = function ( txt ) {
if ( txt ) {
return txt.toLowerCase();
}
return txt;
},
// Change ''«...»'' into « ''...'' ».
arrangeQuotes = function ( txt ) {
if ( txt ) {
if ( ( txt.startsWith( "''«" ) && txt.endsWith( "»''" ) )
|| ( txt.startsWith( '"«' ) && txt.endsWith( '»"' ) )
|| ( txt.startsWith( '``«' ) && txt.endsWith( '»´´' ) )
|| ( txt.startsWith( '‘‘«' ) && txt.endsWith( '»’’' ) )
|| ( txt.startsWith( '“«' ) && txt.endsWith( '»”' ) ) ) {
return txt.replace( /["'‘`“]{1,2}«\s?/, "« ''" ).replace( /\s?»["'’´”]{1,2}/, "'' »" );
}
}
return txt;
},
// Add "<ref>... .</ref>" tags to a selected text.
addReferenceTags = function ( txt ) {
if ( txt ) {
txt = txt.trim();
if ( txt.startsWith( '(' ) && txt.endsWith( ')' ) ) {
txt = txt.substr( 1, txt.length - 2 );
}
return '<ref>' + txt + '.</ref>';
}
return txt;
},
// 'Encapsulate a selected texte in the "{{incise|...}}" template.'
addInciseTemplate = function ( txt ) {
if ( txt ) {
txt = txt.trim();
if ( txt.search( /^[\-–—]/ ) === 0 ) {
// Note: three variations of « tiret cadratin » are checked.
txt = txt.replace( /^[\-–—]\s{0,3}/, '{{incise|' );
if ( txt.search( /[\-–—]$/ ) === txt.length - 1 ) {
return txt.replace( /\s{0,3}[\-–—]$/, '}}' );
}
if ( txt.endsWith( '.' ) ) {
return txt.replace( /\.$/, '|stop}}.' );
}
return txt + '}}';
}
}
return txt;
},
// Surround a selected text by "{{" and "}}".
addWikiTemplateTags = function ( txt ) {
if ( txt ) {
return '{{' + txt + '}}';
}
return txt;
},
// Surround by "{{" and "}}" and replace the middle blank or " " by a "|".
addWikiTemplateTagsAndMiddlePipe = function ( txt ) {
if ( txt ) {
return addWikiTemplateTags( txt ).toLowerCase().replace( /( )|\s/, '|' );
}
return txt;
},
// Insert a parameter's name, if available, and a value to "|".
addParamAndValue = function ( txt, paramName, paramValue ) {
if ( txt == '|' ) {
if ( paramName ) {
return '|' + paramName + '=' + paramValue + '|';
}
else {
return '|' + paramValue + '|';
}
}
return txt;
},
// A function to replace english quotation marks by french ones or add french quotation marks.
addFrenchQuotes = function ( txt ) {
if ( txt) {
if ( txt.search( /^(‘‘)|(``)/ ) === 0 ) {
txt = '« ' + txt.substring( 2 );
}
else if ( txt.search( /^["“‘]/ ) === 0 ) {
txt = '« ' + txt.substring( 1 );
}
else {
return '« ' + txt.trim() + ' »';
}
if ( txt.search( /(’’)|(´´)$/ ) === txt.length - 1 ) {
txt = txt.substring( 0, txt.length - 2 ) + ' »';
}
else if ( txt.search( /["”’]$/ ) === txt.length - 1 ) {
txt = txt.substring( 0, txt.length - 1 ) + ' »';
}
}
return txt;
},
// Format a selected text with a template.
addTemplate = function ( selectedText, tmplDescriptor ) {
var paramValues = [];
if ( selectedText ) {
selectedText = selectedText.trim();
if ( selectedText ) {
// tmplDescriptor.paramsCount = 1, the selected text is handled as one template's parameter.
// tmplDescriptor.paramsCount = -1, the selected text is a set of string tokens separated by a space character ; each token is a template's parameter value.
if ( tmplDescriptor.paramsCount == -1 ) {
if ( selectedText.indexOf( ' ' ) >= 0 ) {
paramValues = selectedText.split( ' ' );
}
else {
paramValues.push( selectedText );
}
}
else if ( tmplDescriptor.paramsCount == 1 ) {
paramValues.push( selectedText );
}
if ( tmplDescriptor.suffix ) {
paramValues.push( tmplDescriptor.suffix );
}
selectedText = mw.libs.fillTemplate( tmplDescriptor.name, paramValues );
}
}
return selectedText;
},
// Apply a template to the current selection.
applyTemplate = function ( tmplDescriptor, currentSelection ) {
if ( currentSelection && currentSelection.length > 0 ) {
if ( tmplDescriptor.cleanSelection !== null ) {
//Arrange the selected text before applying the template.
currentSelection = tmplDescriptor.cleanSelection( currentSelection );
}
if ( tmplDescriptor.addTmpl !== null ) {
// A non standard template's application on current selection.
if ( tmplDescriptor.addTmplDeferred ) {
// Get user's input first (the selection's update is deferred).
tmplDescriptor.addTmpl( currentSelection ).done( function ( txt ) {
updateSelection( txt );
} );
}
else {
updateSelection( tmplDescriptor.addTmpl( currentSelection ) );
}
}
else {
// Standard template's application on current selection.
updateSelection( addTemplate( currentSelection, tmplDescriptor ) );
}
}
},
// Update a selected text.
updateSelection = function ( newText ) {
if ( newText ) {
//Replace the selected text with the new text.
$wikiEditor.textSelection( 'encapsulateSelection', { pre: newText, replace: true } );
}
},
ddlWikitextOptions = [],
ddlInternalLinkOptions = [],
ddlTemplatesOptions = [],
ddlBasicOption = {
label: '',
action: {
type: '',
options: {}
}
},
// Some wikitext blocks ready to be added in article.
wikitextOptionsList = [
{ label: '|frmt pdf', wikitext: '|format=pdf' },
{ label: '|auteur insti.', wikitext: '|auteur institutionnel=' },
{ label: '|éditeur', wikitext: '|éditeur=' },
{ label: '|langue en', wikitext: '|langue=en' },
{ label: 'Réf. date', wikitext: '|année=|mois=|jour=' },
{ label: 'Access date', wikitext: 'consulté le=' + mw.libs.getCurrentDate() },
{ label: '{{pdf}}', wikitext: '{{pdf}} ' },
{ label: '|redresse', wikitext: '|redresse' },
{ label: 'Notes et réfs', wikitext: '== Notes et références ==\n{{Références}}' },
{ label: 'Notes et réfs+', wikitext: '== Notes et références ==\n=== Notes lexicales bilingues ===\n{{Références|groupe=l}}\n\n=== Références ===\n{{Références}}' },
{ label: 'See also', wikitext: '== Voir aussi ==\n=== Articles connexes ===' },
{ label: 'Liens externes', wikitext: '=== Liens externes ===' },
{ label: '{{Officiel}}', wikitext: '* {{Site officiel|langue=|url=|titre=Site officiel d}}' },
{ label: 'Géo > Démo', wikitext: '== Géographie ==\n=== Démographie ===' },
{ label: 'Histo + Éco', wikitext: '== Histoire ==\n== Économie ==' }
],
// Some internal links ready to be added in article.
internalLinkOptionsList = [
{ label: 'AFP', wikitext: 'Agence France-Presse|AFP' },
{ label: 'Le Monde', wikitext: 'Le Monde' },
{ label: 'Libération', wikitext: 'Libération (journal)|Libération' },
{ label: "L'Obs", wikitext: "L'Obs" },
{ label: 'Le Figaro', wikitext: 'Le Figaro' },
{ label: 'Le Parisien', wikitext: 'Le Parisien' },
{ label: 'France Info', wikitext: 'France Info (offre globale)|France Info' },
{ label: 'Le Point', wikitext: 'Le Point' },
{ label: "L'Express", wikitext: "L'Express" },
{ label: 'Les Échos', wikitext: 'Les Échos' },
{ label: 'France 3', wikitext: 'France 3' },
{ label: 'Sud Ouest', wikitext: 'Sud Ouest' },
{ label: 'Ouest-France', wikitext: 'Ouest-France' },
{ label: 'La Dépêche', wikitext: 'La Dépêche du Midi' },
{ label: 'NYT', wikitext: 'The New York Times' },
{ label: 'Le HuffPost', wikitext: 'Le HuffPost' },
{ label: 'NASA', wikitext: 'National Aeronautics and Space Administration|NASA' }
],
// Add a dropdownlist to the wikiEditor's toolbar.
addDropdownlistToToolbar = function ( ddlName, ddlLabel, options ) {
var toolsObject = {};
if ( ddlName && options && options.length > 0 ) {
toolsObject[ ddlName ] = { label: ddlLabel,
type: 'select',
list: options,
icon: 'none'
};
$wikiEditor.wikiEditor( 'addToToolbar', {
'section': 'main',
'group': 'insert',
'tools': toolsObject
} );
}
};
// Build the list of options for the "wikitext" dropdown list.
wikitextOptionsList.forEach( function ( wikitextOption, idx ) {
var optionObject = $.extend( true, {}, ddlBasicOption );
optionObject.label = wikitextOption.label;
optionObject.action.type = 'encapsulate';
optionObject.action.options = {
pre: wikitextOption.wikitext,
};
ddlWikitextOptions[ idx ] = optionObject;
} );
// Build the list of options for the "internal links" dropdown list.
internalLinkOptionsList.forEach( function ( internalLinkOption, idx ) {
var optionObject = $.extend( true, {}, ddlBasicOption );
optionObject.label = internalLinkOption.label;
optionObject.action.type = 'replace';
optionObject.action.options = {
pre: '[[',
peri: internalLinkOption.wikitext,
post: ']]'
};
ddlInternalLinkOptions[ idx ] = optionObject;
} );
// Set the buttons to be inserted in the wikiEditor's toolbar.
tmplDescriptors.forEach( function ( tmplDescriptor, idx ) {
var groupNamePrefix = 'templates-grp', optionObject;
optionObject = Object.assign(
{},
basicToolbarButton,
{
label: tmplDescriptor.linkTitle,
action: {
type: 'callback',
execute: function () {
var currentSelection = $wikiEditor.textSelection( 'getSelection' );
if ( tmplDescriptor.global ) {
if ( currentSelection ) {
// Action on the current selected text.
updateSelection( tmplDescriptor.globalAction( currentSelection ) );
}
else {
// Action on the whole editor's text.
globalAction = true;
$wikiEditor.val( tmplDescriptor.globalAction( $wikiEditor.val() ) );
globalAction = false;
}
}
else {
// Action on a selected text.
applyTemplate( tmplDescriptor, currentSelection );
}
}
}
} );
if ( tmplDescriptor.asButton ) {
// Build a toolbar's button.
toolbarButtonArray[ 'tmplButton' + toolbarButtonsCount ] = optionObject;
toolbarButtonIds.push( idx );
toolbarButtonsCount++;
}
else {
// Add options to the "ddlTemplates" dropdownlist.
ddlTemplatesOptions[ idx - toolbarButtonsCount ] = optionObject;
}
// Create a buttons' group.
if ( toolbarButtonsCount > 0
&& ( toolbarButtonsCount % buttonsPerGroup == 0
|| idx == tmplDescriptors.length - 1 ) ) {
toolbarButtonGroups[ groupNamePrefix + groupsCount ] = { tools: toolbarButtonArray };
toolbarButtonArray = {};
groupsCount++;
}
} );
if ( ddlWikitextOptions.length > 0 ) {
// Add the "ddlWikitext" dropdownlist to the main toolbar.
addDropdownlistToToolbar( 'ddlWikitext', 'Wikitext', ddlWikitextOptions );
}
if ( ddlInternalLinkOptions.length > 0 ) {
// Add the "ddlInternalLinks" dropdownlist to the main toolbar.
addDropdownlistToToolbar( 'ddlInternalLinks', 'InternalLinks', ddlInternalLinkOptions );
}
if ( ddlTemplatesOptions.length > 0) {
// Add the "ddlTemplates" dropdownlist to the main toolbar.
addDropdownlistToToolbar( 'ddlTemplates', 'Templates', ddlTemplatesOptions );
}
// Add a new toolbar section with some groups of buttons.
$wikiEditor.wikiEditor( 'addToToolbar', {
sections: {
templatesRibbon: { // Add a new section.
type: 'toolbar',
label: 'Modèles',
filters: [ 'body.ns-0' ], // Only display the toolbar on the main namespace.
groups: toolbarButtonGroups
}
}
} );
for ( var rowsCount = 1, offset = 0; rowsCount < groupsCount ; rowsCount++ ) {
offset = buttonsPerGroup * ( rowsCount - 1 );
divGroup = 'div.group-templates-grp' + rowsCount + ' > a';
// Remove standard formatting of the toolbar's buttons.
$( divGroup ).removeClass( 'tool tool-button' ).removeAttr( 'style' ).not( 'a:last' ).after( '<b> | </b>' );
// Add a tooltip to each toolbar's links.
$( divGroup ).each( function ( elmtIdx, elmt ) { // Warning: Functions declared within loops referencing an outer scoped variable may lead to confusing semantics. ($, tmplDescriptors, toolbarButtonIds, offset)
$( elmt ).attr( 'title', tmplDescriptors[ toolbarButtonIds[ elmtIdx + offset ] ].tooltip );
} );
}
},
DesignHack = function () {
// Remove useless summary box's warnings.
$( '#editpage-copywarn' ).remove();
$( '#specialcharsets' ).remove();
// Remove useless toolbar's options.
$( '#wikiEditor-section-secondary' ).remove(); // Preview button.
$( '#wikiEditor-section-advanced' ).remove();
$( '#wikiEditor-section-characters' ).remove();
$( '#wikiEditor-section-help' ).remove();
$( 'span.tab.tab-advanced' ).remove();
$( 'span.tab.tab-characters' ).remove();
$( 'span.tab.tab-help' ).remove();
$( '#wikiEditor-section-main > div.group.group-codemirror' ).remove();
$( '#wikiEditor-section-main > div.group.group-insert' ).children( 'span' ).last().remove();
$( '#wikiEditor-section-main > div.group.group-insert' ).children( 'span' ).last().remove();
// Scroll the navigator's viewport to the wikiEditor element.
$( 'body, html' ).animate( { scrollTop: $( '#editform' ).offset().top }, 'fast', function() {
// Hide the left menu.
$( '#mw-panel' ).attr( 'style','display: none;' );
$( '#mw-navigation' ).attr( 'style','display: none;' );
//$( 'div.vector-main-menu-container' ).attr( 'style','display: none;' );
$( '#content' ).attr( 'style', 'width: 98%; margin-left: 0; padding: 2' );
} );
};
$( document ).ready( function () {
mw.loader.using( 'user.options' ).then( function () {
// This can be the string "0" if the user disabled the preference ([[phab:T54542#555387]])
if ( mw.user.options.get( 'usebetatoolbar' ) == 1 ) {
// Enable the wikiEditor's toolbar customization.
$.when(
mw.loader.using( 'jquery.textSelection' ),
mw.loader.using( 'ext.wikiEditor' )
).then( customizeToolbar ).then( DesignHack );
}
} );
} );
} ) ( mediaWiki, jQuery );
}
//</nowiki>