Initial import

This commit is contained in:
Jonatan Heyman 2022-12-28 12:49:26 +01:00
commit 254ca836ef
17 changed files with 4429 additions and 0 deletions

3478
heynote-codemirror/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
{
"name": "heynote-codemirror",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"watch": "rollup -c -w",
"build_grammar": "lezer-generator src/lang-heynote/heynote.grammar -o src/lang-heynote/heynote.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@codemirror/commands": "^6.1.2",
"@codemirror/lang-html": "^6.4.0",
"@codemirror/lang-java": "^6.0.1",
"@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-lezer": "^6.0.1",
"@codemirror/lang-markdown": "^6.0.5",
"@codemirror/lang-php": "^6.0.1",
"@codemirror/lang-python": "^6.1.1",
"@codemirror/lang-sql": "^6.3.3",
"@codemirror/rangeset": "^0.19.9",
"@codemirror/search": "^6.2.3",
"@lezer/generator": "^1.1.3",
"@rollup/plugin-node-resolve": "^15.0.1",
"codemirror": "^6.0.1",
"i": "^0.3.7",
"npm": "^9.2.0",
"rollup": "^3.8.1",
"rollup-plugin-typescript2": "^0.34.1",
"typescript": "^4.9.4"
}
}

View File

@ -0,0 +1,30 @@
//import typescript from 'rollup-plugin-typescript2'
import { nodeResolve } from "@rollup/plugin-node-resolve"
//import { lezer } from "@lezer/generator/rollup"
export default {
input: "./src/editor.js",
output: {
file: "./src/editor.bundle.js",
format: "iife",
//globals: {
// //
//},
},
plugins: [
// typescript({
// check: false,
// tsconfigOverride: {
// compilerOptions: {
// lib: ['es5', 'es6'],
// sourceMap: true,
// target: 'es6',
// strict: false
// }
// }
// }),
nodeResolve(),
//lezer(),
]
}

View File

@ -0,0 +1,5 @@
import { Annotation } from "@codemirror/state"
export const heynoteEvent = Annotation.define()
export const INITIAL_DATA = "initial-data"

View File

@ -0,0 +1,85 @@
import {Annotation, EditorState, Compartment} from "@codemirror/state"
import {EditorView, keymap, drawSelection} from "@codemirror/view"
import {indentWithTab, insertTab, indentLess, indentMore} from "@codemirror/commands"
import {nord} from "./theme/nord.mjs"
import initialData from "./fixture.js"
import { customSetup } from "./setup.js"
import { heynoteLang } from "./lang-heynote/parser.js"
import { noteBlockExtension } from "./note-block.js"
import { heynoteEvent, INITIAL_DATA } from "./annotation.js"
let state = EditorState.create({
extensions: [
/*keymap.of([
{
key: "Shift-Tab",
preventDefault: true,
run: () => {
console.log("debug:", syntaxTree(editor.state).toString())
},
},
]),*/
customSetup,
//minimalSetup,
keymap.of([
{
key: 'Tab',
preventDefault: true,
//run: insertTab,
run: indentMore,
},
{
key: 'Shift-Tab',
preventDefault: true,
run: indentLess,
},
]),
nord,
heynoteLang(),
noteBlockExtension(),
// set cursor blink rate to 1 second
drawSelection({cursorBlinkRate:1000}),
],
})
let editor = new EditorView({
state,
parent: document.getElementById("editor"),
})
// set initial data
editor.update([
editor.state.update({
changes:{
from: 0,
to: editor.state.length,
insert: initialData,
},
annotations: heynoteEvent.of(INITIAL_DATA),
})
])
/*
// render syntax tree
setTimeout(() => {
function render(tree) {
let lists = ''
tree.iterate({
enter(type) {
lists += `<ul><li>${type.name} (${type.from},${type.to})`
},
leave() {
lists += '</ul>'
}
})
return lists
}
let html = render(syntaxTree(editor.state))
document.getElementById("syntaxTree").innerHTML = html;
}, 1000)
*/

View File

