diff --git a/llama.cpp/server/public/index.html b/llama.cpp/server/public/index.html
index ce78652ee1..c916d012dc 100644
--- a/llama.cpp/server/public/index.html
+++ b/llama.cpp/server/public/index.html
@@ -121,9 +121,13 @@
}
pre code {
+ background-color: #22211f;
+ padding: 0.3em 0.3em;
display: block;
background-color: #222;
color: #ddd;
+ overflow-x: auto;
+ tab-size: 4;
}
code {
@@ -131,6 +135,13 @@
padding: 0.1em 0.3em;
border-radius: 3px;
}
+ code span.sh-c { color: #999; } /* comment */
+ code span.sh-s { color: #ae2; } /* string */
+ code span.sh-r { color: #b8f; } /* regexp */
+ code span.sh-p { color: #5df; } /* punctuation */
+ code span.sh-k { color: #f07; } /* keyword */
+ code span.sh-n { color: #fa4; } /* number */
+ code span.sh-d { color: #a8f; } /* defintion */
fieldset label {
margin: 0.5em 0;
@@ -828,20 +839,261 @@
});
}
- // poor mans markdown replacement
+ // Syntax Highlighting, condensed down from https://github.com/speed-highlight/core
+ // Following is a number of regexps that capture some generic highlightable syntax
+ // such as "strings" or /* comments */. These regexps are then utilizied by the
+ // language definitions below, assigning each regexp to a `type`. The type maps
+ // to a sh-* css class.
+
+ const SH_REGEXP = {
+ STRING: /("|')(\\[^]|(?!\1)[^\r\n\\])*\1?/g,
+ STRING_BACKTICK: /`((?!`)[^]|\\[^])*`?/g,
+ COMMENT: /\/\/.*\n?|\/\*((?!\*\/)[^])*(\*\/)?/g,
+ COMMENT_HASH: /#.*\n?/g,
+ COMMENT_PYTHON: /("""|''')(\\[^]|(?!\1)[^])*\1?/g,
+ PREPROC: /#\s*\w+(\\\n|[^\n])*\n?/g,
+ COMMENT_DASH: /--.*\n?/g,
+ COMMENT_XML: /<!--((?!-->)[^])*-->/g,
+ KW: /\b(set|get|as|break|case|const|continue|default|delete|do|else|export|for|from|function|goto|if|import|extern|in|let|var|null|of|package|return|static|switch|typeof|void|while)\b/g,
+ CLASS: /\b(class|constructor|extends|implements|interface|new|private|protected|public|super|this|abstract|final|virtual|instanceof)\b/g,
+ EXCEPTION: /\b(try|throw|throws|catch|finnaly)\b/g,
+ BOOL: /\b(true|false)\b/g,
+ BOOL_PYTHON: /\b(True|False)\b/g,
+ KW_ASYNC: /\b(async|await|yield)\b/g,
+ KW_JS: /\b(with|NaN|debugger|undefined)\b/g,
+ KW_RS: /\b(crate|fn|impl|loop|match|mod|move|mut|pub|ref|self|Self|trait|type|unsafe|use|where|dyn|become|box|macro|override|priv|unsized)\b/g,
+ KW_LUA: /\b(and|elseif|end|local|nil|not|or|repeat|then|until)\b/g,
+ KW_PYTHON: /\b(and|as|assert|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\b/g,
+ TYPES: /\b(char|double|enum|float|int|signed|unsigned|struct|union)\b/g,
+ TYPES_SQL: /\b(varchar|(tiny|medium|long|big)(text|blob|int)|integer|decimal|boolean)\b/g,
+ REGEX: /\/((?!\/)[^\r\n\\]|\\.)+\/[dgimsuy]*/g,
+ NUM: /(\.e?|\b)\d(e-|[\d.oxa-fA-F_])*(\.|\b)/g,
+ DEF: /\b([A-Z][A-Z_]*)\b/g,
+ OP: /(&|<|>|[/*+:?|%^~=!,.^-])+/g,
+ XML_ELEM: /<\w+|<\/\w+|>/g
+ };
+
+ const SH_LANGS = {
+ generic: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ py: [
+ {type: 'c', match: SH_REGEXP.COMMENT_PYTHON},
+ {type: 'c', match: SH_REGEXP.COMMENT_HASH},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.BOOL_PYTHON},
+ {type: 'k', match: SH_REGEXP.KW_PYTHON},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ js: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 's', match: SH_REGEXP.STRING_BACKTICK},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'k', match: SH_REGEXP.EXCEPTION},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.CLASS},
+ {type: 'k', match: SH_REGEXP.KW_ASYNC},
+ {type: 'k', match: SH_REGEXP.KW_JS},
+ {type: 'r', match: SH_REGEXP.REGEX},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ json: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ ],
+ bash: [
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'c', match: SH_REGEXP.COMMENT_HASH},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ c: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.TYPES},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.PREPROC},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ cpp: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'k', match: SH_REGEXP.EXCEPTION},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.CLASS},
+ {type: 'k', match: SH_REGEXP.TYPES},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ rs: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'r', match: SH_REGEXP.REGEX},
+ {type: 'k', match: SH_REGEXP.EXCEPTION},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.CLASS},
+ {type: 'k', match: SH_REGEXP.TYPES},
+ {type: 'k', match: SH_REGEXP.KW_ASYNC},
+ {type: 'k', match: SH_REGEXP.KW_RS},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ lua: [
+ {type: 'c', match: SH_REGEXP.COMMENT_DASH},
+ {type: 'c', match: SH_REGEXP.COMMENT_HASH},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'k', match: SH_REGEXP.KW_LUA},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ java: [
+ {type: 'c', match: SH_REGEXP.COMMENT},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'n', match: SH_REGEXP.DEF},
+ {type: 'k', match: SH_REGEXP.KW},
+ {type: 'k', match: SH_REGEXP.EXCEPTION},
+ {type: 'k', match: SH_REGEXP.BOOL},
+ {type: 'k', match: SH_REGEXP.CLASS},
+ {type: 'k', match: SH_REGEXP.TYPES},
+ ],
+ sql: [
+ {type: 'c', match: SH_REGEXP.COMMENT_DASH},
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 's', match: SH_REGEXP.STRING_BACKTICK},
+ {type: 'r', match: SH_REGEXP.TYPES},
+ {type: 'r', match: SH_REGEXP.TYPES_SQL},
+ {type: 'n', match: SH_REGEXP.NUM},
+ {type: 'k', match: SH_REGEXP.DEF},
+ {type: 'p', match: SH_REGEXP.OP},
+ ],
+ html: [
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'c', match: SH_REGEXP.COMMENT_XML},
+ {type: 'k', match: SH_REGEXP.XML_ELEM},
+ ],
+ xml: [
+ {type: 's', match: SH_REGEXP.STRING},
+ {type: 'c', match: SH_REGEXP.COMMENT_XML},
+ {type: 'k', match: SH_REGEXP.XML_ELEM},
+ ]
+ };
+ SH_LANGS.python = SH_LANGS.py;
+ SH_LANGS.rust = SH_LANGS.rs;
+ SH_LANGS.javascript = SH_LANGS.js;
+
+ const Syntaxhighlightish = (src, lang) => {
+ let html = '';
+ const cache = [];
+ const rules = (SH_LANGS[lang] || SH_LANGS.generic).slice();
+
+ let i = 0;
+ while (i < src.length) {
+ let fm = null;
+ let ft = '';
+ for (let r = rules.length; r-- > 0;) {
+ const token = rules[r];
+
+ if (cache[r] === undefined || cache[r].index < i) {
+ token.match.lastIndex = i;
+ const match = token.match.exec(src);
+ if (match === null) {
+ rules.splice(r, 1);
+ cache.splice(r, 1);
+ continue;
+ }
+ cache[r] = match;
+ }
+ if (cache[r][0] && (fm === null || cache[r].index <= fm.index)) {
+ fm = cache[r];
+ ft = token.type;
+ }
+ }
+ if (fm === null) {
+ break;
+ }
+ if (i !== fm.index) {
+ html += src.substring(i, fm.index);
+ }
+ i = fm.index + fm[0].length;
+ html += ''+fm[0]+'';
+ }
+ html += src.substring(i, src.length);
+ return html;
+ };
+
+ // This transforms _some_ markdown to html by replacing code blocks and
+ // urls with a placeholder, so that any markdown within these already
+ // matched blocks won't be processed again.
+
const Markdownish = (params) => {
+ const blocks = [];
const md = params.text
.replace(/&/g, '&')
.replace(//g, '>')
+
+ // Multiline code - be liberal with the closing ``` here: we just assume
+ // it will be closed eventually. This makes the code formatting and
+ // highlighting work while we still receive more tokens.
+ .replace(/```(\w*)\n([\s\S]*?)(```|$)/g, (m, lang, code) => {
+ const id = '';
+ const block = lang.length ? Syntaxhighlightish(code, lang) : code;
+ blocks.push(''+block+'
');
+ return id;
+ })
+
+ // Inline code
+ .replace(/`(.*?)`/g, (m, code) => {
+ const id = '';
+ blocks.push(''+code+'
');
+ return id;
+ })
+
+ // Urls. These are often wrapped in <> angle brackets
+ .replace(/(\b|<)((https?:\/\/(?:www\.)?|www\.)([^\s]+\([^\s]+[^!,.:\s]|[^(\s]+[^)!,.:\s]))/ig, (m, pre, url, httpwww, hostandpath) => {
+ const id = '';
+ if (httpwww === 'www.') {
+ url = 'http://' + url;
+ }
+ if (pre === '<') {
+ hostandpath = hostandpath.replace(/>$/g, '');
+ url = url.replace(/>$/g, '');
+ }
+ blocks.push(''+hostandpath+'');
+ return id;
+ })
+
+ // Headlines, emphasis and line breaks
.replace(/^#{1,6} (.*)$/gim, '$1
')
- .replace(/\*\*(.*?)\*\*/g, '$1')
- .replace(/__(.*?)__/g, '$1')
- .replace(/\*(.*?)\*/g, '$1')
- .replace(/_(.*?)_/g, '$1')
- .replace(/```.*?\n([\s\S]*?)```/g, '$1
')
- .replace(/`(.*?)`/g, '$1
')
- .replace(/\n/gim, '
');
+ .replace(/(__|\*\*)(.*?)\1/g, '$2')
+ .replace(/(_|\*)(.*?)\1/g, '$2')
+ .replace(/\n/gim, '
')
+
+ // Paste the extracted blocks back in again
+ .replace(//g, (m, index) => blocks[index]);
return html``;
};