diff --git a/client/components/codeEditor/codeEditor.less b/client/components/codeEditor/codeEditor.less
index 3f3869756..84ed8058d 100644
--- a/client/components/codeEditor/codeEditor.less
+++ b/client/components/codeEditor/codeEditor.less
@@ -1,31 +1,134 @@
// Icon fonts for emoji/autocomplete
-@import (less) "@themes/fonts/iconFonts/diceFont.less";
-@import (less) "@themes/fonts/iconFonts/elderberryInn.less";
-@import (less) "@themes/fonts/iconFonts/gameIcons.less";
-@import (less) "@themes/fonts/iconFonts/fontAwesome.less";
+@import (less) '@themes/fonts/iconFonts/diceFont.less';
+@import (less) '@themes/fonts/iconFonts/elderberryInn.less';
+@import (less) '@themes/fonts/iconFonts/gameIcons.less';
+@import (less) '@themes/fonts/iconFonts/fontAwesome.less';
@keyframes sourceMoveAnimation {
50% {
- color: white;
- background-color: red;
+ color : white;
+ background-color : red;
}
100% {
- color: unset;
- background-color: unset;
+ color : unset;
+ background-color : unset;
}
}
:where(.codeEditor) {
- font-family: monospace;
- height: 100%;
- width:100%;
-
- .cm-content {
- tab-size:2 !important;
+ width : 100%;
+ height : calc(100% - 25px);
+ font-family : monospace;
+
+ .cm-editor {
+ height : 100%;
+ outline : none !important;
}
- @media screen and (pointer: coarse) {
- font-size: 16px;
+ &.brewSnippets .cm-snippetLine,
+ :where(&.brewText) .cm-pageLine {
+ background : #33333328;
+ border-top : #333399 solid 1px;
+ }
+
+ &.brewSnippets {
+ .cm-pageLine {
+ color : #777777;
+ background : #3E4E3E1B;
+ border-top : #3399423B solid 1px;
+ }
+ }
+
+ &:where(.brewText), &.brewSnippets {
+
+
+ .cm-pageLine[data-page-number]::after {
+ float : right;
+ color : grey;
+ content : attr(data-page-number);
+ }
+ .cm-columnSplit {
+ font-style : italic;
+ color : grey;
+ background-color : fade(#229999, 15%);
+ border-bottom : #229999 solid 1px;
+ }
+ .cm-define {
+ &:not(.term):not(.definition) {
+ font-weight : bold;
+ color : #949494;
+ background : #E5E5E5;
+ border-radius : 3px;
+ }
+ &.term { color : rgb(96, 117, 143); }
+ &.definition { color : rgb(97, 57, 178); }
+ }
+ .cm-block:not(.cm-comment) {
+ font-weight : bold;
+ color : purple;
+ }
+ .cm-inline-block,
+ .cm-define .cm-inline-block {
+ font-weight : bold;
+ color : red;
+ span:not(.cm-comment) { color : inherit; }
+ }
+ .cm-injection:not(.cm-comment) {
+ font-weight : bold;
+ color : green;
+ span { color : inherit; }
+ }
+ .cm-emoji:not(.cm-comment) {
+ padding-bottom : 1px;
+ margin-left : 2px;
+ font-weight : bold;
+ color : #360034;
+ outline : solid 2px #FF96FC;
+ outline-offset : -2px;
+ background : #FFC8FF;
+ border-radius : 6px;
+ }
+ .cm-superscript:not(.cm-comment) {
+ font-size : 0.9em;
+ font-weight : bold;
+ vertical-align : super;
+ color : goldenrod;
+ }
+ .cm-subscript:not(.cm-comment) {
+ font-size : 0.9em;
+ font-weight : bold;
+ vertical-align : sub;
+ color : rgb(123, 123, 15);
+ }
+ .cm-definitionList {
+ .cm-definitionTerm { color : rgb(96, 117, 143); }
+ .cm-definitionColon:not(:has(.cm-comment)) {
+ font-weight : bold;
+ color : #949494;
+ background : #E5E5E5;
+ border-radius : 3px;
+ }
+ .cm-definitionDesc { color : rgb(97, 57, 178); }
+ }
+
+ .cm-tooltip-autocomplete {
+
+ li {
+ display : flex;
+ gap : 10px;
+ align-items : center;
+ justify-content : flex-start;
+
+ .cm-completionIcon { display : none; }
+ .cm-tooltip-autocomplete .cm-completionLabel { translate : 0 -2px; }
+ }
+ }
+ }
+
+ .cm-content { tab-size : 2 !important; }
+
+ @media screen and (pointer : coarse) {
+ font-size : 16px;
}
.cm-gutterElement span {
@@ -44,14 +147,14 @@
/* Flash animation for source moves */
.cm-line.sourceMoveFlash {
- animation-name: sourceMoveAnimation;
- animation-duration: 0.4s;
+ animation-name : sourceMoveAnimation;
+ animation-duration : 0.4s;
}
/* Search input */
.cm-searchField {
- width: 25em !important;
- outline: 1px inset #00000055 !important;
+ width : 25em !important;
+ outline : 1px inset #00000055 !important;
}
/* Tab character visualization (optional) */
@@ -67,6 +170,6 @@
/* Emoji preview styling */
.emojiPreview {
- font-size: 1.5em;
- line-height: 1.2em;
+ font-size : 1.5em;
+ line-height : 1.2em;
}
diff --git a/client/components/codeEditor/customHighlight.js b/client/components/codeEditor/customHighlight.js
index 3fa164757..345e253d3 100644
--- a/client/components/codeEditor/customHighlight.js
+++ b/client/components/codeEditor/customHighlight.js
@@ -125,8 +125,6 @@ export function tokenizeCustomMarkdown(text) {
from : offset,
to : offset + desc.length,
});
-
- return;
}
// --- multiline def list ---
diff --git a/client/components/codeEditor/customKeyMaps.js b/client/components/codeEditor/customKeyMaps.js
index 7a9f64d6d..7da06b119 100644
--- a/client/components/codeEditor/customKeyMaps.js
+++ b/client/components/codeEditor/customKeyMaps.js
@@ -20,72 +20,142 @@ const indentLess = (view)=>{
const makeBold = (view)=>{
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
- const text = selected.startsWith('**') && selected.endsWith('**')
- ? selected.slice(2, -2)
- : `**${selected}**`;
+
+ let text, cursor;
+
+ if(from === to) {
+ text = '****';
+ cursor = from + 2;
+ } else if(selected.startsWith('**') && selected.endsWith('**')) {
+ text = selected.slice(2, -2);
+ cursor = from + text.length;
+ } else {
+ text = `**${selected}**`;
+ cursor = from + text.length;
+ }
+
view.dispatch({
changes : { from, to, insert: text },
- selection : { anchor: from + text.length },
+ selection : { anchor: cursor },
});
+
return true;
};
const makeItalic = (view)=>{
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
- const text = selected.startsWith('*') && selected.endsWith('*')
- ? selected.slice(1, -1)
- : `*${selected}*`;
+
+ let text, cursor;
+
+ if(from === to) {
+ text = '**';
+ cursor = from + 1;
+ } else if(selected.startsWith('*') && selected.endsWith('*')) {
+ text = selected.slice(2, -2);
+ cursor = from + text.length;
+ } else {
+ text = `*${selected}*`;
+ cursor = from + text.length;
+ }
+
view.dispatch({
changes : { from, to, insert: text },
- selection : { anchor: from + text.length },
+ selection : { anchor: cursor },
});
+
return true;
};
const makeUnderline = (view)=>{
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
- const text = selected.startsWith('') && selected.endsWith('')
- ? selected.slice(3, -4)
- : `${selected}`;
+
+ let text, cursor;
+
+ if(from === to) {
+ text = '';
+ cursor = from + 3;
+ } else if(selected.startsWith('') && selected.endsWith('')) {
+ text = selected.slice(3, -4);
+ cursor = from + text.length;
+ } else {
+ text = `${selected}`;
+ cursor = from + text.length;
+ }
+
view.dispatch({
changes : { from, to, insert: text },
- selection : { anchor: from + text.length },
+ selection : { anchor: cursor },
});
+
return true;
};
-
const makeSuper = (view)=>{
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
- const text = selected.startsWith('^') && selected.endsWith('^')
- ? selected.slice(1, -1)
- : `^${selected}^`;
+
+ let text, cursor;
+
+ if(from === to) {
+ text = '^^';
+ cursor = from + 1;
+ } else if(selected.startsWith('^') && selected.endsWith('^')) {
+ text = selected.slice(1, -1);
+ cursor = from + text.length;
+ } else {
+ text = `^${selected}^`;
+ cursor = from + text.length;
+ }
+
view.dispatch({
changes : { from, to, insert: text },
- selection : { anchor: from + text.length },
+ selection : { anchor: cursor },
});
+
return true;
};
const makeSub = (view)=>{
const { from, to } = view.state.selection.main;
const selected = view.state.doc.sliceString(from, to);
- const text = selected.startsWith('^^') && selected.endsWith('^^')
- ? selected.slice(2, -2)
- : `^^${selected}^^`;
+
+ let text, cursor;
+
+ if(from === to) {
+ text = '^^^^';
+ cursor = from + 2;
+ } else if(selected.startsWith('^^') && selected.endsWith('^^')) {
+ text = selected.slice(2, -2);
+ cursor = from + text.length;
+ } else {
+ text = `^^${selected}^^`;
+ cursor = from + text.length;
+ }
+
view.dispatch({
changes : { from, to, insert: text },
- selection : { anchor: from + text.length },
+ selection : { anchor: cursor },
});
+
return true;
};
-const makeNbsp = (view)=>{
- const { from, to } = view.state.selection.main;
- view.dispatch({ changes: { from, to, insert: ' ' } });
- return true;
+const makeNbsp = (view) => {
+ const { from } = view.state.selection.main;
+
+ const prev2 = from >= 2
+ ? view.state.doc.sliceString(from - 2, from)
+ : '';
+
+ const insert = (prev2 === ':>' || prev2 === '>>') ? '>' : ':>';
+
+ view.dispatch({
+ changes: { from, to: from, insert },
+ selection: { anchor: from + insert.length },
+ });
+
+ return true;
};
const makeSpace = (view)=>{
@@ -188,13 +258,13 @@ const newPage = (view)=>{
return true;
};
-export const generalKeymap = keymap.of([
+export const generalKeymap = Prec.high(keymap.of([
{ key: 'Tab', run: indentMore },
{ key: 'Mod-z', run: undo }, //i think it may be unnecessary
{ key: 'Mod-Shift-z', run: redo },
{ key: 'Mod-y', run: redo },
- { key: 'Mod-d', run: deleteLine},
-]);
+ { key: 'Mod-d', run: deleteLine },
+]));
export const markdownKeymap = Prec.highest(keymap.of([
//{ key: 'Shift-Tab', run: indentMore },
diff --git a/client/homebrew/editor/editor.less b/client/homebrew/editor/editor.less
index 7503749fc..a55fad852 100644
--- a/client/homebrew/editor/editor.less
+++ b/client/homebrew/editor/editor.less
@@ -6,116 +6,6 @@
height : 100%;
container : editor / inline-size;
background : white;
- :where(.codeEditor) {
- height : calc(100% - 25px);
- .cm-editor { height : 100%;
- outline:none !important;
- }
- &.brewSnippets .cm-snippetLine {
- background : #33333328;
- border-top : #333399 solid 1px;
- }
-
- :where(&.brewText) .cm-pageLine {
- background : #33333328;
- border-top : #333399 solid 1px;
- }
-
- &.brewSnippets {
- .cm-pageLine {
- background : #3e4e3e1b;
- border-top : #3399423b solid 1px;
- color:#777;
- }
- }
-
- &:where(.brewText), &.brewSnippets {
-
-
- .cm-tooltip-autocomplete {
-
- li {
- display : flex;
- gap : 10px;
- align-items : center;
- justify-content : flex-start;
-
- .cm-completionIcon { display : none; }
- .cm-tooltip-autocomplete .cm-completionLabel { translate : 0 -2px; }
- }
- }
-
- .cm-pageLine[data-page-number]::after {
- content:attr(data-page-number);
- float:right;
- color : grey;
- }
- .cm-columnSplit {
- font-style : italic;
- color : grey;
- background-color : fade(#229999, 15%);
- border-bottom : #229999 solid 1px;
- }
- .cm-define {
- &:not(.term):not(.definition) {
- font-weight : bold;
- color : #949494;
- background : #E5E5E5;
- border-radius : 3px;
- }
- &.term { color : rgb(96, 117, 143); }
- &.definition { color : rgb(97, 57, 178); }
- }
- .cm-block:not(.cm-comment) {
- font-weight : bold;
- color : purple;
- }
- .cm-inline-block:not(.cm-comment) {
- font-weight : bold;
- color : red ;
- span { color : inherit }
- }
- .cm-injection:not(.cm-comment) {
- font-weight : bold;
- color : green;
- span { color : inherit }
- }
- .cm-emoji:not(.cm-comment) {
- padding-bottom : 1px;
- margin-left : 2px;
- font-weight : bold;
- color : #360034;
- outline : solid 2px #FF96FC;
- outline-offset : -2px;
- background : #FFC8FF;
- border-radius : 6px;
- }
- .cm-superscript:not(.cm-comment) {
- font-size : 0.9em;
- font-weight : bold;
- vertical-align : super;
- color : goldenrod;
- }
- .cm-subscript:not(.cm-comment) {
- font-size : 0.9em;
- font-weight : bold;
- vertical-align : sub;
- color : rgb(123, 123, 15);
- }
- .cm-definitionList {
- .cm-definitionTerm { color : rgb(96, 117, 143); }
- .cm-definitionColon {
- font-weight : bold;
- color : #949494;
- background : #E5E5E5;
- border-radius : 3px;
- }
- .cm-definitionDesc { color : rgb(97, 57, 178); }
- }
-
- }
-
- }
.brewJump {
position : absolute;
diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx
index 6beff1510..07a20fa08 100644
--- a/client/homebrew/editor/snippetbar/snippetbar.jsx
+++ b/client/homebrew/editor/snippetbar/snippetbar.jsx
@@ -29,7 +29,7 @@ import cm5Themes from 'codemirror-5-themes';
const themes = { default: defaultCM5Theme, ...cm5Themes, darkbrewery };
-const EditorThemes = Object.entries(themes)
+const themeNames = Object.entries(themes)
.filter(([name, value]) =>
Array.isArray(value) &&
!name.endsWith('Init') &&
@@ -37,6 +37,13 @@ const EditorThemes = Object.entries(themes)
)
.map(([name]) => name);
+const EditorThemes = [
+ 'default',
+ ...themeNames
+ .filter(name => name !== 'default')
+ .sort((a, b) => a.localeCompare(b))
+];
+
const execute = function(val, props){
if(_.isFunction(val)) return val(props);
return val;
diff --git a/package-lock.json b/package-lock.json
index fc582c2f9..565fe43bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,7 +33,7 @@
"@vitejs/plugin-react": "^5.1.2",
"body-parser": "^2.2.0",
"classnames": "^2.5.1",
- "codemirror-5-themes": "^1.3.0",
+ "codemirror-5-themes": "^1.4.0",
"cookie-parser": "^1.4.7",
"core-js": "^3.49.0",
"cors": "^2.8.5",
@@ -6094,9 +6094,9 @@
}
},
"node_modules/codemirror-5-themes": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/codemirror-5-themes/-/codemirror-5-themes-1.3.0.tgz",
- "integrity": "sha512-FO8HG4m4GdcphVtJFcj8wcx9nhktb4UMnSu8ia5yCNd3G89pBGqrIxw2UAEluJP4D2gLZWQOwdPaU8Ik3Bqt2w==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/codemirror-5-themes/-/codemirror-5-themes-1.4.0.tgz",
+ "integrity": "sha512-3WKAmpTLqcE1MXFLHdNtwQYaxlWZXS69MY79UiNsFpW9KedMkf/vBYBjUAmacDXPKAJjdPSNMGmCPIZi21yoXA==",
"dependencies": {
"@codemirror/view": "^6.41.1"
}
diff --git a/package.json b/package.json
index e1d15eebe..b25885497 100644
--- a/package.json
+++ b/package.json
@@ -109,7 +109,7 @@
"@vitejs/plugin-react": "^5.1.2",
"body-parser": "^2.2.0",
"classnames": "^2.5.1",
- "codemirror-5-themes": "^1.3.0",
+ "codemirror-5-themes": "^1.4.0",
"cookie-parser": "^1.4.7",
"core-js": "^3.49.0",
"cors": "^2.8.5",
diff --git a/themes/codeMirror/darkvision.css b/themes/codeMirror/darkvision.css
deleted file mode 100644
index c88455c91..000000000
--- a/themes/codeMirror/darkvision.css
+++ /dev/null
@@ -1,126 +0,0 @@
-/*This document is old, from back when Codemirror was version 5,
-if someone wants to update it, feel free, it needs to be like default.js or darkbrewery.js
-Then imported in snippetbar.jsx and codeEditor.jsx.
-*/
-
-.CodeMirror {
- background: #0C0C0C;
- color: #B9BDB6;
-}
-
-/* Brew BG */
-.brewRenderer {
- background-color: #0C0C0C;
-}
-
-.cm-s-darkvision {
- /* Blinking cursor and selection */
- .CodeMirror-cursor {
- border-left: 1px solid #B9BDB6;
- }
- .CodeMirror-selected {
- background: #E0E8FF40;
- }
-
- /* Line number stuff */
- .cm-gutter-elt {
- color: #81969A;
- }
- .CodeMirror-linenumber {
- background-color: #0C0C0C;
- }
- .cm-gutter {
- background-color: #0C0C0C;
- }
-
- /* column splits */
- .editor .codeEditor .columnSplit {
- font-style: italic;
- color: inherit;
- background-color:#1F5763;
- border-bottom: #299 solid 1px;
- }
-
- /* # headings */
- .cm-header {
- color: #C51B1B;
- -webkit-text-stroke-width: 0.1px;
- }
- /* bold points */
- .cm-strong {
- font-weight: bold;
- color: #309DD2;
- }
- /* Link headings */
- .cm-link {
- color: #DD6300;
- }
- /* links */
- .cm-string {
- color: #5CE638;
- }
- /*@import*/
- .cm-def {
- color: #2986CC;
- }
- /* Bullets and such */
- .cm-variable-2 {
- color: #3CBF30;
- }
-
- /* Tags (divs) */
- .cm-tag {
- color: #E3FF00;
- }
- .cm-attribute {
- color: #E3FF00;
- }
- .cm-atom {
- color: #CF7EA9;
- }
- .cm-qualifier {
- color: #EE1919;
- }
- .cm-comment {
- color: #BBC700;
- }
- .cm-keyword {
- color: #CC66FF;
- }
- .cm-property {
- color: aqua;
- }
- .cm-error {
- color: #C50202;
- }
- .CodeMirror-foldmarker {
- color: #F0FF00;
- }
- /* New page */
- .cm-builtin {
- color: #FFF;
- }
-}
-
-.editor .codeEditor {
- /* blocks */
- .block:not(.cm-comment) {
- color: magenta;
- }
- /* definition lists */
- .define.definition {
- color: #FFAA3E;
- }
- .define.term {
- color: #7290d9;
- }
- .define:not(.term):not(.definition) {
- background: #333;
- }
- /* New page */
- .pageLine {
- background: #000;
- color: #000;
- border-bottom: 1px solid #FFF;
- }
-}