Pail/backtick-comments.js

113 lines
4.7 KiB
JavaScript
Raw Normal View History

const jsKeywords = new Set([
"abstract", "arguments", "await*", "boolean", "break", "byte", "case",
"catch", "char", "class*", "const", "continue", "debugger", "default",
"delete", "do", "double", "else", "enum*", "eval", "export*", "extends*",
"false", "final", "finally", "float", "for", "function", "goto", "if",
"implements", "import*", "in", "instanceof", "int", "interface", "let*",
"long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "super*", "switch", "synchronized", "this",
"throw", "throws", "transient", "true", "try", "typeof", "var", "void",
"volatile", "while", "with", "yield"
])
const csKeywords = new Set([
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char",
"checked", "class", "const", "continue", "decimal", "default", "delegate",
"do", "double", "else", "enum", "event", "explicit", "extern", "false",
"finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
"in", "int", "interface", "internal", "is", "lock", "long", "namespace",
"new", "null", "object", "operator", "out", "override", "params", "private",
"protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
"short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked",
"unsafe", "ushort", "using", "virtual", "void", "volatile", "while",
])
const javaKeywords = new Set([
"abstract", "continue", "for", "new", "switch", "assert", "default",
"goto", "package", "synchronized", "boolean", "do", "if", "private",
"this", "break", "double", "implements", "protected", "throw", "byte",
"else", "import", "public", "throws", "case", "enum", "instanceof",
"return", "transient", "catch", "extends", "int", "short", "try", "char",
"final", "interface", "static", "void", "class", "finally", "long",
"strictfp", "volatile", "const", "float", "native", "super", "while",
])
const keywordMap = {
js: jsKeywords,
mjs: jsKeywords,
java: javaKeywords,
cs: csKeywords,
none: new Set()
}
const bookendedWith = (text, bookend) => text.startsWith(bookend) && text.endsWith(bookend)
const getClass = (text, prefix, keywords) => {
if (keywords.has(text)) {
return prefix + 'keyword'
}
if (bookendedWith(text, '"')) {
return prefix + 'string'
}
return prefix + 'variable'
}
const getKeywords = () => keywordMap[getFileName()?.replace(/.*\./g, '')] || keywordMap.none
const commentSpan = (innerText, prefix) => {
const span = document.createElement('span')
span.innerText = innerText
span.classList.add(prefix + 'comment')
return span
}
const colorCodeInComment = (codeStart = '`', codeEnd) => {
codeEnd ??= codeStart
const processed = new Set()
const keywords = getKeywords()
const comments = [...getClassNameElementsArray('hl-comment'), ...getClassNameElementsArray('cm-comment')]
comments.forEach(element => {
const codeStartIndex = element.innerText?.indexOf(codeStart)
if (codeStartIndex === -1 || processed.has(element)) {
return
}
const prefix = element.classList.contains('hl-comment') ? 'hl-' : 'cm-'
const endOfCodeStart = codeStartIndex + codeStart.length
const codeStartText = element.innerText.substring(0, endOfCodeStart)
const codeStartElement = commentSpan(codeStartText, prefix)
element.innerText = element.innerText.substring(endOfCodeStart, element.innerText.length)
element.replaceWith(codeStartElement, element)
while (element) {
if (!element.classList.contains('hl-comment') && !element.classList.contains('cm-comment')) {
break
}
processed.add(element)
element.classList.remove(`${prefix}comment`)
const text = element.innerText.replaceAll(codeStart, '').replaceAll(codeEnd, '')
element.classList.add(getClass(text, prefix, keywords))
const codeEndIndex = element.innerText.indexOf(codeEnd)
if (codeEndIndex > -1) {
const codeEndElement = commentSpan(element.innerText.substring(codeEndIndex), prefix)
element.innerText = element.innerText.substring(0, codeEndIndex)
element.replaceWith(element, codeEndElement)
break
}
element = element.nextElementSibling
}
})
}
const commentCodeFix = () => {
colorCodeInComment('`', '`')
colorCodeInComment('<code>', '</code>')
colorCodeInComment('<pre>', '</pre>')
colorCodeInComment('<tt>', '</tt>')
}
addFix(commentCodeFix)