@ -0,0 +1,84 @@
/*export default `text
kukjavascript
ojprutt
hejpython
f = lambda: 2 +1`;*/
export default `∞∞∞python
# hmm
def my_func():
print("hejsan")
import {basicSetup} from "codemirror"
import {EditorView, keymap} from "@codemirror/view"
import {javascript} from "@codemirror/lang-javascript"
import {indentWithTab, insertTab, indentLess, indentMore} from "@codemirror/commands"
import {nord} from "./nord.mjs"javascript
let editor = new EditorView({
//extensions: [basicSetup, javascript()],
extensions: [
basicSetup,
javascript(),
//keymap.of([indentWithTab]),
keymap.of([
{
key: 'Tab',
preventDefault: true,
//run: insertTab,
run: indentMore,
},
{
key: 'Shift-Tab',
preventDefault: true,
run: indentLess,
},
]),
nord,
],
parent: document.getElementById("editor"),
})
json
{
"name": "heynote-codemirror",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@codemirror/commands": "^6.1.2",
"@codemirror/lang-javascript": "^6.1.2",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-python": "^6.1.1",
"@rollup/plugin-node-resolve": "^15.0.1",
"codemirror": "^6.0.1",
"i": "^0.3.7",
"npm": "^9.2.0",
"rollup": "^3.8.1",
"rollup-plugin-typescript2": "^0.34.1",
"typescript": "^4.9.4"
}
}
html
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Test</h1>
<script>
console.log("hej")
</script>
</body>
</html>
sql
SELECT * FROM table WHERE id = 1;
`;

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Heynote</title>
<link rel=stylesheet href="styles.css">
</head>
<body>
<div id="editor"></div>
<!--<div id="syntaxTree"></div>-->
<script src="editor.bundle.js"></script>
</body>
</html>

View File

@ -0,0 +1,31 @@
import { ExternalTokenizer } from '@lezer/lr'
import { NoteContent } from "./heynote.terms.js"
const EOF = -1;
export const noteContent = new ExternalTokenizer((input) => {
let current = input.peek(0);
let next = input.peek(1);
if (current === EOF) {
return;
}
while (true) {
let potentialLang = "";
for (let i=0; i<15; i++) {
potentialLang += String.fromCharCode(input.peek(i));
}
if (potentialLang.match(/^∞∞∞(text|javascript|json|python|html|sql|markdown|java|lezer|php)\n/g)) {
input.acceptToken(NoteContent);
return;
}
if (next === EOF) {
input.acceptToken(NoteContent, 1);
return;
}
current = input.advance();
next = input.peek(1);
}
});

View File

@ -0,0 +1,21 @@
@top Document { Note* }
Note {
NoteDelimiter NoteContent
}
NoteDelimiter {
noteDelimiterMark NoteLanguage noteDelimiterEnter
}
@tokens {
noteDelimiterMark { "∞∞∞" }
NoteLanguage { "text" | "javascript" | "json" | "python" | "html" | "sql" | "markdown" | "java" | "lezer" | "php" }
noteDelimiterEnter { "\n" }
//NoteContent { String }
//String { (![∞])+ }
}
@external tokens noteContent from "./external-tokens.js" { NoteContent }

View File

@ -0,0 +1,17 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr"
import {noteContent} from "./external-tokens.js"
export const parser = LRParser.deserialize({
version: 14,
states: "!WQQOPOOOVOPO'#C`O[OQO'#C_OOOO'#Cb'#CbQQOPOOOaOPO,58zOOOO,58y,58yOOOO-E6`-E6`OOOQ1G.f1G.f",
stateData: "f~OWPO~OTTO~OPUO~OXWO~O",
goto: "fVPPPW[P`TROSTQOSQSORVS",
nodeNames: "⚠ NoteContent Document Note NoteDelimiter NoteLanguage",
maxTerm: 9,
skippedNodes: [0],
repeatNodeCount: 1,
tokenData: "&e~RXYZn#[#]s#^#_![#`#a#u#a#b$_#d#e%T#g#h%p#h#i%v%&x%&y&S~sOX~~vP#h#iy~|P#a#b!P~!SP#`#a!V~![OT~~!_Q#T#U!e#g#h#i~!hP#j#k!k~!nP#T#U!q~!vPT~#g#h!y~!|P#V#W#P~#SP#f#g#V~#YP#]#^#]~#`P#d#e#c~#fP#h#i!V~#lP#c#d#o~#rP#b#c!V~#xP#X#Y#{~$OP#n#o$R~$UP#X#Y$X~$[P#f#g!V~$bP#T#U$e~$hP#f#g$k~$nP#_#`$q~$tP#W#X$w~$zP#c#d$}~%QP#k#l#o~%WQ#[#]%^#m#n%d~%aP#d#e!V~%gP#h#i%j~%mP#[#]#i~%sP#e#f!P~%yP#X#Y%|~&PP#l#m#c~&VP%&x%&y&Y~&]P%&x%&y&`~&eOW~",
tokenizers: [0, noteContent],
topRules: {"Document":[0,2]},
tokenPrec: 0
})

