Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Bobby Cohn/SourceAssess.
// SourceAssess
// <nowiki>
/**
* SourceAssess.js
*
* Wikipedia user script to review article references and generate a
* {{source assess table}} or {{ORGCRIT assess table}} templates for
* use in AfC, AfD or similar discussions.
*
* Version: v26.04.29 - Stable release
* Release notes: added the ability to edit the list of sources and
* reset the list of sources from the scanned page. Scanned references
* on a page are no longer required to build a reference list.
*
*/
var SourceAssess = {};
window.SourceAssess = SourceAssess;
// ─── Portlet link ────────────────────────────────────────────────────────────
$.when(
mw.loader.using(['mediawiki.api', 'ext.gadget.morebits']),
$.ready
).then(function () {
var portletLink = mw.util.addPortletLink(
'p-cactions',
'#',
'Assess sources',
'ca-sourceassess',
'Review references and generate a source assessment table'
);
$(portletLink).on('click', function (e) {
e.preventDefault();
SourceAssess.run();
});
});
// ─── Entry point ─────────────────────────────────────────────────────────────
SourceAssess.run = function () {
// If we already have state from a previous open, go straight to the window
if (SourceAssess._refs && SourceAssess._refs.length > 0) {
SourceAssess.displayWindow(SourceAssess._refs, SourceAssess._assessments);
return;
}
var pageName = mw.config.get('wgPageName');
var api = new mw.Api();
api.get({
action: 'query',
titles: pageName,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
formatversion: 2
}).then(function (data) {
var page = data.query.pages[0];
if (!page || page.missing) {
mw.notify('SourceAssess: could not load page wikitext.', { type: 'error' });
return;
}
var wikitext = page.revisions[0].slots.main.content;
var refs = SourceAssess.extractRefs(wikitext);
if (refs.length === 0) {
mw.notify('SourceAssess: no <ref> tags found on this page. You can add references manually.', { type: 'warn' });
SourceAssess._refs = [''];
SourceAssess._originalRefs = [''];
SourceAssess._assessments = [{ i: '', r: '', s: '', ij: '', rj: '', sj: '', '2': '', '2j': '', skipped: false }];
SourceAssess._currentIndex = 0;
SourceAssess.showRefEditor(SourceAssess._refs, SourceAssess._assessments, { close: function () {} });
return;
}
// Cache before displaying
SourceAssess._refs = refs;
SourceAssess._originalRefs = refs.slice(); // snapshot for Reset
SourceAssess._assessments = refs.map(function () {
return { i: '', r: '', s: '', ij: '', rj: '', sj: '', '2': '', '2j': '', skipped: false };
});
SourceAssess.displayWindow(SourceAssess._refs, SourceAssess._assessments);
}).catch(function (err) {
mw.notify('SourceAssess: API error – ' + err, { type: 'error' });
});
};
// ─── Reference extraction ─────────────────────────────────────────────────────
/**
* Extract all unique <ref ...>...</ref> contents from wikitext.
* Ignores self-closing <ref ... /> tags and named back-references <ref name="x" />.
* Deduplicates by inner content so named refs that repeat are only listed once.
*/
SourceAssess.extractRefs = function (wikitext) {
// Match opening ref tag (with optional attributes) and capture content
var refPattern = /<ref(?:\s[^>]*[^/])?>([^<]+(?:<(?!\/ref>)[^<]*)*)<\/ref>/gi;
var seen = {};
var refs = [];
var match;
while ((match = refPattern.exec(wikitext)) !== null) {
var content = match[1].trim();
if (content && !seen[content]) {
seen[content] = true;
refs.push(content);
}
}
return refs;
};
// ─── Main window ──────────────────────────────────────────────────────────────
SourceAssess.displayWindow = function (refs, assessments) {
var currentIndex = SourceAssess._currentIndex || 0;
// ── Window setup ──
var win = new Morebits.simpleWindow(780, 600);
win.setTitle('Source assessment');
win.setScriptName('SourceAssess');
win.addFooterLink('Documentation', 'User:Bobby Cohn/SourceAssess');
win.addFooterLink('Leave feedback', 'User talk:Bobby Cohn');
SourceAssess._win = win;
// ── Top-level container (we rebuild inner content each step) ──
var outerForm = new Morebits.quickForm(function () { /* no submit — handled manually */ });
var container = outerForm.append({ type: 'div', id: 'sa-container' });
// Progress bar / header
var progressRow = container.append({
type: 'div',
style: 'display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;'
});
progressRow.append({
type: 'div',
id: 'sa-progress',
style: 'font-weight:bold;'
});
var progressBtns = progressRow.append({
type: 'div',
style: 'display:flex; gap:6px;'
});
progressBtns.append({
type: 'button',
label: 'Edit references',
name: 'sa-edit-refs'
});
progressBtns.append({
type: 'button',
label: 'Generate table',
name: 'sa-finish'
});
// Rendered reference preview
container.append({
type: 'div',
id: 'sa-ref-preview',
style: [
'border:1px solid #a2a9b1',
'border-radius:3px',
'padding:8px 10px',
'min-height:30px',
'max-height:120px',
'overflow-y:auto',
'margin-bottom:6px'
].join(';')
});
// Reference display (wikitext)
container.append({
type: 'div',
id: 'sa-reftext',
style: [
'background:#f8f9fa',
'border:1px solid #a2a9b1',
'border-radius:3px',
'padding:8px 10px',
'font-family:monospace',
'font-size:0.85em',
'white-space:pre-wrap',
'word-break:break-all',
'max-height:60px',
'overflow-y:auto',
'margin-bottom:8px'
].join(';')
});
// Assessment fields table
var table = container.append({
type: 'div',
id: 'sa-fields',
style: 'display:table; width:100%; border-collapse:separate; border-spacing:0 6px;'
});
var labels = [
'<a href="http://wiki.nitrosworld.org/wiki/Wikipedia:Independent_sources" target="_blank" rel="noopener" style="font-style:normal;">Independence</a>',
'<a href="http://wiki.nitrosworld.org/wiki/Wikipedia:Reliable_sources" target="_blank" rel="noopener" style="font-style:normal;">Reliability</a>',
'<a href="http://wiki.nitrosworld.org/wiki/Wikipedia:Significant_coverage" target="_blank" rel="noopener" style="font-style:normal;">Significant coverage</a>'
];
var keys = ['i', 'r', 's'];
var justifKeys = ['ij', 'rj', 'sj'];
keys.forEach(function (key, idx) {
var row = table.append({
type: 'div',
style: 'display:table-row;'
});
// Label cell
row.append({
type: 'div',
label: labels[idx],
style: 'display:table-cell; width:200px; vertical-align:middle; padding-right:8px; font-weight:bold;'
});
// Dropdown cell
var dropCell = row.append({
type: 'div',
style: 'display:table-cell; vertical-align:middle; padding-right:12px;'
});
dropCell.append({
type: 'select',
name: 'sa-sel-' + key,
list: [
{ label: '(Empty)', value: '' },
{ label: 'Yes', value: 'y' },
{ label: 'No', value: 'n' },
{ label: 'Unsure', value: '?' }
]
});
// Justification cell
var justCell = row.append({
type: 'div',
style: 'display:table-cell; vertical-align:middle; width:100%;'
});
justCell.append({
type: 'input',
name: 'sa-just-' + justifKeys[idx],
placeholder: 'Optional justification ...',
style: 'width:99%;'
});
});
// Fourth field — hidden unless ORGCRIT mode is active
var orgcritRow = table.append({
type: 'div',
id: 'sa-row-2',
style: 'display:' + (SourceAssess._orgcrit ? 'table-row' : 'none') + ';'
});
orgcritRow.append({
type: 'div',
label: '<a href="http://wiki.nitrosworld.org/wiki/WP:PSTS" target="_blank" rel="noopener" style="font-style:normal;">Secondary</a>',
style: 'display:table-cell; width:200px; vertical-align:middle; padding-right:8px; font-weight:bold;'
});
var orgcritDrop = orgcritRow.append({
type: 'div',
style: 'display:table-cell; vertical-align:middle; padding-right:12px;'
});
orgcritDrop.append({
type: 'select',
name: 'sa-sel-2',
list: [
{ label: '(Empty)', value: '' },
{ label: 'Yes', value: 'y' },
{ label: 'No', value: 'n' },
{ label: 'Unsure', value: '?' }
]
});
orgcritRow.append({
type: 'div',
style: 'display:table-cell; vertical-align:middle; width:100%;'
}).append({
type: 'input',
name: 'sa-just-2j',
placeholder: 'Optional justification ...',
style: 'width:99%;'
});
// Skip checkbox
container.append({
type: 'checkbox',
name: 'sa-skip-cb',
list: [{ label: 'Ignore this reference', value: 'skip' }]
});
// ORGCRIT checkbox
container.append({
type: 'checkbox',
name: 'sa-orgcrit',
list: [{ label: 'Apply ORGCRIT assessment', value: 'orgcrit' }]
});
// Navigation buttons
var btnRow = container.append({
type: 'div',
style: 'margin-top:14px; display:flex; gap:8px;'
});
btnRow.append({ type: 'button', label: '← Previous', name: 'sa-prev' });
btnRow.append({ type: 'button', label: 'Next →', name: 'sa-next' });
var rendered = outerForm.render();
win.setContent(rendered);
win.display();
var dialog = document.querySelector('.morebits-dialog');
if (dialog) {
dialog.style.zIndex = '10000';
}
win.close = (function (originalClose) {
return function () {
readForm(currentIndex); // flush current form state before closing
SourceAssess._currentIndex = currentIndex;
originalClose.apply(win, arguments);
};
})(win.close);
// ── Helper: populate form with current ref data ──
function populateForm(idx) {
var a = assessments[idx];
var refCount = refs.length;
// Progress
document.getElementById('sa-progress').textContent =
'Reference ' + (idx + 1) + ' of ' + refCount;
// Rendered preview
var api = new mw.Api();
api.post({
action: 'parse',
text: refs[idx],
contentmodel: 'wikitext',
prop: 'text',
disablelimitreport: true,
formatversion: 2
}).then(function (data) {
var preview = document.getElementById('sa-ref-preview');
if (preview) {
preview.innerHTML = data.parse.text;
preview.querySelectorAll('a').forEach(function (a) {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener');
});
}
}).catch(function () {
var preview = document.getElementById('sa-ref-preview');
if (preview) preview.textContent = '(Preview unavailable)';
});
// Ref text
document.getElementById('sa-reftext').textContent = refs[idx];
// Dropdowns & justification
keys.forEach(function (key, i) {
var sel = document.querySelector('[name="sa-sel-' + key + '"]');
if (sel) sel.value = a[key];
var inp = document.querySelector('[name="sa-just-' + justifKeys[i] + '"]');
if (inp) inp.value = a[justifKeys[i]];
});
// Optional ORGCRIT assessment
var orgcritCb = document.querySelector('[name="sa-orgcrit"]');
if (orgcritCb) orgcritCb.checked = SourceAssess._orgcrit || false;
var row2 = document.getElementById('sa-row-2');
if (row2) row2.style.display = SourceAssess._orgcrit ? 'table-row' : 'none';
var sel2 = document.querySelector('[name="sa-sel-2"]');
if (sel2) sel2.value = a['2'] || '';
var inp2 = document.querySelector('[name="sa-just-2j"]');
if (inp2) inp2.value = a['2j'] || '';
// Skip checkbox
var skipCb = document.querySelector('[name="sa-skip-cb"]');
if (skipCb) skipCb.checked = a.skipped;
updateSkipState(a.skipped);
// Prev button
var prevBtn = document.querySelector('[name="sa-prev"]');
if (prevBtn) prevBtn.disabled = (idx === 0);
// Next button
var nextBtn = document.querySelector('[name="sa-next"]');
if (nextBtn) nextBtn.disabled = (idx === refs.length - 1);
}
function updateSkipState(skipped) {
var fieldsDiv = document.getElementById('sa-fields');
if (fieldsDiv) {
fieldsDiv.style.opacity = skipped ? '0.4' : '1';
var inputs = fieldsDiv.querySelectorAll('select, input');
inputs.forEach(function (el) { el.disabled = skipped; });
}
}
function readForm(idx) {
var a = assessments[idx];
var skipCb = document.querySelector('[name="sa-skip-cb"]');
a.skipped = skipCb ? skipCb.checked : false;
keys.forEach(function (key, i) {
var sel = document.querySelector('[name="sa-sel-' + key + '"]');
a[key] = (sel && !a.skipped) ? sel.value : '';
var inp = document.querySelector('[name="sa-just-' + justifKeys[i] + '"]');
a[justifKeys[i]] = (inp && !a.skipped) ? inp.value : '';
});
var sel2 = document.querySelector('[name="sa-sel-2"]');
a['2'] = (sel2 && !a.skipped) ? sel2.value : '';
var inp2 = document.querySelector('[name="sa-just-2j"]');
a['2j'] = (inp2 && !a.skipped) ? inp2.value : '';
}
// ── Wire up events ──
$(document).off('.sourceassess'); // Remove ALL previous SourceAssess handlers in one shot
$(document).on('change.sourceassess', '[name="sa-skip-cb"]', function () {
updateSkipState(this.checked);
});
$(document).on('click.sourceassess', '[name="sa-prev"]', function (e) {
e.preventDefault();
readForm(currentIndex);
if (currentIndex > 0) {
currentIndex--;
SourceAssess._currentIndex = currentIndex;
populateForm(currentIndex);
}
});
$(document).on('click.sourceassess', '[name="sa-next"]', function (e) {
e.preventDefault();
readForm(currentIndex);
if (currentIndex < refs.length - 1) {
currentIndex++;
SourceAssess._currentIndex = currentIndex;
populateForm(currentIndex);
}
});
$(document).on('click.sourceassess', '[name="sa-finish"]', function (e) {
e.preventDefault();
readForm(currentIndex);
SourceAssess.showSummary(refs, assessments, win);
});
$(document).on('change.sourceassess', '[name="sa-orgcrit"]', function () {
SourceAssess._orgcrit = this.checked;
var row = document.getElementById('sa-row-2');
if (row) row.style.display = this.checked ? 'table-row' : 'none';
});
$(document).on('click.sourceassess', '[name="sa-edit-refs"]', function (e) {
e.preventDefault();
readForm(currentIndex);
SourceAssess.showRefEditor(refs, assessments, win);
});
// Initialise first ref
populateForm(currentIndex);
};
// ─── Reference editor window ──────────────────────────────────────────────────
SourceAssess.showRefEditor = function (refs, assessments, prevWin) {
prevWin.close();
var win3 = new Morebits.simpleWindow(780, 620);
win3.setTitle('Edit references');
win3.setScriptName('SourceAssess');
win3.addFooterLink('Documentation', 'User:Bobby Cohn/SourceAssess');
win3.addFooterLink('Leave feedback', 'User talk:Bobby Cohn');
var form3 = new Morebits.quickForm(function () {});
form3.append({
type: 'div',
style: 'font-style:italic; color:#555; margin-bottom:8px;',
label: 'Reference editing is in development and may affect source assessment. Review assessments after changing or modifying the reference list. See <a href="http://wiki.nitrosworld.org/wiki/User:Bobby Cohn/SourceAssess#Known_issues" target="_blank" rel="noopener">known issues</a> for more information. '
});
// Placeholder div — rebuildRefList will populate this after render
form3.append({
type: 'div',
id: 'sa-ref-editor-list'
});
// Bottom button row
var bottomRow = form3.append({
type: 'div',
style: 'display:flex; justify-content:space-between; margin-top:8px; margin-bottom:12px;'
});
var leftBtns = bottomRow.append({
type: 'div',
style: 'display:flex; gap:6px;'
});
leftBtns.append({
type: 'button',
label: '+',
name: 'sa-ref-add-new',
style: 'width:28px;'
});
leftBtns.append({
type: 'button',
label: 'Reset',
name: 'sa-ref-reset'
});
bottomRow.append({
type: 'button',
label: '← Return to assessment',
name: 'sa-ref-editor-return'
});
var rendered3 = form3.render();
win3.setContent(rendered3);
win3.display();
var dialog3 = document.querySelector('.morebits-dialog');
if (dialog3) {
dialog3.style.zIndex = '10000';
}
// ── Helpers ──
function readRefEdits() {
var result = [];
var idx = 0;
while (true) {
var ta = document.querySelector('[name="sa-ref-edit-' + idx + '"]');
if (!ta) break;
result.push({
value: ta.value.trim(),
original: ta.getAttribute('data-original-content') || ta.value.trim()
});
idx++;
}
return result;
}
// UPDATE rebuildRefList to accept objects:
function rebuildRefList(values) {
var list = document.getElementById('sa-ref-editor-list');
if (!list) return;
list.innerHTML = '';
values.forEach(function (item, i) {
var val = typeof item === 'object' ? item.value : item;
var original = typeof item === 'object' ? item.original : item;
var field = document.createElement('fieldset');
field.style.cssText = 'border:1px solid #a2a9b1; padding:6px 10px; margin-bottom:6px;';
var legend = document.createElement('legend');
legend.textContent = 'Reference ' + (i + 1);
field.appendChild(legend);
var inner = document.createElement('div');
inner.style.cssText = 'display:flex; gap:6px; align-items:flex-start;';
var ta = document.createElement('textarea');
ta.name = 'sa-ref-edit-' + i;
ta.value = val;
ta.setAttribute('data-original-content', original);
ta.style.cssText = 'width:100%; box-sizing:border-box; font-family:monospace; font-size:0.85em; height:60px; resize:vertical;';
var removeBtn = document.createElement('button');
removeBtn.textContent = '−';
removeBtn.name = 'sa-ref-remove-' + i;
removeBtn.style.cssText = 'flex-shrink:0; width:28px;';
inner.appendChild(ta);
inner.appendChild(removeBtn);
field.appendChild(inner);
list.appendChild(field);
});
}
// Initial render of ref list
rebuildRefList(refs.map(function (ref) {
return { value: ref, original: ref };
}));
// ── Wire up events ──
$(document).off('.sourceassess-refeditor');
$(document).on('click.sourceassess-refeditor', '[name^="sa-ref-remove-"]', function (e) {
e.preventDefault();
var idx = parseInt(this.name.replace('sa-ref-remove-', ''), 10);
var values = readRefEdits();
if (values.length <= 1) {
mw.notify('SourceAssess: cannot remove the last reference.', { type: 'warn' });
SourceAssess._fixNotifZ();
return;
}
values.splice(idx, 1);
rebuildRefList(values);
});
$(document).on('click.sourceassess-refeditor', '[name="sa-ref-add-new"]', function (e) {
e.preventDefault();
var values = readRefEdits();
values.push({ value: '', original: '' });
rebuildRefList(values);
});
// Reset handler:
$(document).on('click.sourceassess-refeditor', '[name="sa-ref-reset"]', function (e) {
e.preventDefault();
if (!confirm('Reset references to the originally extracted list? Any edits will be lost.')) return;
SourceAssess._refs = SourceAssess._originalRefs.slice();
SourceAssess._assessments = SourceAssess._originalRefs.map(function (ref, i) {
return SourceAssess._assessments[i] || { i: '', r: '', s: '', ij: '', rj: '', sj: '', '2': '', '2j': '', skipped: false };
});
rebuildRefList(SourceAssess._refs.map(function (ref) {
return { value: ref, original: ref };
}));
});
$(document).on('click.sourceassess-refeditor', '[name="sa-ref-editor-return"]', function (e) {
e.preventDefault();
// Build a map from original content to its assessment
var contentToAssessment = {};
SourceAssess._refs.forEach(function (ref, i) {
contentToAssessment[ref] = SourceAssess._assessments[i];
});
// Read edited values and their original content from data attributes
var newRefs = [];
var newAssessments = [];
var idx = 0;
while (true) {
var ta = document.querySelector('[name="sa-ref-edit-' + idx + '"]');
if (!ta) break;
var newVal = ta.value.trim();
var originalContent = ta.getAttribute('data-original-content') || '';
newRefs.push(newVal);
// If content unchanged, carry forward the matching assessment
// If content changed or new, use the assessment for that original slot or blank
newAssessments.push(
contentToAssessment[originalContent] ||
contentToAssessment[newVal] ||
{ i: '', r: '', s: '', ij: '', rj: '', sj: '', '2': '', '2j': '', skipped: false }
);
idx++;
}
SourceAssess._refs = newRefs;
SourceAssess._assessments = newAssessments;
if (SourceAssess._currentIndex >= newRefs.length) {
SourceAssess._currentIndex = newRefs.length - 1;
}
win3.close();
SourceAssess.displayWindow(SourceAssess._refs, SourceAssess._assessments);
});
};
// ─── Summary / output window ──────────────────────────────────────────────────
SourceAssess.showSummary = function (refs, assessments, prevWin) {
prevWin.close();
// Determine whether to build ORGCRIT
var isOrgcrit = SourceAssess._orgcrit || false;
var tableTemplate = isOrgcrit ? 'ORGCRIT assess table' : 'source assess table';
var entryTemplate = isOrgcrit ? 'ORGCRIT assess' : 'source assess';
var currentUser = mw.config.get('wgUserName');
// Build wikitext
var lines = ['{{' + tableTemplate];
if (!isOrgcrit) {
lines.push('| startopen = yes');
lines.push('| user = ' + currentUser);
}
lines.push('|');
refs.forEach(function (ref, idx) {
var a = assessments[idx];
if (a.skipped) return;
lines.push('{{' + entryTemplate);
lines.push('| source = ' + ref);
lines.push('| i = ' + a.i + ' | ij = ' + a.ij);
lines.push('| r = ' + a.r + ' | rj = ' + a.rj);
lines.push('| s = ' + a.s + ' | sj = ' + a.sj);
if (isOrgcrit) {
lines.push('| 2 = ' + a['2'] + ' | 2j = ' + a['2j']);
}
lines.push('}}');
});
lines.push('<!-- Generated using [[User:Bobby Cohn/SourceAssess|SourceAssess]] -->');
lines.push('}}');
var wikicode = lines.join('\n');
// ── New window ──
var win2 = new Morebits.simpleWindow(800, 720);
win2.setTitle('Source assessment table summary');
win2.setScriptName('SourceAssess');
win2.addFooterLink('Documentation', 'User:Bobby Cohn/SourceAssess');
win2.addFooterLink('Leave feedback', 'User talk:Bobby Cohn');
var form2 = new Morebits.quickForm(function () {});
// ── Rendered preview (parsed via API) ──
var previewSection = form2.append({
type: 'div',
label: 'Rendered preview',
style: 'font-weight:bold; margin-bottom:4px;'
});
previewSection.append({
type: 'div',
id: 'sa-preview-loading',
label: 'Loading preview…',
style: 'font-style:italic; color:#555;'
});
previewSection.append({
type: 'div',
id: 'sa-preview-content',
style: [
'border:1px solid #a2a9b1',
'border-radius:3px',
'padding:8px 10px',
'min-height:60px',
'max-height:380px',
'overflow-y:auto',
'display:none'
].join(';')
});
// ── Wikitext output ──
var codeSection = form2.append({
type: 'field',
label: 'Wikitext'
});
codeSection.append({
type: 'div',
style: 'margin-bottom:8px;'
}).append({
type: 'button',
label: 'Copy to clipboard',
name: 'sa-copy'
});
codeSection.append({
type: 'textarea',
name: 'sa-output',
value: wikicode,
style: [
'width:100%',
'height:200px',
'font-family:monospace',
'font-size:0.82em',
'white-space:pre',
'max-height:120px',
'resize:vertical'
].join(';')
});
form2.append({
type: 'button',
label: '← Return to assessment',
name: 'sa-return',
style: 'margin-bottom:12px;'
});
var rendered2 = form2.render();
win2.setContent(rendered2);
win2.display();
var dialog = document.querySelector('.morebits-dialog');
if (dialog) {
dialog.style.zIndex = '10000';
}
// Populate textarea (Morebits may not set value directly)
var ta = document.querySelector('[name="sa-output"]');
if (ta) ta.value = wikicode;
// Copy button
$(document).off('.sourceassess-summary');
$(document).on('click.sourceassess-summary', '[name="sa-copy"]', function (e) {
e.preventDefault();
var el = document.querySelector('[name="sa-output"]');
if (!el) return;
el.select();
try {
document.execCommand('copy');
mw.notify('SourceAssess: wikitext copied to clipboard.', { type: 'success' });
} catch (err) {
// Fallback for browsers blocking execCommand
if (navigator.clipboard) {
navigator.clipboard.writeText(el.value).then(function () {
mw.notify('SourceAssess: wikitext copied to clipboard.', { type: 'success' });
});
}
}
});
$(document).off('.sourceassess-return');
$(document).on('click.sourceassess-return', '[name="sa-return"]', function (e) {
e.preventDefault();
win2.close();
SourceAssess.displayWindow(SourceAssess._refs, SourceAssess._assessments);
});
// ── Fetch rendered preview ──
var api = new mw.Api();
api.post({
action: 'parse',
text: wikicode,
contentmodel: 'wikitext',
prop: 'text',
disablelimitreport: true,
formatversion: 2
}).then(function (data) {
var loading = document.getElementById('sa-preview-loading');
var content = document.getElementById('sa-preview-content');
if (loading) loading.style.display = 'none';
if (content) {
content.innerHTML = data.parse.text;
content.style.display = 'block';
// Make links open in new tab to avoid navigating away
content.querySelectorAll('a').forEach(function (a) {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener');
});
}
}).catch(function () {
var loading = document.getElementById('sa-preview-loading');
if (loading) loading.textContent = '(Preview unavailable – check wikitext below.)';
});
};
// </nowiki>