Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Any JavaScript here will be loaded for all users on every page load. */
/* DRUID */
$(function () {
$(".druid-main-images-label").off("click");
$(".druid-main-images-label").click(function () {
var $parent = $(this).closest(".druid-container");
$parent.find(".druid-toggleable").removeClass("focused");
var i = $(this).attr("data-druid");
$parent.find(".druid-toggleable[data-druid=" + i + "]").addClass("focused");
});
$(".druid-collapsible").off("click");
$(".druid-collapsible").click(function () {
var kind = $(this).attr("data-druid-section");
$(this).toggleClass("druid-collapsible-collapsed");
$(this)
.closest(".druid-container")
.find("[data-druid-section-row=" + kind + "]")
.toggleClass("druid-collapsed");
});
});
/* End DRUID */
/* [[Template:Spoiler]] */
$(function () {
$('.spoiler-content')
.off('click') // in case this code is loaded twice
.on('click', function(e){
$(this).toggleClass('show');
}).find('a').on('click', function(e){
e.stopPropagation();
});
});
/* End Template:Spoiler */
/* Link to imported modules from Lua code */
$(function() {
var config = mw.config.get([
'wgCanonicalNamespace',
'wgFormattedNamespaces'
]);
if (config.wgCanonicalNamespace !== 'Module') {
return;
}
var localizedNamespace = config.wgFormattedNamespaces[828];
$('.s1, .s2, .s').each(function() {
var $this = $(this);
var html = $this.html();
var quote = html[0];
var isLongStringQuote = quote === '[';
var quoteRE = new RegExp('^\\' + quote + '|\\' + quote + '$', 'g');
if (isLongStringQuote) {
quoteRE = /^\[\[|\]\]$/g;
}
var name = html.replace(quoteRE, '');
var isEnglishPrefix = name.startsWith('Module:');
var isLocalizedPrefix = name.startsWith(localizedNamespace + ':');
var isDevPrefix = name.startsWith('Dev:');
if (isEnglishPrefix || isLocalizedPrefix || isDevPrefix) {
var attrs = {
href: mw.util.getUrl(name)
};
if (isDevPrefix) {
attrs.href = 'https://commons.wiki.gg/wiki/Module:' + mw.util.wikiUrlencode(name.replace('Dev:', ''));
attrs.target = '_blank';
attrs.rel = 'noopener';
}
var link = mw.html.element('a', attrs, name);
var str = quote + link + quote;
if (isLongStringQuote) {
str = '[[' + link + ']]';
}
$this.html(str);
}
});
});
/* dynamic gif displayer ONLY TOUCH IF YOU KNOW WHAT YOU ARE DOING */
(function() {
'use strict';
console.log('Dynamic GIF Displayer: Script loading...');
// Configuration
const CONFIG = {
containerClass: 'dynamic-gif-container',
displayClass: 'gif-display-area',
autoExpand: true,
expandDelay: 200,
collapseDelay: 1000
};
let expandTimer = null;
let collapseTimer = null;
let currentGif = null;
function safeCreateError(message) {
const div = document.createElement('div');
div.className = 'gif-error';
div.textContent = message;
return div;
}
function safeCreatePlaceholder(message) {
const div = document.createElement('div');
div.className = 'gif-placeholder';
div.textContent = message;
return div;
}
function init() {
console.log('Dynamic GIF Displayer: Initializing...');
const containers = document.querySelectorAll('.' + CONFIG.containerClass);
console.log('Dynamic GIF Displayer: Found', containers.length, 'containers');
containers.forEach(container => {
console.log('Dynamic GIF Displayer: Setting up container', container.id);
setupContainer(container);
attachTooltipListeners(container);
});
}
function setupContainer(container) {
const displayArea = container.querySelector('.' + CONFIG.displayClass);
if (!displayArea) {
console.error('Dynamic GIF Displayer: No display area found');
return;
}
displayArea.addEventListener('mouseenter', () => {
clearTimeout(collapseTimer);
});
displayArea.addEventListener('mouseleave', () => {
scheduleCollapse(container);
});
}
function attachTooltipListeners(container) {
console.log('Dynamic GIF Displayer: Attaching tooltip listeners...');
const gifMap = buildGifMap(container);
console.log('Dynamic GIF Displayer: GIF map', gifMap);
const tooltips = document.querySelectorAll('.advanced-tooltip');
console.log('Dynamic GIF Displayer: Found', tooltips.length, 'tooltips');
tooltips.forEach((tooltip) => {
const skillTitle = tooltip.querySelector('.skill-title');
if (!skillTitle) return;
const skillName = skillTitle.textContent.trim();
const gifUrl = gifMap[skillName];
console.log('Dynamic GIF Displayer: Processing tooltip:', skillName, 'GIF:', gifUrl);
if (gifUrl) {
tooltip.removeEventListener('mouseenter', tooltip._gifHoverHandler);
tooltip.removeEventListener('mouseleave', tooltip._gifLeaveHandler);
tooltip._gifHoverHandler = () => handleTooltipHover(container, gifUrl, skillName);
tooltip._gifLeaveHandler = () => scheduleCollapse(container);
tooltip.addEventListener('mouseenter', tooltip._gifHoverHandler);
tooltip.addEventListener('mouseleave', tooltip._gifLeaveHandler);
console.log('Dynamic GIF Displayer: Attached listeners to', skillName);
}
});
}
function buildGifMap(container) {
const gifMap = {};
const listData = container.getAttribute('data-gif-list');
if (!listData) {
console.error('Dynamic GIF Displayer: No data-gif-list attribute found');
return gifMap;
}
console.log('Dynamic GIF Displayer: Raw list data:', listData);
const entries = listData.split(';').filter(e => e.trim());
console.log('Dynamic GIF Displayer: Found', entries.length, 'entries');
entries.forEach(entry => {
const parts = entry.split(':');
if (parts.length >= 2) {
const skillName = parts[0].trim();
const gifFile = parts.slice(1).join(':').trim();
if (skillName && gifFile) {
let gifUrl;
if (typeof mw !== 'undefined' && mw.config) {
gifUrl = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/images/' + gifFile;
} else {
gifUrl = '/images/' + gifFile;
}
gifMap[skillName] = gifUrl;
console.log('Dynamic GIF Displayer: Mapped "' + skillName + '" to', gifUrl);
}
}
});
return gifMap;
}
function handleTooltipHover(container, gifUrl, skillName) {
console.log('Dynamic GIF Displayer: Hovering', skillName);
clearTimeout(collapseTimer);
clearTimeout(expandTimer);
expandTimer = setTimeout(() => {
showGif(container, gifUrl, skillName);
}, CONFIG.expandDelay);
}
function showGif(container, gifUrl, skillName) {
console.log('Dynamic GIF Displayer: Showing GIF for', skillName, gifUrl);
const displayArea = container.querySelector('.' + CONFIG.displayClass);
if (!displayArea) return;
const gifSize = container.getAttribute('data-gif-size') || '400';
if (!container.classList.contains('expanded')) {
container.classList.add('expanded');
console.log('Dynamic GIF Displayer: Expanded container');
}
if (currentGif !== gifUrl) {
const imgContainer = displayArea.querySelector('.gif-image-container');
const caption = displayArea.querySelector('.gif-caption');
if (imgContainer) {
const placeholder = imgContainer.querySelector('.gif-placeholder');
if (placeholder) {
placeholder.remove();
}
imgContainer.style.height = gifSize + 'px';
imgContainer.style.minHeight = gifSize + 'px';
const gifFilename = gifUrl.split('/').pop();
if (gifFilename.toLowerCase() === 'blank' || gifFilename.toLowerCase() === 'blank.gif') {
imgContainer.innerHTML = '';
imgContainer.appendChild(safeCreatePlaceholder('This node does not require a GIF due to its simplicity.'));
imgContainer.classList.remove('loading');
} else {
imgContainer.classList.add('loading');
const img = document.createElement('img');
img.src = gifUrl;
img.alt = skillName;
img.style.maxHeight = gifSize + 'px';
img.onload = () => {
imgContainer.innerHTML = '';
imgContainer.appendChild(img);
imgContainer.classList.remove('loading');
console.log('Dynamic GIF Displayer: GIF loaded successfully');
};
img.onerror = () => {
imgContainer.innerHTML = '';
imgContainer.appendChild(safeCreateError('GIF not found: ' + gifUrl));
imgContainer.classList.remove('loading');
console.error('Dynamic GIF Displayer: Failed to load GIF', gifUrl);
};
}
}
if (caption) {
caption.textContent = skillName;
caption.style.display = 'block';
}
currentGif = gifUrl;
}
}
function scheduleCollapse(container) {
clearTimeout(collapseTimer);
collapseTimer = setTimeout(() => {
container.classList.remove('expanded');
const displayArea = container.querySelector('.' + CONFIG.displayClass);
if (displayArea) {
const imgContainer = displayArea.querySelector('.gif-image-container');
const caption = displayArea.querySelector('.gif-caption');
if (imgContainer) {
imgContainer.innerHTML = '';
imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
imgContainer.style.height = '';
imgContainer.style.minHeight = '';
}
if (caption) {
caption.textContent = '';
caption.style.display = 'none';
}
}
currentGif = null;
console.log('Dynamic GIF Displayer: Collapsed container and cleared content');
}, CONFIG.collapseDelay);
}
window.toggleGifDisplay = function(containerId) {
console.log('Dynamic GIF Displayer: Toggle clicked for', containerId);
const container = document.getElementById(containerId);
if (!container) {
console.error('Dynamic GIF Displayer: Container not found', containerId);
return;
}
clearTimeout(collapseTimer);
if (container.style.display === 'none') {
container.style.display = 'block';
} else {
container.style.display = 'none';
}
if (container.style.display === 'none') {
const displayArea = container.querySelector('.' + CONFIG.displayClass);
if (displayArea) {
const imgContainer = displayArea.querySelector('.gif-image-container');
const caption = displayArea.querySelector('.gif-caption');
if (imgContainer) {
imgContainer.innerHTML = '';
imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
imgContainer.style.height = '';
imgContainer.style.minHeight = '';
}
if (caption) {
caption.textContent = '';
caption.style.display = 'none';
}
}
container.classList.remove('expanded');
currentGif = null;
}
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
window.addEventListener('load', init);
if (typeof mw !== 'undefined' && mw.hook) {
mw.hook('wikipage.content').add(init);
}
const observer = new MutationObserver(function(mutations) {
let shouldReinit = false;
mutations.forEach(function(mutation) {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1 && (
node.classList && node.classList.contains('advanced-tooltip') ||
node.querySelector && node.querySelector('.advanced-tooltip')
)) {
shouldReinit = true;
}
});
}
});
if (shouldReinit) {
console.log('Dynamic GIF Displayer: Content changed, reinitializing...');
setTimeout(init, 100);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
console.log('Dynamic GIF Displayer: Script loaded');
})();
class WikiLinkParser {
constructor(options = {}) {
this.options = {
baseUrl: options.baseUrl || '/wiki/',
openInNewWindow: options.openInNewWindow !== false,
checkExistence: options.checkExistence !== false,
slugify: options.slugify !== false,
existingPages: options.existingPages || ['HomePage', 'Documentation', 'Getting Started', 'API Reference', 'JavaScript', 'Regular Expressions']
};
}
// Main parsing function
parse(text) {
// Pattern matches [[Link]] or [[Link|Display]]
const linkPattern = /\[\[([^\[\]|]+)(?:\|([^\[\]]+))?\]\]/g;
let linkCount = 0;
const uniqueLinks = new Set();
const parsed = text.replace(linkPattern, (match, link, display) => {
linkCount++;
uniqueLinks.add(link.trim());
return this.createLink(link.trim(), display ? display.trim() : null);
});
return {
html: parsed,
stats: {
linkCount,
uniqueLinks: uniqueLinks.size
}
};
}
// Create HTML link from wiki syntax
createLink(pageName, displayText = null) {
const text = displayText || pageName;
const url = this.generateUrl(pageName);
const exists = this.pageExists(pageName);
const className = exists ? 'wiki-link' : 'wiki-link missing';
const target = this.options.openInNewWindow ? ' target="_blank"' : '';
const title = exists ? `Go to ${pageName}` : `${pageName} (page does not exist)`;
return `<a href="${url}" class="${className}" title="${title}"${target}>${text}</a>`;
}
// Generate URL from page name
generateUrl(pageName) {
let url = pageName;
// Handle special namespaces
if (pageName.includes(':')) {
const [namespace, name] = pageName.split(':', 2);
url = `${namespace.toLowerCase()}/${name}`;
}
// Slugify if option is enabled
if (this.options.slugify) {
url = url
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w\-\/]/g, '');
}
return this.options.baseUrl + url;
}
// Check if page exists (mock implementation)
pageExists(pageName) {
if (!this.options.checkExistence) return true;
// Remove namespace for checking
const cleanName = pageName.includes(':')
? pageName.split(':', 2)[1]
: pageName;
return this.options.existingPages.includes(cleanName);
}
// Parse and convert to HTML with line breaks
parseToHtml(text) {
const result = this.parse(text);
// Convert line breaks to <br> tags for display
result.html = result.html.replace(/\n/g, '<br>');
return result;
}
}
// Initialize the demo
let parser = new WikiLinkParser();
function updatePreview() {
const input = document.getElementById('input').value;
const preview = document.getElementById('preview');
const stats = document.getElementById('stats');
// Update parser options based on checkboxes
parser.options.openInNewWindow = document.getElementById('newWindow').checked;
parser.options.checkExistence = document.getElementById('checkExistence').checked;
parser.options.slugify = document.getElementById('slugify').checked;
const result = parser.parseToHtml(input);
preview.innerHTML = result.html;
stats.innerHTML = `Links found: ${result.stats.linkCount} | Unique pages: ${result.stats.uniqueLinks}`;
}
// Set up event listeners
document.getElementById('input').addEventListener('input', updatePreview);
document.getElementById('newWindow').addEventListener('change', updatePreview);
document.getElementById('checkExistence').addEventListener('change', updatePreview);
document.getElementById('slugify').addEventListener('change', updatePreview);
// Initial preview
updatePreview();
// Make parser available globally for console experimentation
window.wikiParser = parser;
console.log('WikiLinkParser is available as window.wikiParser for testing');