View File

@ -0,0 +1,7 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
export const
NoteContent = 1,
Document = 2,
Note = 3,
NoteDelimiter = 4,
NoteLanguage = 5

View File

@ -0,0 +1,45 @@
import { parseMixed } from "@lezer/common"
import { jsonLanguage } from "@codemirror/lang-json"
import { pythonLanguage } from "@codemirror/lang-python"
import { javascriptLanguage } from "@codemirror/lang-javascript"
import { htmlLanguage } from "@codemirror/lang-html"
import { StandardSQL } from "@codemirror/lang-sql"
import { markdownLanguage } from "@codemirror/lang-markdown"
import { javaLanguage } from "@codemirror/lang-java"
import { lezerLanguage } from "@codemirror/lang-lezer"
import { phpLanguage } from "@codemirror/lang-php"
import { NoteContent, NoteLanguage } from "./heynote.terms.js"
const languageMapping = {
"json": jsonLanguage.parser,
"javascript": javascriptLanguage.parser,
"python": pythonLanguage.parser,
"html": htmlLanguage.parser,
"sql": StandardSQL.language.parser,
"markdown": markdownLanguage.parser,
"java": javaLanguage.parser,
"lezer": lezerLanguage.parser,
"php": phpLanguage.parser,
}
export function configureNesting() {
return parseMixed((node, input) => {
let id = node.type.id
if (id == NoteContent) {
let noteLang = node.node.parent.firstChild.getChildren(NoteLanguage)[0]
let langName = input.read(noteLang?.from, noteLang?.to)
//console.log("langName:", langName)
if (langName in languageMapping) {
//console.log("found parser for language:", langName)
return {
parser:languageMapping[langName],
}
}
}
return null
})
}

View File

@ -0,0 +1,44 @@
import { parser } from "./heynote.js"
import { configureNesting } from "./nested-parser.js";
import {LRLanguage, LanguageSupport, indentNodeProp, foldNodeProp, foldInside, delimitedIndent} from "@codemirror/language"
import {styleTags, tags as t} from "@lezer/highlight"
import { json } from "@codemirror/lang-json"
import { javascript } from "@codemirror/lang-javascript"
function foldNode(node) {
//console.log("foldNode", node);
return {from:node.from, to:node.to-1};
//let first = node.firstChild, last = node.lastChild;
//return first && first.to < last.from ? { from: first.to, to: last.type.isError ? node.to : last.from } : null;
}
export const HeynoteLanguage = LRLanguage.define({
parser: parser.configure({
props: [
styleTags({
NoteDelimiter: t.tagName,
}),
foldNodeProp.add({
NoteContent: foldNode,
}),
],
wrap: configureNesting(),
}),
languageData: {
commentTokens: {line: ";"}
}
})
export function heynoteLang() {
let wrap = configureNesting();
let lang = HeynoteLanguage.configure({dialect:"", wrap:wrap});
return new LanguageSupport(lang, [json().support])
}
/*export function heynote() {
return new LanguageSupport(HeynoteLanguage)
}*/

View File

