(function () { `use strict`; class MikuSyntaxHighlighter { constructor() { this.htmlTags = [ `html`, `head`, `title`, `body`, `div`, `span`, `p`, `a`, `img`, `ul`, `li`, `ol`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `strong`, `em`, `br`, `hr`, `table`, `tr`, `td`, `th`, `thead`, `tbody`, `form`, `input`, `button`, `select`, `option`, `textarea`, `label`, `section`, `article`, `header`, `footer`, `nav`, `aside`, `main`, `figure`, `figcaption`, `video`, `audio`, `source`, `canvas`, `svg`, `style`, `script`, `link`, `meta` ]; this.cssProperties = [ `background`, `background-color`, `background-image`, `color`, `font-family`, `font-size`, `font-weight`, `margin`, `padding`, `border`, `width`, `height`, `display`, `position`, `top`, `left`, `right`, `bottom`, `z-index`, `opacity`, `text-align`, `text-decoration`, `line-height`, `border-radius`, `box-shadow` ]; this.cssValues = [ `auto`, `none`, `block`, `inline`, `flex`, `grid`, `absolute`, `relative`, `fixed`, `center`, `left`, `right`, `bold`, `normal`, `hidden`, `visible` ]; this.jsKeywords = [ `function`, `var`, `let`, `const`, `if`, `else`, `for`, `while`, `do`, `switch`, `case`, `default`, `break`, `continue`, `return`, `try`, `catch`, `finally`, `throw`, `new`, `this`, `class`, `import`, `export`, `async`, `await` ]; } escapeHtml(text) { return text .replace(/&/g, `&`) .replace(//g, `>`) .replace(/"/g, `"`) .replace(/'/g, `'`); } wrapSpan(text, className) { return `${text}`; } highlightHtmlTag(tag) { const escapedTag = this.escapeHtml(tag); let result = escapedTag; result = result.replace(/<(\/?)([\w-]+)((?:\s+(?:[\w-:]+(?:\s*=\s*(?:"[^&]*"|'[^']*'|[^\s&>]*))?))*)>/g, (match, slash, tagName, attributesStr) => { const startBracket = '<' + slash; const endBracket = '>'; const highlightedTagName = this.wrapSpan(tagName, 'miku-syntax-html-tag'); let processedAttributes = attributesStr; if (attributesStr && attributesStr.trim()) { processedAttributes = attributesStr.replace(/\s+([\w-:]+)(?:\s*=\s*("[^&]*"|'[^']*'|[^\s&>]*))?/g, (attrMatch, attrName, attrValue) => { let result = ' ' + this.wrapSpan(attrName, 'miku-syntax-html-attribute'); if (attrValue !== undefined) { if (attrValue.startsWith('"') || attrValue.startsWith("'")) { result += '=' + this.wrapSpan(attrValue, 'miku-syntax-html-string'); } else { result += '=' + attrValue; } } return result; } ); } return startBracket + highlightedTagName + processedAttributes + endBracket; } ); return result; } highlightCSS(code) { if (!code.trim()) return this.escapeHtml(code); let result = ``; let i = 0; while (i < code.length) { if (code.substr(i, 2) === `/*`) { const commentEnd = code.indexOf(`*/`, i); if (commentEnd !== -1) { const comment = code.substring(i, commentEnd + 2); result += `${this.escapeHtml(comment)}`; i = commentEnd + 2; continue; } } if (/[a-zA-Z-]/.test(code[i])) { let word = ``; let wordStart = i; while (i < code.length && /[a-zA-Z-]/.test(code[i])) { word += code[i]; i++; } let nextChar = i; while (nextChar < code.length && /\s/.test(code[nextChar])) { nextChar++; } if (nextChar < code.length && code[nextChar] === `:`) { if (this.cssProperties.includes(word)) { result += `${this.escapeHtml(word)}`; } else { result += this.escapeHtml(word); } } else { if (this.cssValues.includes(word.toLowerCase())) { result += `${this.escapeHtml(word)}`; } else { result += this.escapeHtml(word); } } continue; } result += this.escapeHtml(code[i]); i++; } return result; } highlightJS(code) { if (!code.trim()) return this.escapeHtml(code); let result = ``; let i = 0; while (i < code.length) { if (code.substr(i, 2) === `//`) { const lineEnd = code.indexOf(`\n`, i); const comment = lineEnd !== -1 ? code.substring(i, lineEnd) : code.substring(i); result += `${this.escapeHtml(comment)}`; i = lineEnd !== -1 ? lineEnd : code.length; continue; } if (code.substr(i, 2) === `/*`) { const commentEnd = code.indexOf(`*/`, i); if (commentEnd !== -1) { const comment = code.substring(i, commentEnd + 2); result += `${this.escapeHtml(comment)}`; i = commentEnd + 2; continue; } } if (code[i] === `"` || code[i] === `'` || code[i] === `\``) { const quote = code[i]; let string = quote; i++; while (i < code.length && code[i] !== quote) { if (code[i] === `\\` && i + 1 < code.length) { string += code[i] + code[i + 1]; i += 2; } else { string += code[i]; i++; } } if (i < code.length) { string += code[i]; i++; } result += `${this.escapeHtml(string)}`; continue; } if (/\d/.test(code[i])) { let number = ``; while (i < code.length && /[\d.]/.test(code[i])) { number += code[i]; i++; } result += `${this.escapeHtml(number)}`; continue; } if (/[a-zA-Z_$]/.test(code[i])) { let word = ``; while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) { word += code[i]; i++; } if (this.jsKeywords.includes(word)) { result += `${this.escapeHtml(word)}`; } else { let nextChar = i; while (nextChar < code.length && /\s/.test(code[nextChar])) { nextChar++; } if (nextChar < code.length && code[nextChar] === `(`) { result += `${this.escapeHtml(word)}`; } else { result += this.escapeHtml(word); } } continue; } result += this.escapeHtml(code[i]); i++; } return result; } highlight(code) { if (!code) return ``; let result = ``; let i = 0; while (i < code.length) { if (code.substr(i, 4) === ``, i); if (commentEnd !== -1) { const comment = code.substring(i, commentEnd + 3); result += this.wrapSpan(this.escapeHtml(comment), `miku-syntax-html-comment`); i = commentEnd + 3; continue; } } if (code.substr(i, 6).toLowerCase() === ``, styleTagEnd); if (styleTagEnd !== -1 && styleEnd !== -1) { const openTag = code.substring(styleStart, styleTagEnd + 1); const cssContent = code.substring(styleTagEnd + 1, styleEnd); const closeTag = code.substring(styleEnd, styleEnd + 8); result += this.highlightHtmlTag(openTag); result += this.highlightCSS(cssContent); result += this.highlightHtmlTag(closeTag); i = styleEnd + 8; continue; } } if (code.substr(i, 7).toLowerCase() === ``, scriptTagEnd); if (scriptTagEnd !== -1 && scriptEnd !== -1) { const openTag = code.substring(scriptStart, scriptTagEnd + 1); const jsContent = code.substring(scriptTagEnd + 1, scriptEnd); const closeTag = code.substring(scriptEnd, scriptEnd + 9); result += this.highlightHtmlTag(openTag); result += this.highlightJS(jsContent); result += this.highlightHtmlTag(closeTag); i = scriptEnd + 9; continue; } } if (code[i] === `<` && i + 1 < code.length && /[a-zA-Z\/!]/.test(code[i + 1])) { let j = i + 1; let inQuotes = false; let quoteChar = null; let tagEnd = -1; while (j < code.length) { if (!inQuotes && code[j] === '>') { tagEnd = j; break; } if ((code[j] === '"' || code[j] === "'") && (j === 0 || code[j - 1] !== '\\')) { if (!inQuotes) { inQuotes = true; quoteChar = code[j]; } else if (code[j] === quoteChar) { inQuotes = false; } } j++; } if (tagEnd !== -1) { const tag = code.substring(i, tagEnd + 1); result += this.highlightHtmlTag(tag); i = tagEnd + 1; continue; } } result += this.escapeHtml(code[i]); i++; } return result; } } class MikuAutocomplete { constructor() { this.htmlTags = [ `html`, `head`, `title`, `body`, `div`, `span`, `p`, `a`, `ul`, `li`, `ol`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `strong`, `em`, `table`, `tr`, `td`, `th`, `thead`, `tbody`, `form`, `button`, `select`, `option`, `textarea`, `label`, `section`, `article`, `header`, `footer`, `nav`, `aside`, `main`, `figure`, `figcaption`, `video`, `audio`, `source`, `canvas`, `svg`, `style`, `script`, `link`, `meta` ]; this.voidElements = [ `br`, `hr`, `img`, `input`, `meta`, `link`, `area`, `base`, `col`, `embed`, `source`, `track`, `wbr` ]; this.htmlAttributes = [ `id`, `class`, `style`, `src`, `href`, `alt`, `title`, `data-`, `role`, `type`, `name`, `value`, `placeholder`, `required`, `disabled`, `readonly`, `width`, `height`, `target`, `rel`, `for`, `method`, `action` ]; this.cssProperties = [ `background`, `background-color`, `background-image`, `background-size`, `color`, `font-family`, `font-size`, `font-weight`, `font-style`, `text-align`, `text-decoration`, `line-height`, `margin`, `margin-top`, `margin-bottom`, `margin-left`, `margin-right`, `padding`, `padding-top`, `padding-bottom`, `padding-left`, `padding-right`, `border`, `border-radius`, `width`, `height`, `display`, `position`, `top`, `bottom`, `left`, `right`, `z-index`, `opacity` ]; this.cssValues = [ `auto`, `none`, `inherit`, `initial`, `block`, `inline`, `inline-block`, `flex`, `grid`, `absolute`, `relative`, `fixed`, `static`, `center`, `left`, `right`, `bold`, `normal`, `italic`, `underline`, `hidden`, `visible` ]; this.jsKeywords = [ `function`, `var`, `let`, `const`, `if`, `else`, `for`, `while`, `do`, `switch`, `case`, `default`, `break`, `continue`, `return`, `try`, `catch`, `finally`, `throw`, `new`, `this`, `super`, `class`, `extends`, `import`, `export`, `from`, `as`, `async`, `await`, `typeof`, `instanceof`, `in`, `of`, `delete` ]; this.jsMethods = [ `console.log`, `document.getElementById`, `document.querySelector`, `addEventListener`, `setTimeout`, `setInterval`, `JSON.parse`, `JSON.stringify`, `Math.floor`, `Math.ceil`, `Math.round`, `Math.random`, `fetch`, `alert` ]; this.emmetAbbreviations = { div: `
`, p: ``, span: ``, a: ``, ul: `