// Окрашивает внутренние ссылки в редакторе вики-кода при включённой подсветке синтаксиса:
// рабочие ссылки - в синий цвет
// нерабочие - в красный
// перенаправления - в зелёный
// [ДАННЫЕ УДАЛЕНЫ] - в серый
//
// Для корректной работы скрипта необходимо задать кастомные стили,
// см. .cm-link-* в [[:meta:User:I am smiling/global.css]]
mw.loader.using(['ext.wikiEditor']).then(() => {
mw.loader.using(['mediawiki.api', 'jquery']).then(() => {
function highlightLinks(cm) {
const doc = cm.getDoc();
const text = doc.getValue();
const linkRegex = /\[\[([^\[\]|]+)(?:\|[^\[\]]+)?\]\]/g;
const titles = new Set();
let match;
while ((match = linkRegex.exec(text)) !== null) {
titles.add(match[1].trim());
}
getLinkStatuses([...titles]).then(statuses => {
cm.addOverlay({
token: function (stream) {
if (stream.match(/\[\[[^\[\]|]+(?:\|[^\[\]]+)?\]\]/)) {
const raw = stream.current();
const m = raw.match(/^\[\[([^\[\]|]+)(?:\|.*)?\]\]$/);
if (!m) return null;
const title = m[1].trim();
const status = statuses[title] || 'grey';
return `link-${status}`;
} else {
stream.next();
return null;
}
}
});
});
}
async function getLinkStatuses(titles) {
const result = {};
const chunks = [];
for (let i = 0; i < titles.length; i += 50) {
chunks.push(titles.slice(i, i + 50));
}
for (const chunk of chunks) {
try {
const data = await new mw.Api().get({
action: 'query',
format: 'json',
redirects: 1,
titles: chunk.join('|')
});
for (const [id, page] of Object.entries(data.query.pages)) {
const title = page.title;
if (parseInt(id) < 0) result[title] = 'red';
else if (page.redirect) result[title] = 'green';
else result[title] = 'blue';
}
if (data.query.redirects) {
for (const redir of data.query.redirects) {
result[redir.from] = result[redir.to] === 'blue' ? 'green' : result[redir.to];
}
}
} catch (e) {
console.warn('Status not found', e);
}
}
return result;
}
// Запускаем изначально (если CodeMirror включён сразу)
const initialCM = $(".wikiEditor-ui .CodeMirror")[0]?.CodeMirror;
if (initialCM) {
highlightLinks(initialCM);
}
// Слушаем появления новых CodeMirror после переключения чекбокса
new MutationObserver(() => {
const cm = $(".wikiEditor-ui .CodeMirror")[0]?.CodeMirror;
if (cm && !cm._wikilinkOverlayAdded) {
cm._wikilinkOverlayAdded = true; // чтобы не дублировать
highlightLinks(cm);
}
}).observe(document.body, { childList: true, subtree: true });
});
});