@ -0,0 +1,178 @@
import { ViewPlugin, EditorView, Decoration, WidgetType } from "@codemirror/view"
import { layer, RectangleMarker } from "@codemirror/view"
import { EditorState, RangeSetBuilder, StateField } from "@codemirror/state";
import { RangeSet } from "@codemirror/rangeset";
import { syntaxTree } from "@codemirror/language"
import { Note, Document, NoteDelimiter } from "./lang-heynote/heynote.terms.js"
import { IterMode } from "@lezer/common";
import { INITIAL_DATA } from "./annotation.js";
class NoteBlockStart extends WidgetType {
constructor() {
super()
}
eq(other) {
//return other.checked == this.checked
return true
}
toDOM() {
let wrap = document.createElement("div")
wrap.className = "block-start"
//wrap.innerHTML = "<br>"
return wrap
}
ignoreEvent() {
return false
}
}
class FirstNoteBlockStart extends WidgetType {
constructor() {
super()
}
eq(other) {
return true
}
toDOM() {
let wrap = document.createElement("span")
wrap.className = "block-start-first"
return wrap
}
ignoreEvent() {
return false
}
}
const noteBlockWidget = () => {
const decorate = (state) => {
const widgets = [];
syntaxTree(state).iterate({
enter: (type) => {
if (type.name === "NoteDelimiter") {
//console.log("found!", type.name, type.from, type.to)
let deco = Decoration.replace({
widget: type.from === 0 ? new FirstNoteBlockStart() : new NoteBlockStart(),
inclusive: false,
block: type.from === 0 ? false : true,
side: 0,
});
widgets.push(deco.range(type.from, type.from === 0 ? type.to :type.to-1));
}
},
mode: IterMode.IgnoreMounts,
});
return widgets.length > 0 ? RangeSet.of(widgets) : Decoration.none;
};
const noteBlockStartField = StateField.define({
create(state) {
return decorate(state);
},
update(widgets, transaction) {
if (transaction.docChanged) {
return decorate(transaction.state);
}
//return widgets.map(transaction.changes);
return widgets
},
provide(field) {
return EditorView.decorations.from(field);
}
});
return [noteBlockStartField];
};
function atomicRanges(view) {
let builder = new RangeSetBuilder()
syntaxTree(view.state).iterate({
enter: (type) => {
if (type.type.id === NoteDelimiter) {
builder.add(type.from, type.to, {})
}
},
mode: IterMode.IgnoreMounts,
});
return builder.finish()
}
const atomicNoteBlock = ViewPlugin.fromClass(
class {
constructor(view) {
this.atomicRanges = atomicRanges(view)
}
update(update) {
if (update.docChanged) {
this.atomicRanges = atomicRanges(update.view)
}
}
},
{
provide: plugin => EditorView.atomicRanges.of(view => {
return view.plugin(plugin)?.atomicRanges || Decoration.none
})
}
)
const blockLayer = () => {
return layer({
above: false,
markers(view) {
const markers = []
let idx = 0
syntaxTree(view.state).iterate({
enter: (type) => {
//console.log("type", type.name, type.type.id, Document)
if (type.type.id == Document || type.type.id == Note) {
return true
} else if (type.type.id === NoteDelimiter) {
const contentNode = type.node.nextSibling
//console.log("adding marker", type.node.nextSibling.name)
//let line = view.state.doc.lineAt(type.from)
const fromCoords = view.coordsAtPos(contentNode.from)
const toCoords = view.coordsAtPos(contentNode.to)
//console.log("line", fromCoords.top, toCoords.bottom)
//console.log("documentTop", view.documentTop)
markers.push(new RectangleMarker(
idx++ % 2 == 0 ? "block-even" : "block-odd",
0,
fromCoords.top - (view.documentTop - view.documentPadding.top),
2000,
(toCoords.bottom - fromCoords.top),
))
return false;
}
return false;
},
mode: IterMode.IgnoreMounts,
});
return markers
},
update(update, dom) {
return update.docChanged || update.viewportChanged
},
class: "blocks-layer"
})
}
const preventFirstBlockFromBeingDeleted = EditorState.changeFilter.of((tr) => {
if (!tr.annotations.some(a => a.value === INITIAL_DATA)) {
return [-1,10]
}
})
export const noteBlockExtension = () => {
return [noteBlockWidget(), atomicNoteBlock, blockLayer(), preventFirstBlockFromBeingDeleted]
}

View File

