monorepo/native/wordpress/maple-code-blocks/assets/js/prism.js

182 lines
6.6 KiB
JavaScript

/* PrismJS - Minimal Core for GitHub Code Viewer */
/* This is a simplified version focused on safety and basic highlighting */
(function(){
if (typeof self === 'undefined' || !self.Prism || !self.document) {
return;
}
var Prism = window.Prism = {
languages: {},
// Simplified tokenization with infinite loop prevention
tokenize: function(text, grammar) {
// Prevent tokenizing huge files
if (text.length > 100000) {
return [text]; // Return as plain text for very large files
}
var tokens = [];
var rest = text;
var maxIterations = 10000; // Prevent infinite loops
var iterations = 0;
while (rest.length > 0 && iterations < maxIterations) {
iterations++;
var matchFound = false;
for (var token in grammar) {
if (!grammar.hasOwnProperty(token) || !grammar[token]) {
continue;
}
var pattern = grammar[token];
if (pattern instanceof RegExp) {
var matches = rest.match(pattern);
if (matches && matches.index === 0) {
matchFound = true;
tokens.push({
type: token,
content: matches[0]
});
rest = rest.substring(matches[0].length);
break;
}
}
}
// If no match found, consume one character as plain text
if (!matchFound) {
if (tokens.length > 0 && typeof tokens[tokens.length - 1] === 'string') {
tokens[tokens.length - 1] += rest.charAt(0);
} else {
tokens.push(rest.charAt(0));
}
rest = rest.substring(1);
}
}
// Add any remaining text
if (rest.length > 0) {
tokens.push(rest);
}
return tokens;
},
// Highlight element
highlightElement: function(element) {
var language = element.className.match(/language-(\w+)/);
if (!language) return;
language = language[1];
var grammar = Prism.languages[language];
if (!grammar) return;
// Get text content (already HTML escaped by PHP)
var code = element.textContent;
// Simple tokenization
var tokens = Prism.tokenize(code, grammar);
// Build highlighted HTML (safe because content is already escaped)
var highlighted = tokens.map(function(token) {
if (typeof token === 'string') {
return token;
}
return '<span class="token ' + token.type + '">' + token.content + '</span>';
}).join('');
element.innerHTML = highlighted;
},
// Highlight all code blocks
highlightAll: function() {
var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code');
for (var i = 0, element; element = elements[i++];) {
Prism.highlightElement(element);
}
}
};
// Define basic grammars for common languages
Prism.languages.javascript = {
'comment': /\/\/.*|\/\*[\s\S]*?\*\//,
'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
'keyword': /\b(?:var|let|const|function|return|if|else|for|while|do|switch|case|break|continue|typeof|instanceof|new|this|throw|try|catch|finally|async|await|class|extends|super|import|export|default|yield)\b/,
'boolean': /\b(?:true|false)\b/,
'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/,
'operator': /[+\-*/%=!<>&|^~?:]+/,
'punctuation': /[{}[\];(),.:]/
};
Prism.languages.python = {
'comment': /#.*/,
'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield)\b/,
'boolean': /\b(?:True|False|None)\b/,
'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?j?/i,
'operator': /[+\-*/%=!<>&|^~]+/,
'punctuation': /[{}[\];(),.:]/
};
Prism.languages.php = {
'comment': /\/\/.*|\/\*[\s\S]*?\*\/|#.*/,
'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
'keyword': /\b(?:abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
'boolean': /\b(?:false|true)\b/i,
'variable': /\$\w+/,
'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
'operator': /[+\-*/%=!<>&|^~?:]+/,
'punctuation': /[{}[\];(),.:]/
};
Prism.languages.html = Prism.languages.xml = {
'comment': /<!--[\s\S]*?-->/,
'tag': {
pattern: /<\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\.|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
inside: {
'punctuation': /^<\/?|\/?>$/,
'attr-name': /[^\s>\/]+/,
'attr-value': /=(?:("|')(?:\\.|(?!\1)[^\\])*\1|[^\s'">=]+)/i
}
}
};
Prism.languages.css = {
'comment': /\/\*[\s\S]*?\*\//,
'atrule': /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
'url': /url\((?:(["'])(?:\\.|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
'selector': /[^{}\s][^{}]*(?=\s*\{)/,
'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
'important': /!important\b/i,
'punctuation': /[(){};:]/
};
Prism.languages.json = {
'property': /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i,
'string': /"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,
'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
'punctuation': /[{}[\]);,]/,
'operator': /:/g,
'boolean': /\b(?:true|false)\b/i,
'null': /\bnull\b/i
};
// Language aliases
Prism.languages.js = Prism.languages.javascript;
Prism.languages.py = Prism.languages.python;
// Auto-initialize
if (document.readyState !== 'loading') {
setTimeout(Prism.highlightAll, 0);
} else {
document.addEventListener('DOMContentLoaded', Prism.highlightAll);
}
})();