Uporabnik:TadejM/AFC-submit-wizard.js: Razlika med redakcijama
Videz
Izbrisana vsebina Dodana vsebina
Brez povzetka urejanja Oznaka: ročna vrnitev |
test Oznaki: zamenjano vrnjeno |
||
Vrstica 1: | Vrstica 1: | ||
/* Deprecated by [[MediaWiki:Common.js]] */ |
|||
/** |
|||
/* Popravek za Glavno stran */ |
|||
* MediaWiki:AfC-submit-wizard.js |
|||
function mainPageRenameNamespaceTab() { |
|||
* |
|||
try { |
|||
* JavaScript, ki se uporablja za predložitev osnutkov člankov v pregled. |
|||
var Node = document.getElementById( 'ca-nstab-main' ).firstChild; |
|||
* Uporablja se na strani [[Wikipedija:Članki za ustvaritev/Predložitev]]. |
|||
if ( Node.textContent ) { // Per DOM Level 3 |
|||
* Naloženo prek [[mw:Snippets/Load JS and CSS by URL]]. |
|||
document.createElement( "span" ); |
|||
* |
|||
Node.textContent = 'Glavna stran'; |
|||
* Spremembe lahko predlagate na GitHub (https://github.com/wikimedia-gadgets/afc-submit-wizard) |
|||
} else if ( Node.innerText ) { // IE doesn't handle .textContent |
|||
* ali na pogovorni strani. |
|||
document.createElement( "span" ); |
|||
* |
|||
Node.innerText = 'Glavna stran'; |
|||
* Avtor: [[:en:User:SD0001]] |
|||
} else { // Fallback |
|||
* Licenca: MIT |
|||
document.createElement( "span" ); |
|||
*/ |
|||
Node.replaceChild( Node.firstChild, document.createTextNode( 'Glavna stran' ) ); |
|||
} |
|||
/* jshint maxerr: 999 */ |
|||
} catch(e) { |
|||
/* globals mw, $, OO */ |
|||
// bailing out! |
|||
/* <nowiki> */ |
|||
} |
|||
} |
|||
(function () { |
|||
if ( mw.config.get('wgTitle') == 'Glavna stran' && ( mw.config.get('wgNamespaceNumber') == 0 || mw.config.get('wgNamespaceNumber') == 1 ) ) { |
|||
$.when( |
|||
$( mainPageRenameNamespaceTab ); |
|||
$.ready, |
|||
} |
|||
mw.loader.using([ |
|||
'mediawiki.util', 'mediawiki.api', 'mediawiki.Title', |
|||
'mediawiki.widgets', 'oojs-ui-core', 'oojs-ui-widgets' |
|||
]) |
|||
).then(function () { |
|||
if (mw.config.get('wgPageName') !== 'Wikipedija:Članki za ustvaritev/Predložitev' || |
|||
mw.config.get('wgAction') !== 'view') { |
|||
return; |
|||
} |
|||
init(); |
|||
}); |
|||
var afc = {}, ui = {}; |
|||
window.afc = afc; |
|||
afc.ui = ui; |
|||
var config = { |
|||
allowedNamespaces: [2, 4, 118, 5], // User, Wikipedia, Draft, WT |
|||
debounceDelay: 500, |
|||
redirectionDelay: 1000, |
|||
defaultAfcTopic: 'other' |
|||
}; |
|||
// TODO: move to a separate JSON subpage, would be feasible once [[phab:T198758]] is resolved |
|||
var messages = { |
|||
"document-title": "Predložitev vašega osnutka ...", |
|||
"page-title": "Predložitev vašega osnutka ...", |
|||
"fieldset-label": "Predložite svoj osnutek v pregled na Člankih za ustvaritev (ČU)", |
|||
"title-label": "Naslov osnutka", |
|||
"title-placeholder": "Vnesite naslov osnutka. Ta se običajno začne z \"Osnutek:\"", |
|||
"title-helptip": "To je treba predhodno izpolniti, če ste kliknili povezavo na strani osnutka.", |
|||
"rawclass-label": "Izberite najustreznejšo kategorijo", |
|||
"rawclass-helptip": "Za biografije o strokovnjakih izberite eno od obeh kategorij namesto ene, povezane s področjem.", |
|||
"shortdesc-placeholder": "Na kratko, z 2–5 besedami, opišite temo (npr. \"Slovenski astronom\", \"Nogometni stadion v Franciji\")", |
|||
"shortdesc-label": "Kratek opis", |
|||
"shortdesc-helptip": "Ne presezite 40 znakov", |
|||
"talktags-placeholder": "Začnite vnašati za iskanje oznak ...", |
|||
"talktags-label": "Klasifikacijske oznake wikiprojekta", |
|||
"talktags-helptip": "1-4 dodani wikiprojekti so veliko. Če na primer želite dodati oznako Fizika, vam ni treba dodati tudi oznake Znanost.", |
|||
"orestopic-placeholder": "Začnite tipkati za iskanje tem ...", |
|||
"orestopic-label": "Tematski klasifikatorji", |
|||
"orestopic-helptip": "Izberite relevantna področja teme", |
|||
"submit-label": "Predloži", |
|||
"footer-text": "<small>Če niste prepričani, kaj vnesti v polje, ga lahko preskočite. Če potrebujete dodatn pomoč, lahko zanjo zaprosite na [[Wikipedija:Forum za pomoč|Forumu za pomoč]]</b> ali dobite pomoč v živo na <b>[https://t.me/sl_wiki Telegramu]</b>.<br>Imate težave pri uporabi tega obrazca? <b>[/w/index.php?title=Pogovor o Wikipediji:Članki za ustvaritev&action=edit&preloadtitle=Te%C5%BE%0Aave%20s%20predlo%C5%BE%0Aitvijo Sporočite jih]</b>.</small>", |
|||
"submitting-as": "Predložitev kot Uporabnik:$1", |
|||
"validation-invalidtitle": "Prosimo, preverite naslov osnutka. Ta naslov ni veljaven.", |
|||
"validation-missingtitle": "Prosimo, preverite naslov osnutka. Tak osnutek ne obstaja.", |
|||
"validation-wrongns": "Prosimo, preverite naslov osnutka – začeti se mora z \"Wikipedija:Osnutki\" ali \"Uporabnik:\"", |
|||
"warning-norefs": "Ta osnutek ne vsebuje nobenih sklicev. Dodajte sklice, saj bo brez njih verjetno zavrnjen. Glejte [[Pomoč:Pomoč:Uvod v sklicevanje z vikioznačevanjem/2|pomoč za dodajanje sklicev]].", |
|||
"status-processing": "Obdelava ...", |
|||
"status-saving": "Shranjevanje strani osnutka ...", |
|||
"editsummary-main": "Predložitev z uporabo [[WP:AFCSW|AfC-submit-wizard]]", |
|||
"status-redirecting": "Predložitev je uspela. Preusmerjanje na stran osnutka ...", |
|||
"captcha-label": "Prosimo, vnesite črke, ki se pojavijo v spodnjem polju", |
|||
"captcha-placeholder": "Vnesite črke tukaj", |
|||
"captcha-helptip": "Varnostno preverjanje CAPTCHA. Ko končate, kliknite »Predloži«.", |
|||
"error-saving-main": "Prišlo je do napake ($1). Prosimo, poskusite znova ali pojdite na forum za pomoč.", |
|||
"status-saving-talk": "Shranjevanje pogovorne strani osnutka ...", |
|||
"editsummary-talk": "Dodajanje oznak wikiprojektov z uporabo [[WP:AFCSW|AfC-submit-wizard]]", |
|||
"status-talk-success": "Na pogovorno stran so bile uspešno dodane oznake wikiprojektov.", |
|||
"error-saving-talk": "Pri urejanju pogovorne strani je prišlo do napake ($1).", |
|||
"error-main": "Prišlo je do napake ($1). Prosimo, poskusite znova ali pojdite na forum za pomoč." |
|||
}; |
|||
function init() { |
|||
for (var key in messages) { |
|||
mw.messages.set('afcsw-' + key, messages[key]); |
|||
} |
|||
document.title = msg('document-title'); |
|||
$('#firstHeading').text(msg('page-title')); |
|||
var apiOptions = { |
|||
parameters: { |
|||
format: 'json', |
|||
formatversion: '2' |
|||
}, |
|||
ajax: { |
|||
headers: { |
|||
'Api-User-Agent': 'w:sl:MediaWiki:AFC-submit-wizard.js' |
|||
} |
|||
} |
|||
}; |
|||
// Two different API objects so that aborts on the lookupApi don't stop the final |
|||
// evaluate process |
|||
afc.api = new mw.Api(apiOptions); |
|||
afc.lookupApi = new mw.Api(apiOptions); |
|||
constructUI(); |
|||
} |
|||
function constructUI() { |
|||
ui.fieldset = new OO.ui.FieldsetLayout({ |
|||
label: msg('fieldset-label'), |
|||
classes: [ 'container' ], |
|||
items: [ |
|||
ui.titleLayout = new OO.ui.FieldLayout(ui.titleInput = new mw.widgets.TitleInputWidget({ |
|||
value: (mw.util.getParamValue('page') || '').replace(/_/g, ' '), |
|||
placeholder: msg('title-placeholder'), |
|||
}), { |
|||
label: msg('title-label'), |
|||
align: 'top', |
|||
help: msg('title-helptip'), |
|||
helpInline: true |
|||
}), |
|||
ui.afcTopicLayout = new OO.ui.FieldLayout(ui.afcTopicInput = new OO.ui.RadioSelectInputWidget(), { |
|||
label: msg('rawclass-label'), |
|||
help: msg('rawclass-helptip'), |
|||
align: 'inline', |
|||
}), |
|||
ui.shortdescLayout = new OO.ui.FieldLayout(ui.shortdescInput = new OO.ui.TextInputWidget({ |
|||
placeholder: msg('shortdesc-placeholder'), |
|||
maxLength: 100 |
|||
}), { |
|||
label: msg('shortdesc-label'), |
|||
align: 'top', |
|||
help: msg('shortdesc-helptip'), |
|||
helpInline: true, |
|||
}), |
|||
ui.talkTagsLayout = new OO.ui.FieldLayout(ui.talkTagsInput = new OO.ui.MenuTagMultiselectWidget({ |
|||
placeholder: msg('talktags-placeholder'), |
|||
tagLimit: 10, |
|||
autocomplete: false, |
|||
$overlay: $('<div>').addClass('projectTagOverlay').css({ |
|||
'position': 'absolute', |
|||
'z-index': '110' |
|||
}).appendTo('body') |
|||
}), { |
|||
label: msg('talktags-label'), |
|||
align: 'top', |
|||
help: msg('talktags-helptip'), |
|||
helpInline: true, |
|||
}), |
|||
// This is shown only if the ORES topic lookup fails, or is inconclusive |
|||
ui.oresTopicLayout = new OO.ui.FieldLayout(ui.oresTopicInput = new OO.ui.MenuTagMultiselectWidget({ |
|||
placeholder: msg('orestopic-placeholder'), |
|||
tagLimit: 10, |
|||
autocomplete: false, // XXX: doesn't seem to work |
|||
options: [ "biography", "women", "food-and-drink", "internet-culture", "linguistics", "literature", "books", "entertainment", "films", "media", "music", "radio", "software", "television", "video-games", "performing-arts", "philosophy-and-religion", "sports", "architecture", "comics-and-anime", "fashion", "visual-arts", "geographical", "africa", "central-africa", "eastern-africa", "northern-africa", "southern-africa", "western-africa", "central-america", "north-america", "south-america", "asia", "central-asia", "east-asia", "north-asia", "south-asia", "southeast-asia", "west-asia", "eastern-europe", "europe", "northern-europe", "southern-europe", "western-europe", "oceania", "business-and-economics", "education", "history", "military-and-warfare", "politics-and-government", "society", "transportation", "biology", "chemistry", "computing", "earth-and-environment", "engineering", "libraries-and-information", "mathematics", "medicine-and-health", "physics", "stem", "space", "technology" ].map(function (e) { |
|||
return { |
|||
data: e, |
|||
label: e |
|||
}; |
|||
}) |
|||
}), { |
|||
label: msg('orestopic-label'), |
|||
align: 'top', |
|||
help: msg('orestopic-helptip'), |
|||
helpInline: true |
|||
}), |
|||
ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ |
|||
label: msg('submit-label'), |
|||
flags: [ 'progressive', 'primary' ], |
|||
})) |
|||
] |
|||
}); |
|||
ui.footerLayout = new OO.ui.FieldLayout(new OO.ui.LabelWidget({ |
|||
label: $('<div>') |
|||
.append(linkify(msg('footer-text'))) |
|||
}), { |
|||
align: 'top' |
|||
}); |
|||
afc.topicOptionsLoaded = getJSONPage('Wikipedija:Članki za ustvaritev/AfC topic map.json').then(function (optionsJson) { |
|||
var options = []; |
|||
$.each(optionsJson, function (code, info) { |
|||
options.push({ |
|||
label: info.label, |
|||
data: code |
|||
}); |
|||
}); |
|||
ui.afcTopicInput.setOptions(options); |
|||
ui.afcTopicInput.setValue(config.defaultAfcTopic); |
|||
// resolve promise with allowed option codes: |
|||
return options.map(function (op) { |
|||
return op.data; |
|||
}); |
|||
}); |
|||
ui.oresTopicLayout.toggle(false); |
|||
var asUser = mw.util.getParamValue('username'); |
|||
if (asUser && asUser !== mw.config.get('wgUserName')) { |
|||
ui.fieldset.addItems([ |
|||
new OO.ui.FieldLayout(new OO.ui.MessageWidget({ |
|||
type: 'notice', |
|||
inline: true, |
|||
label: msg('submitting-as', asUser) |
|||
})) |
|||
], /* position */ 5); // just before submit button |
|||
} |
|||
// Attach |
|||
$('#afc-submit-wizard-container').empty().append(ui.fieldset.$element, ui.footerLayout.$element); |
|||
// Populate talk page tags for multi-select widget |
|||
afc.talkTagOptionsLoaded = getJSONPage('Wikipedija:Članki za ustvaritev/WikiProject templates.json').then(function (data) { |
|||
ui.talkTagsInput.addOptions(Object.keys(data).map(function (k) { |
|||
return { |
|||
data: data[k], |
|||
label: k |
|||
}; |
|||
})); |
|||
}); |
|||
ui.clearTalkTags = function () { |
|||
afc.talkTagOptionsLoaded.then(function () { |
|||
ui.talkTagsInput.setValue([]); |
|||
}); |
|||
}; |
|||
ui.addTalkTags = function (tags) { |
|||
afc.talkTagOptionsLoaded.then(function () { |
|||
ui.talkTagsInput.setValue(ui.talkTagsInput.getValue().concat(tags)); |
|||
}); |
|||
}; |
|||
// Get mapping of infoboxes with relevant WikiProjects |
|||
afc.ibxmapLoaded = getJSONPage('Wikipedija:Članki za ustvaritev/Infobox WikiProject map.json'); |
|||
ui.submitButton.on('click', handleSubmit); |
|||
ui.titleInput.on('change', mw.util.debounce(config.debounceDelay, onDraftInputChange)); |
|||
if (mw.util.getParamValue('page')) { |
|||
onDraftInputChange(); |
|||
} |
|||
// The default font size in monobook and modern are too small at 10px |
|||
mw.util.addCSS('.skin-modern .projectTagOverlay, .skin-monobook .projectTagOverlay { font-size: 130%; }'); |
|||
afc.beforeUnload = function (e) { |
|||
e.preventDefault(); |
|||
e.returnValue = ''; |
|||
return ''; |
|||
}; |
|||
$(window).on('beforeunload', afc.beforeUnload); |
|||
} |
|||
function onDraftInputChange() { |
|||
afc.lookupApi.abort(); // abort older API requests |
|||
var drafttitle = ui.titleInput.getValue().trim(); |
|||
if (!drafttitle) { // empty |
|||
return; |
|||
} |
|||
debug('sprememba vnosa osnutka »' + ui.titleInput.getValue() + '«'); |
|||
// re-initialize |
|||
ui.titleLayout.setErrors([]); |
|||
ui.titleLayout.setWarnings([]); |
|||
afc.oresTopics = null; |
|||
afc.talktext = null; |
|||
afc.pagetext = null; |
|||
ui.clearTalkTags(); |
|||
afc.lookupApi.get({ |
|||
"action": "query", |
|||
"prop": "revisions|description|info", |
|||
"titles": drafttitle, |
|||
"rvprop": "content", |
|||
"rvslots": "main" |
|||
}).then(setPrefillsFromPageData); |
|||
var titleObj = mw.Title.newFromText(drafttitle); |
|||
if (!titleObj || titleObj.isTalkPage()) { |
|||
return; |
|||
} |
|||
var talkpagename = titleObj.getTalkPage().toText(); |
|||
afc.lookupApi.get({ |
|||
"action": "query", |
|||
"prop": "revisions", |
|||
"titles": talkpagename, |
|||
"rvprop": "content", |
|||
"rvslots": "main", |
|||
}).then(setPrefillsFromTalkPageData); |
|||
} |
|||
function setPrefillsFromPageData(json) { |
|||
debug('page fetch query', json); |
|||
var page = json.query.pages[0]; |
|||
var preNormalizedTitle = json.query.normalized && json.query.normalized[0] && |
|||
json.query.normalized[0].from; |
|||
debug('page.title: "' + page.title + '"'); |
|||
if (ui.titleInput.getValue() !== (preNormalizedTitle || page.title)) { |
|||
return; // user must have changed the title already |
|||
} |
|||
var errors = errorsFromPageData(page); |
|||
if (errors.length) { |
|||
ui.titleLayout.setErrors(errors); |
|||
return; |
|||
} |
|||
ui.titleLayout.setWarnings(warningsFromPageData(page)); |
|||
afc.pagetext = page.revisions[0].slots.main.content; |
|||
// Set AfC topic category |
|||
var topicMatch = afc.pagetext.match(/\{\{AfC topic\|(.*?)\}\}/); |
|||
if (topicMatch) { |
|||
afc.topicOptionsLoaded.then(function(allowedCodes) { |
|||
var topic = topicMatch[1]; |
|||
debug("Pridobljene oznake tem:", allowedCodes); |
|||
debug("Najdena tema ČU:", topic); |
|||
// if the code found in the template is an invalid one, keep the default to "other", |
|||
// rather than the first item in the list |
|||
if (allowedCodes.indexOf(topic) !== -1) { |
|||
ui.afcTopicInput.setValue(topic); |
|||
} else { |
|||
ui.afcTopicInput.setValue(config.defaultAfcTopic); |
|||
} |
|||
}); |
|||
} else { |
|||
ui.afcTopicInput.setValue(config.defaultAfcTopic); |
|||
} |
|||
// Set short description in form |
|||
ui.shortdescInput.setValue(page.description || ''); |
|||
// Guess WikiProject tags from infoboxes on the page |
|||
afc.ibxmapLoaded.then(function (ibxmap) { |
|||
var infoboxRgx = /\{\{([Ii]nfopolje [^|}]*)/g, |
|||
wikiprojects = [], |
|||
match; |
|||
while (match = infoboxRgx.exec(afc.pagetext)) { |
|||
var ibx = match[1].trim(); |
|||
ibx = ibx[0].toUpperCase() + ibx.slice(1); |
|||
if (ibxmap[ibx]) { |
|||
wikiprojects = wikiprojects.concat(ibxmap[ibx]); |
|||
} |
|||
} |
|||
debug('wikiprojekti iz infopolja: ', wikiprojects); |
|||
ui.addTalkTags(wikiprojects); |
|||
}); |
|||
// Fill ORES topics |
|||
getOresTopics(page.lastrevid).then(function (topics) { |
|||
debug('ORES topics: ', topics); |
|||
if (!topics || !topics.length) { // unexpected API response or API returns unsorted |
|||
ui.oresTopicLayout.toggle(true); |
|||
} else { |
|||
ui.oresTopicLayout.toggle(false); |
|||
afc.oresTopics = topics; |
|||
} |
|||
}, function () { |
|||
ui.oresTopicLayout.toggle(true); |
|||
}); |
|||
} |
|||
function setPrefillsFromTalkPageData (json) { |
|||
var talkpage = json.query.pages[0]; |
|||
if (!talkpage || talkpage.missing) { |
|||
return; |
|||
} |
|||
afc.talktext = talkpage.revisions[0].slots.main.content; |
|||
debug(afc.talktext); |
|||
var existingWikiProjects = extractWikiProjectTagsFromText(afc.talktext); |
|||
var existingTags = existingWikiProjects.map(function (e) { |
|||
return e.name; |
|||
}); |
|||
debug(existingTags); |
|||
ui.addTalkTags(existingTags); |
|||
} |
|||
/** |
|||
* @param {Object} page - from query API response |
|||
* @returns {string[]} |
|||
*/ |
|||
function errorsFromPageData(page) { |
|||
if (!page || page.invalid) { |
|||
return [msg('validation-invalidtitle')]; |
|||
} |
|||
if (page.missing) { |
|||
return [msg('validation-missingtitle')]; |
|||
} |
|||
if (config.allowedNamespaces.indexOf(page.ns) === -1) { |
|||
return [msg('validation-wrongns')]; |
|||
} |
|||
return []; |
|||
} |
|||
/** |
|||
* @param {Object} page - from query API response |
|||
* @returns {string[]} |
|||
*/ |
|||
function warningsFromPageData(page) { |
|||
var pagetext = page.revisions[0].slots.main.content; |
|||
var warnings = []; |
|||
// Show no refs warning |
|||
if (!/<ref/i.test(pagetext) && !/\{\{([Ss]fn|[Hh]arv)/.test(pagetext)) { |
|||
warnings.push('warning-norefs'); |
|||
} |
|||
// TODO: Show warning for use of deprecated/unreliable sources |
|||
// TODO: Show tip for avoiding peacock words or promotional language? |
|||
return warnings.map(function (warning) { |
|||
return new OO.ui.HtmlSnippet(linkify(msg(warning))); |
|||
}); |
|||
} |
|||
/** |
|||
* @param {number} revid |
|||
* @returns {jQuery.Promise<string[]>} |
|||
*/ |
|||
function getOresTopics(revid) { |
|||
return $.get('https://ores.wikimedia.org/v3/scores/enwiki/?models=drafttopic&revids=' + revid).then(function (json) { |
|||
// null is returned if at any point something in the API output is unexpected |
|||
// ES2020 has optional chaining, but of course on MediaWiki we're still stuck with ES5 |
|||
return json && |
|||
json.enwiki && |
|||
json.enwiki.scores && |
|||
json.enwiki.scores[revid] && |
|||
json.enwiki.scores[revid].drafttopic && |
|||
json.enwiki.scores[revid].drafttopic.score && |
|||
(json.enwiki.scores[revid].drafttopic.score.prediction instanceof Array) && |
|||
json.enwiki.scores[revid].drafttopic.score.prediction.map(function (topic, idx, topics) { |
|||
// Remove Asia.Asia* if Asia.South-Asia is present (example) |
|||
if (topic.slice(-1) === '*') { |
|||
var metatopic = topic.split('.').slice(0, -1).join('.'); |
|||
for (var i = 0; i < topics.length; i++) { |
|||
if (topics[i] !== topic && topics[i].startsWith(metatopic)) { |
|||
return; |
|||
} |
|||
} |
|||
return metatopic.split('.').pop(); |
|||
} |
|||
return topic.split('.').pop(); |
|||
}) |
|||
.filter(function (e) { |
|||
return e; // filter out undefined from above |
|||
}) |
|||
.map(function (topic) { |
|||
// convert topic string to normalised form |
|||
return topic |
|||
.replace(/[A-Z]/g, function (match) { |
|||
return match[0].toLowerCase(); |
|||
}) |
|||
.replace(/ /g, '-') |
|||
.replace(/&/g, 'and'); |
|||
}); |
|||
}); |
|||
} |
|||
/*** |
|||
* @param {string} text |
|||
* @returns {{wikitext: string, name: string}[]} |
|||
*/ |
|||
function extractWikiProjectTagsFromText(text) { |
|||
if (!text) { |
|||
return []; |
|||
} |
|||
// this is best-effort, no guaranteed accuracy |
|||
var existingTags = []; |
|||
var rgx = /\{\{(WikiProjekt [^|}]*).*?\}\}/g; |
|||
var match; |
|||
while (match = rgx.exec(text)) { // jshint ignore:line |
|||
var tag = match[1].trim(); |
|||
if (tag === 'WikiProject banner shell') { |
|||
continue; |
|||
} |
|||
existingTags.push({ |
|||
wikitext: match[0], |
|||
name: tag |
|||
}); |
|||
} |
|||
return existingTags; |
|||
} |
|||
/** |
|||
* @param {string} type |
|||
* @param {string} message |
|||
*/ |
|||
function setMainStatus(type, message) { |
|||
if (!ui.mainStatusLayout || !ui.mainStatusLayout.isElementAttached()) { |
|||
ui.fieldset.addItems([ |
|||
ui.mainStatusLayout = new OO.ui.FieldLayout(ui.mainStatusArea = new OO.ui.MessageWidget()) |
|||
]); |
|||
} |
|||
ui.mainStatusArea.setType(type); |
|||
ui.mainStatusArea.setLabel(message); |
|||
} |
|||
/** |
|||
* @param {string} type |
|||
* @param {string} message |
|||
*/ |
|||
function setTalkStatus(type, message) { |
|||
if (!ui.talkStatusLayout) { |
|||
ui.fieldset.addItems([ |
|||
ui.talkStatusLayout = new OO.ui.FieldLayout(ui.talkStatusArea = new OO.ui.MessageWidget()) |
|||
]); |
|||
} |
|||
ui.talkStatusArea.setType(type); |
|||
ui.talkStatusArea.setLabel(message); |
|||
} |
|||
function handleSubmit() { |
|||
setMainStatus('notice', msg('status-processing')); |
|||
ui.submitButton.setDisabled(true); |
|||
ui.mainStatusLayout.scrollElementIntoView(); |
|||
var draft = ui.titleInput.getValue(); |
|||
debug(draft); |
|||
afc.api.get({ |
|||
"action": "query", |
|||
"prop": "revisions|description", |
|||
"titles": draft, |
|||
"rvprop": "content", |
|||
"rvslots": "main", |
|||
}).then(function (json) { |
|||
var apiPage = json.query.pages[0]; |
|||
var errors = errorsFromPageData(apiPage); |
|||
if (errors.length) { |
|||
ui.titleLayout.setErrors(errors); |
|||
ui.fieldset.removeItems([ui.mainStatusLayout]); |
|||
ui.submitButton.setDisabled(false); |
|||
ui.titleLayout.scrollElementIntoView(); |
|||
return; |
|||
} |
|||
var text = prepareDraftText(apiPage); |
|||
setMainStatus('notice', msg('status-saving')); |
|||
saveDraftPage(draft, text).then(function () { |
|||
setMainStatus('success', msg('status-redirecting')); |
|||
$(window).off('beforeunload', afc.beforeUnload); |
|||
setTimeout(function () { |
|||
location.href = mw.util.getUrl(draft); |
|||
}, config.redirectionDelay); |
|||
}, function (code, err) { |
|||
if (code === 'captcha') { |
|||
ui.fieldset.removeItems([ui.mainStatusLayout, ui.talkStatusLayout]); |
|||
ui.captchaLayout.scrollElementIntoView(); |
|||
} else { |
|||
setMainStatus('error', msg('error-saving-main', makeErrorMessage(code, err))); |
|||
} |
|||
ui.submitButton.setDisabled(false); |
|||
}); |
|||
var talktext = prepareTalkText(afc.talktext); |
|||
if (!afc.talktext && !talktext) { |
|||
// No content earlier, no content now. Stop here to avoid |
|||
// creating the talk page as empty. |
|||
return; |
|||
} |
|||
setTalkStatus('notice', msg('status-saving-talk')); |
|||
afc.api.postWithEditToken({ |
|||
"action": "edit", |
|||
"title": new mw.Title(draft).getTalkPage().toText(), |
|||
"text": talktext, |
|||
"summary": msg('editsummary-talk') |
|||
}).then(function (data) { |
|||
if (data.edit && data.edit.result === 'Success') { |
|||
setTalkStatus('success', msg('status-talk-success')); |
|||
} else { |
|||
return $.Deferred().reject('unexpected result'); |
|||
} |
|||
}).catch(function (code, err) { |
|||
setTalkStatus('error', msg('error-saving-talk', makeErrorMessage(code, err))); |
|||
}); |
|||
}).catch(function (code, err) { |
|||
setMainStatus('error', msg('error-main', makeErrorMessage(code, err))); |
|||
ui.submitButton.setDisabled(false); |
|||
}); |
|||
} |
|||
function saveDraftPage(title, text) { |
|||
// TODO: handle edit conflict |
|||
var editParams = { |
|||
"action": "edit", |
|||
"title": title, |
|||
"text": text, |
|||
"summary": msg('editsummary-main') |
|||
}; |
|||
if (ui.captchaLayout && ui.captchaLayout.isElementAttached()) { |
|||
editParams.captchaid = afc.captchaid; |
|||
editParams.captchaword = ui.captchaInput.getValue(); |
|||
ui.fieldset.removeItems([ui.captchaLayout]); |
|||
} |
|||
return afc.api.postWithEditToken(editParams).then(function (data) { |
|||
if (!data.edit || data.edit.result !== 'Success') { |
|||
if (data.edit && data.edit.captcha) { |
|||
// Handle captcha for non-confirmed users |
|||
var url = data.edit.captcha.url; |
|||
afc.captchaid = data.edit.captcha.id; // abuse of global? |
|||
ui.fieldset.addItems([ |
|||
ui.captchaLayout = new OO.ui.FieldLayout(ui.captchaInput = new OO.ui.TextInputWidget({ |
|||
placeholder: msg('captcha-placeholder'), |
|||
required: true |
|||
}), { |
|||
warnings: [ new OO.ui.HtmlSnippet('<img src=' + url + '>') ], |
|||
label: msg('captcha-label'), |
|||
align: 'top', |
|||
help: msg('captcha-helptip'), |
|||
helpInline: true, |
|||
}), |
|||
], /* position */ 6); // just after submit button |
|||
// TODO: submit when enter key is pressed in captcha field |
|||
return $.Deferred().reject('captcha'); |
|||
} else { |
|||
return $.Deferred().reject('unexpected-result'); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
/** |
|||
* @param {Object} page - page information from the API |
|||
* @returns {string} final draft page text to save |
|||
*/ |
|||
function prepareDraftText(page) { |
|||
var text = page.revisions[0].slots.main.content; |
|||
var header = ''; |
|||
// Handle short description |
|||
var shortDescTemplateExists = /\{\{[Ss]hort ?desc(ription)?\s*\|/.test(text); |
|||
var shortDescExists = !!page.description; |
|||
var existingShortDesc = page.description; |
|||
if (ui.shortdescInput.getValue()) { |
|||
// 1. No shortdesc - insert the one provided by user |
|||
if (!shortDescExists) { |
|||
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n'; |
|||
// 2. Shortdesc exists from {{short description}} template - replace it |
|||
} else if (shortDescExists && shortDescTemplateExists) { |
|||
text = text.replace(/\{\{[Ss]hort ?desc(ription)?\s*\|.*?\}\}\n*/g, ''); |
|||
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n'; |
|||
// 3. Shortdesc exists, but not generated by {{short description}}. If the user |
|||
// has changed the value, save the new value |
|||
} else if (shortDescExists && existingShortDesc !== ui.shortdescInput.getValue()) { |
|||
header += '{{Short description|' + ui.shortdescInput.getValue() + '}}\n'; |
|||
// 4. Shortdesc exists, but not generated by {{short description}}, and user hasn't changed the value |
|||
} else { |
|||
// Do nothing |
|||
} |
|||
} else { |
|||
// User emptied the shortdesc field (or didn't exist from before): remove any existing shortdesc. |
|||
// This doesn't remove any shortdesc that is generated by other templates |
|||
// Race condition (FIXME): if someone else added a shortdesc to the draft after this user opened the wizard, |
|||
// that shortdesc gets removed |
|||
text = text.replace(/\{\{[Ss]hort ?desc(ription)?\s*\|.*?\}\}\n*/g, ''); |
|||
} |
|||
// Draft topics |
|||
debug(ui.oresTopicInput); |
|||
if (ui.oresTopicLayout.isVisible()) { |
|||
afc.oresTopics = ui.oresTopicInput.getValue(); |
|||
} |
|||
if (afc.oresTopics && afc.oresTopics.length) { |
|||
text = text.replace(/\{\{[Tt]eme osnutkov\|.*?\}\}\n*/g, ''); |
|||
header += '{{Teme osnutkov|' + afc.oresTopics.join('|') + '}}\n'; |
|||
} |
|||
// Add AfC topic |
|||
text = text.replace(/\{\{AfC topic\|(.*?)\}\}/g, ''); |
|||
header += '{{AfC topic|' + ui.afcTopicInput.getValue() + '}}\n'; |
|||
// put AfC submission template |
|||
header += '{{subst:submit|1=' + (mw.util.getParamValue('username') || '{{subst:REVISIONUSER}}') + '}}\n'; |
|||
// insert everything to the top |
|||
text = header + text; |
|||
debug(text); |
|||
return text; |
|||
} |
|||
/** |
|||
* @param {string} initialText - initial talk page text |
|||
* @returns {string} - final talk page text to save |
|||
*/ |
|||
function prepareTalkText(initialText) { |
|||
var text = initialText; |
|||
// TODO: this can be improved to put tags within {{WikiProject banner shell}} (if already present or otherwise) |
|||
var alreadyExistingWikiProjects = extractWikiProjectTagsFromText(text); |
|||
var alreadyExistingTags = alreadyExistingWikiProjects.map(function (e) { |
|||
return e.name; |
|||
}); |
|||
var tagsToAdd = ui.talkTagsInput.getValue().filter(function (tag) { |
|||
return alreadyExistingTags.indexOf(tag) === -1; |
|||
}); |
|||
var tagsToRemove = alreadyExistingTags.filter(function (tag) { |
|||
return ui.talkTagsInput.getValue().indexOf(tag) === -1; |
|||
}); |
|||
tagsToRemove.forEach(function (tag) { |
|||
text = text.replace(new RegExp('\\{\\{\\s*' + tag + '\\s*(\\|.*?)?\\}\\}\\n?'), ''); |
|||
}); |
|||
var tagsToAddText = tagsToAdd.map(function (tag) { |
|||
return '{{' + tag + '}}'; |
|||
}).join('\n') + (tagsToAdd.length ? '\n' : ''); |
|||
text = tagsToAddText + (text || ''); |
|||
// remove |class=draft parameter in any WikiProject templates |
|||
text = text.replace(/(\{\{wikiproject.*?)\|\s*class\s*=\s*draft\s*/gi, '$1'); |
|||
return text; |
|||
} |
|||
/** |
|||
* Load a JSON page from the wiki. |
|||
* Use API (instead of $.getJSON with action=raw) to take advantage of caching |
|||
* @param {string} page |
|||
* @returns {jQuery.Promise<Record<string, any>>} |
|||
**/ |
|||
function getJSONPage (page) { |
|||
return afc.api.get({ |
|||
action: 'query', |
|||
titles: page, |
|||
prop: 'revisions', |
|||
rvprop: 'content', |
|||
rvlimit: 1, |
|||
rvslots: 'main', |
|||
uselang: 'content', |
|||
maxage: '3600', // 1 hour |
|||
smaxage: '3600', |
|||
formatversion: 2 |
|||
}).then(function (json) { |
|||
var content = json.query.pages[0].revisions[0].slots.main.content; |
|||
return JSON.parse(content); |
|||
}).catch(function (code, err) { |
|||
console.error(makeErrorMessage(code, err)); |
|||
}); |
|||
} |
|||
/** |
|||
* Expands wikilinks and external links into HTML. |
|||
* Used instead of mw.msg(...).parse() because we want links to open in a new tab, |
|||
* and we don't want tags to be mangled. |
|||
* @param {string} input |
|||
* @returns {string} |
|||
*/ |
|||
function linkify(input) { |
|||
return input |
|||
.replace( |
|||
/\[\[:?(?:([^|\]]+?)\|)?([^\]|]+?)\]\]/g, |
|||
function(_, target, text) { |
|||
if (!target) { |
|||
target = text; |
|||
} |
|||
return '<a target="_blank" href="' + mw.util.getUrl(target) + |
|||
'" title="' + target.replace(/"/g, '"') + '">' + text + '</a>'; |
|||
} |
|||
) |
|||
// for ext links, display text should be given |
|||
.replace( |
|||
/\[(\S*?) (.*?)\]/g, |
|||
function (_, target, text) { |
|||
return '<a target="_blank" href="' + target + '">' + text + '</a>'; |
|||
} |
|||
); |
|||
} |
|||
function msg(key) { |
|||
var messageArgs = Array.prototype.slice.call(arguments, 1); |
|||
return mw.msg.apply(mw, ['afcsw-' + key].concat(messageArgs)); |
|||
} |
|||
function makeErrorMessage(code, err) { |
|||
if (code === 'http') { |
|||
return 'http: ni internetne povezave'; |
|||
} |
|||
return code + (err && err.error && err.error.info ? ': ' + err.error.info : ''); |
|||
} |
|||
function debug() { |
|||
Array.prototype.slice.call(arguments).forEach(function (arg) { |
|||
console.log(arg); |
|||
}); |
|||
} |
|||
})(); // File-level closure to protect functions from being exposed to the global scope or overwritten |
|||
/* </nowiki> */ |
Redakcija: 01:10, 28. februar 2023
/* Deprecated by [[MediaWiki:Common.js]] */
/* Popravek za Glavno stran */
function mainPageRenameNamespaceTab() {
try {
var Node = document.getElementById( 'ca-nstab-main' ).firstChild;
if ( Node.textContent ) { // Per DOM Level 3
document.createElement( "span" );
Node.textContent = 'Glavna stran';
} else if ( Node.innerText ) { // IE doesn't handle .textContent
document.createElement( "span" );
Node.innerText = 'Glavna stran';
} else { // Fallback
document.createElement( "span" );
Node.replaceChild( Node.firstChild, document.createTextNode( 'Glavna stran' ) );
}
} catch(e) {
// bailing out!
}
}
if ( mw.config.get('wgTitle') == 'Glavna stran' && ( mw.config.get('wgNamespaceNumber') == 0 || mw.config.get('wgNamespaceNumber') == 1 ) ) {
$( mainPageRenameNamespaceTab );
}