@ -0,0 +1,96 @@
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap } from '@codemirror/view';
export { EditorView } from '@codemirror/view';
import { EditorState } from '@codemirror/state';
import { foldGutter, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, foldKeymap } from '@codemirror/language';
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
import { lintKeymap } from '@codemirror/lint';
// (The superfluous function calls around the list of extensions work
// around current limitations in tree-shaking software.)
/**
This is an extension value that just pulls together a number of
extensions that you might want in a basic editor. It is meant as a
convenient helper to quickly set up CodeMirror without installing
and importing a lot of separate packages.
Specifically, it includes...
- [the default command bindings](https://codemirror.net/6/docs/ref/#commands.defaultKeymap)
- [line numbers](https://codemirror.net/6/docs/ref/#view.lineNumbers)
- [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars)
- [the undo history](https://codemirror.net/6/docs/ref/#commands.history)
- [a fold gutter](https://codemirror.net/6/docs/ref/#language.foldGutter)
- [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection)
- [drop cursor](https://codemirror.net/6/docs/ref/#view.dropCursor)
- [multiple selections](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections)
- [reindentation on input](https://codemirror.net/6/docs/ref/#language.indentOnInput)
- [the default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle) (as fallback)
- [bracket matching](https://codemirror.net/6/docs/ref/#language.bracketMatching)
- [bracket closing](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets)
- [autocompletion](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion)
- [rectangular selection](https://codemirror.net/6/docs/ref/#view.rectangularSelection) and [crosshair cursor](https://codemirror.net/6/docs/ref/#view.crosshairCursor)
- [active line highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLine)
- [active line gutter highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLineGutter)
- [selection match highlighting](https://codemirror.net/6/docs/ref/#search.highlightSelectionMatches)
- [search](https://codemirror.net/6/docs/ref/#search.searchKeymap)
- [linting](https://codemirror.net/6/docs/ref/#lint.lintKeymap)
(You'll probably want to add some language package to your setup
too.)
This extension does not allow customization. The idea is that,
once you decide you want to configure your editor more precisely,
you take this package's source (which is just a bunch of imports
and an array literal), copy it into your own code, and adjust it
as desired.
*/
const customSetup = /*@__PURE__*/(() => [
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
dropCursor(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
bracketMatching(),
//closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
...lintKeymap
])
])();
/**
A minimal set of extensions to create a functional editor. Only
includes [the default keymap](https://codemirror.net/6/docs/ref/#commands.defaultKeymap), [undo
history](https://codemirror.net/6/docs/ref/#commands.history), [special character
highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars), [custom selection
drawing](https://codemirror.net/6/docs/ref/#view.drawSelection), and [default highlight
style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle).
*/
const minimalSetup = /*@__PURE__*/(() => [
highlightSpecialChars(),
history(),
drawSelection(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
keymap.of([
...defaultKeymap,
...historyKeymap,
])
])();
export { customSetup, minimalSetup };

View File

@ -0,0 +1,41 @@
html,
body {
margin: 0;
padding: 0;
background: #fff;
color: #444;
font-family: 'Gill Sans','Gill Sans MT',Calibri,'Trebuchet MS',sans-serif;
height: 100%;
}
#editor {
height: 100%;
}
#editor .cm-editor {
height: 100%;
}
#syntaxTree {
height: 20%;
overflow-y: auto;
}
.kuken {
background: #f00;
}
.balle .test-marker {
background: rgb(94, 84, 106);
}
.blocks-layer .block-even {
background: #3f3b4b;
}
.blocks-layer .block-odd {
background: rgb(57, 71, 77);
}
.block-start {
/*background: rgb(0, 0, 0);
height: 2px*/
}

View File

