From f1ca6eeee28cb664ef370eefee71ac25ba33a9d7 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 8 Nov 2023 00:49:39 -0600 Subject: [PATCH] Near complete --- client/homebrew/editor/editor.jsx | 18 +++++++ client/homebrew/editor/editor.less | 8 +++ shared/naturalcrit/codeEditor/codeEditor.jsx | 23 +++++++++ shared/naturalcrit/markdown.js | 53 ++++++++------------ 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index b4f1fc824..df8100db3 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -160,6 +160,24 @@ const Editor = createClass({ } } + // Superscript + if(line.includes('^^') && !line.includes('^^^')) { + const regex = /.*\^\^(.+)\^\^/y; + let match; + while ((match = regex.exec(line)) != null) { + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) - 2 }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length + 2 }, { className: 'superscript' }); + } + } + + // Subscript + if(line.includes('^^^')) { + const regex = /.*\^\^\^(.+)\^\^\^/y; + let match; + while ((match = regex.exec(line)) != null) { + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) - 3 }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length + 3 }, { className: 'subscript' }); + } + } + // Highlight injectors {style} if(line.includes('{') && line.includes('}')){ const regex = /(?:^|[^{\n])({(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\2})/gm; diff --git a/client/homebrew/editor/editor.less b/client/homebrew/editor/editor.less index d31ceb97c..1f8b6e718 100644 --- a/client/homebrew/editor/editor.less +++ b/client/homebrew/editor/editor.less @@ -43,6 +43,14 @@ font-weight : bold; color : green; } + .superscript:not(.cm-comment) { + font-weight : bold; + color : goldenrod; + } + .subscript:not(.cm-comment) { + font-weight : bold; + color : rgb(123, 123, 15); + } } .brewJump { diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index e0a2220b4..b6ea07cf1 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -112,6 +112,10 @@ const CodeEditor = createClass({ 'Shift-Tab' : this.dedent, 'Ctrl-B' : this.makeBold, 'Cmd-B' : this.makeBold, + 'Ctrl-6' : this.makeSuper, + 'Cmd-6' : this.makeSuper, + 'Ctrl-7' : this.makeSub, + 'Cmd-7' : this.makeSub, 'Ctrl-I' : this.makeItalic, 'Cmd-I' : this.makeItalic, 'Ctrl-U' : this.makeUnderline, @@ -219,6 +223,25 @@ const CodeEditor = createClass({ } }, + makeSuper : function() { + const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^'; + this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around'); + if(selection.length === 0){ + const cursor = this.codeMirror.getCursor(); + this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 }); + } + }, + + makeSub : function() { + const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '^^^' && selection.slice(-3) === '^^^'; + this.codeMirror.replaceSelection(t ? selection.slice(3, -3) : `^^^${selection}^^^`, 'around'); + if(selection.length === 0){ + const cursor = this.codeMirror.getCursor(); + this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 3 }); + } + }, + + makeNbsp : function() { this.codeMirror.replaceSelection(' ', 'end'); }, diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index ae30e4922..d032a37df 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -206,47 +206,38 @@ const mustacheInjectBlock = { } }; -const superScripts = { - name : 'superScriptsInjectInline', +const superSubScripts = { + name : 'superSubScripts', level : 'inline', start(src) { return src.match(/.*\^\^(.+)\^\^/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /.*\^\^(.+)\^\^/y; - const match = inlineRegex.exec(src); - if(match) { - const tags = ` ${processStyleTags(match[1])}`; - return { - type : 'text', // Should match "name" above - raw : match[0], // Text to consume from the source - text : '', - tags - }; + const superRegex = /.*\^\^(.+)\^\^/y; + const subRegex = /.*\^\^\^(.+)\^\^\^/y; + let isSuper = false; + let match = subRegex.exec(src); + if(!match){ + match = superRegex.exec(src); + if(match) { + isSuper = true; + } + } else { + console.log(src); } - }, - renderer(token) { - return `${token.tags}`; - } -}; -const subScripts = { - name : 'subScriptsInjectInline', - level : 'inline', - start(src) { return src.match(/.*\^\^\^(.+)\^\^\^/)?.index; }, // Hint to Marked.js to stop and check for a match - tokenizer(src, tokens) { - const inlineRegex = /.*\^\^\^(.+)\^\^\^/y; - const match = inlineRegex.exec(src); - if(match) { - const tags = ` ${processStyleTags(match[1])}`; + if(match?.length) { + const tags = this.lexer.inlineTokens(match[1]); return { - type : 'text', // Should match "name" above - raw : match[0], // Text to consume from the source - text : '', + type : 'superSubScripts', // Should match "name" above + raw : match[0], // Text to consume from the source + text : src, + super : isSuper, tags }; } }, renderer(token) { - return `${token.tags}`; + const tag = token.super ? 'sup' : 'sub'; + return `<${tag}>${this.parser.parseInline(token.tags)}`; } }; @@ -282,7 +273,7 @@ const definitionLists = { } }; -Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, subScripts, superScripts] }); +Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, superSubScripts] }); Marked.use(mustacheInjectBlock); Marked.use({ renderer: renderer, mangle: false }); Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite());