182 lines
6.6 KiB
JavaScript
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);
|
|
}
|
|
|
|
})();
|