@ -0,0 +1,214 @@
import { EditorView } from '@codemirror/view';
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { tags } from '@lezer/highlight';
// Colors from https://www.nordtheme.com/docs/colors-and-palettes
// Polar Night
const base00 = '#2e3440', // black
base01 = '#3b4252', // dark grey
base02 = '#434c5e', base03 = '#4c566a'; // grey
// Snow Storm
const base04 = '#d8dee9', // grey
base05 = '#e5e9f0', // off white
base06 = '#eceff4'; // white
// Frost
const base07 = '#8fbcbb', // moss green
base08 = '#88c0d0', // ice blue
base09 = '#81a1c1', // water blue
base0A = '#5e81ac'; // deep blue
// Aurora
const base0b = '#bf616a', // red
base0C = '#d08770', // orange
base0D = '#ebcb8b', // yellow
base0E = '#a3be8c', // green
base0F = '#b48ead'; // purple
const invalid = '#d30102', darkBackground = '#252a33', background = base00, tooltipBackground = base01, selection = base03, cursor = '#fff';
const highlightBackground = 'rgba(255,255,255,0.04)';
const lineNumberColor = '#535963';
const commentColor = '#888d97';
const matchingBracket = 'rgba(255,255,255,0.1)';
/**
The editor theme styles for Nord.
*/
const nordTheme = /*@__PURE__*/EditorView.theme({
'&': {
color: base04,
backgroundColor: background
},
'.cm-content': {
caretColor: cursor
},
'.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor, borderLeftWidth:'2px', height:'19px !important', marginTop:'-2px !important' },
'&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': { backgroundColor: selection },
'.cm-panels': { backgroundColor: darkBackground, color: base03 },
'.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
'.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
'.cm-searchMatch': {
backgroundColor: 'transparent',
outline: `1px solid ${base07}`
},
'.cm-searchMatch.cm-searchMatch-selected': {
backgroundColor: base04,
color: base00
},
'.cm-activeLine': { backgroundColor: highlightBackground },
'.cm-selectionMatch': {
backgroundColor: base05,
color: base01
},
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
outline: `0.5px solid ${base07}`
},
'&.cm-focused .cm-matchingBracket': {
backgroundColor: matchingBracket,
color: base02
},
'&.cm-focused .cm-nonmatchingBracket': {
outline: `0.5px solid #bc8f8f`
},
'.cm-gutters': {
backgroundColor: base00,
color: lineNumberColor,
border: 'none'
},
'.cm-activeLineGutter': {
backgroundColor: highlightBackground,
color: base04
},
'.cm-foldPlaceholder': {
backgroundColor: 'transparent',
border: 'none',
color: '#ddd'
},
'.cm-tooltip': {
border: 'none',
backgroundColor: tooltipBackground
},
'.cm-tooltip .cm-tooltip-arrow:before': {
borderTopColor: 'transparent',
borderBottomColor: 'transparent'
},
'.cm-tooltip .cm-tooltip-arrow:after': {
borderTopColor: tooltipBackground,
borderBottomColor: tooltipBackground
},
'.cm-tooltip-autocomplete': {
'& > ul > li[aria-selected]': {
backgroundColor: highlightBackground,
color: base03
}
}
}, { dark: true });
/**
The highlighting style for code in the Nord theme.
*/
const nordHighlightStyle = /*@__PURE__*/HighlightStyle.define([
{ tag: tags.keyword, color: base0A },
{
tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName],
color: base08
},
{ tag: [tags.variableName], color: base07 },
{ tag: [/*@__PURE__*/tags.function(tags.variableName)], color: base07 },
{ tag: [tags.labelName], color: base09 },
{
tag: [tags.color, /*@__PURE__*/tags.constant(tags.name), /*@__PURE__*/tags.standard(tags.name)],
color: base0A
},
{ tag: [/*@__PURE__*/tags.definition(tags.name), tags.separator], color: base0E },
{ tag: [tags.brace], color: base07 },
{
tag: [tags.annotation],
color: invalid
},
{
tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace],
color: base0F
},
{
tag: [tags.typeName, tags.className],
color: base0D
},
{
tag: [tags.operator, tags.operatorKeyword],
color: base0E
},
{
tag: [tags.tagName],
color: base0F
},
{
tag: [tags.squareBracket],
color: base0b
},
{
tag: [tags.angleBracket],
color: base0C
},
{
tag: [tags.attributeName],
color: base0D
},
{
tag: [tags.regexp],
color: base0A
},
{
tag: [tags.quote],
color: base0F
},
{ tag: [tags.string], color: base0E },
{
tag: tags.link,
color: base0E,
textDecoration: 'underline',
textUnderlinePosition: 'under'
},
{
tag: [tags.url, tags.escape, /*@__PURE__*/tags.special(tags.string)],
color: base07
},
{ tag: [tags.meta], color: base08 },
{ tag: [tags.monospace], color: base04, fontStyle: 'italic' },
{ tag: [tags.comment], color: commentColor, fontStyle: 'italic' },
{ tag: tags.strong, fontWeight: 'bold', color: base0A },
{ tag: tags.emphasis, fontStyle: 'italic', color: base0A },
{ tag: tags.strikethrough, textDecoration: 'line-through' },
{ tag: tags.heading, fontWeight: 'bold', color: base0A },
{ tag: /*@__PURE__*/tags.special(tags.heading1), fontWeight: 'bold', color: base0A },
{ tag: tags.heading1, fontWeight: 'bold', color: base0A },
{
tag: [tags.heading2, tags.heading3, tags.heading4],
fontWeight: 'bold',
color: base0A
},
{
tag: [tags.heading5, tags.heading6],
color: base0A
},
{ tag: [tags.atom, tags.bool, /*@__PURE__*/tags.special(tags.variableName)], color: base0C },
{
tag: [tags.processingInstruction, tags.inserted],
color: base07
},
{
tag: [tags.contentSeparator],
color: base0D
},
{ tag: tags.invalid, color: base02, borderBottom: `1px dotted ${invalid}` }
]);
/**
Extension to enable the Nord theme (both the editor theme and
the highlight style).
*/
const nord = [
nordTheme,
/*@__PURE__*/syntaxHighlighting(nordHighlightStyle)
];
export { nord, nordHighlightStyle, nordTheme };