From 4de2c496c938565fdf87f2cf9a95ce3fab57893a Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Fri, 24 Feb 2023 14:51:56 -0800 Subject: [PATCH] Vendor basicSetup --- package-lock.json | 88 ++++++++++++++-------------- package.json | 2 + src-web/components/Editor/Editor.css | 42 +++++++++++++ src-web/hooks/useCodemirror.ts | 75 ++++++++++++++++++++++-- 4 files changed, 159 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3117913f..a0d895b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,11 @@ "name": "tauri-app", "version": "0.0.0", "dependencies": { + "@codemirror/commands": "^6.2.1", "@codemirror/lang-html": "^6.4.2", "@codemirror/lang-javascript": "^6.1.4", "@codemirror/lang-json": "^6.0.1", + "@codemirror/search": "^6.2.3", "@radix-ui/react-dropdown-menu": "^2.0.2", "@radix-ui/react-icons": "^1.2.0", "@radix-ui/react-popover": "1.0.3", @@ -429,6 +431,17 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@codemirror/commands": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.1.tgz", + "integrity": "sha512-FFiNKGuHA5O8uC6IJE5apI5rT9gyjlw4whqy4vlcX0wE/myxL6P1s0upwDhY4HtMWLOwzwsp0ap3bjdQhvfDOA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, "node_modules/@codemirror/lang-css": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.0.2.tgz", @@ -502,6 +515,16 @@ "crelt": "^1.0.5" } }, + "node_modules/@codemirror/search": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.2.3.tgz", + "integrity": "sha512-V9n9233lopQhB1dyjsBK2Wc1i+8hcCqxl1wQ46c5HWWLePoe4FluV3TGHoZ04rBRlGjNyz9DTmpJErig8UE4jw==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, "node_modules/@codemirror/state": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", @@ -2752,27 +2775,6 @@ "@codemirror/view": "^6.0.0" } }, - "node_modules/codemirror/node_modules/@codemirror/commands": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.1.tgz", - "integrity": "sha512-FFiNKGuHA5O8uC6IJE5apI5rT9gyjlw4whqy4vlcX0wE/myxL6P1s0upwDhY4HtMWLOwzwsp0ap3bjdQhvfDOA==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.2.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/codemirror/node_modules/@codemirror/search": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.2.3.tgz", - "integrity": "sha512-V9n9233lopQhB1dyjsBK2Wc1i+8hcCqxl1wQ46c5HWWLePoe4FluV3TGHoZ04rBRlGjNyz9DTmpJErig8UE4jw==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -6615,6 +6617,17 @@ "@lezer/common": "^1.0.0" } }, + "@codemirror/commands": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.1.tgz", + "integrity": "sha512-FFiNKGuHA5O8uC6IJE5apI5rT9gyjlw4whqy4vlcX0wE/myxL6P1s0upwDhY4HtMWLOwzwsp0ap3bjdQhvfDOA==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, "@codemirror/lang-css": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.0.2.tgz", @@ -6688,6 +6701,16 @@ "crelt": "^1.0.5" } }, + "@codemirror/search": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.2.3.tgz", + "integrity": "sha512-V9n9233lopQhB1dyjsBK2Wc1i+8hcCqxl1wQ46c5HWWLePoe4FluV3TGHoZ04rBRlGjNyz9DTmpJErig8UE4jw==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, "@codemirror/state": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", @@ -8164,29 +8187,6 @@ "@codemirror/search": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" - }, - "dependencies": { - "@codemirror/commands": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.1.tgz", - "integrity": "sha512-FFiNKGuHA5O8uC6IJE5apI5rT9gyjlw4whqy4vlcX0wE/myxL6P1s0upwDhY4HtMWLOwzwsp0ap3bjdQhvfDOA==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.2.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" - } - }, - "@codemirror/search": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.2.3.tgz", - "integrity": "sha512-V9n9233lopQhB1dyjsBK2Wc1i+8hcCqxl1wQ46c5HWWLePoe4FluV3TGHoZ04rBRlGjNyz9DTmpJErig8UE4jw==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - } } }, "color-convert": { diff --git a/package.json b/package.json index bf7576da..0d767a7f 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,11 @@ "tauri-build": "tauri build" }, "dependencies": { + "@codemirror/commands": "^6.2.1", "@codemirror/lang-html": "^6.4.2", "@codemirror/lang-javascript": "^6.1.4", "@codemirror/lang-json": "^6.0.1", + "@codemirror/search": "^6.2.3", "@radix-ui/react-dropdown-menu": "^2.0.2", "@radix-ui/react-icons": "^1.2.0", "@radix-ui/react-popover": "1.0.3", diff --git a/src-web/components/Editor/Editor.css b/src-web/components/Editor/Editor.css index 47802398..ae88271f 100644 --- a/src-web/components/Editor/Editor.css +++ b/src-web/components/Editor/Editor.css @@ -36,9 +36,51 @@ .cm-editor .cm-gutters { background-color: hsl(var(--color-gray-50)); border-right: 0; + color: hsl(var(--color-gray-200)); +} + +.cm-editor .fold-gutter-icon { + height: 1.5em; + padding-top: 0.2em; + padding-left: 0.4em; + padding-right: 0.4em; + cursor: pointer; + border-radius: 0.2em; +} + +.cm-editor .fold-gutter-icon::after { + display: block; + width: 0.5em; + height: 0.5em; + border: 1px solid transparent; + border-left-color: currentColor; + border-bottom-color: currentColor; + transform: rotate(-45deg); + content: ""; +} + +.cm-editor .fold-gutter-icon[data-open] { + padding-top: 0.4em; + padding-left: 0.2em; +} + +.cm-editor .fold-gutter-icon[data-open]::after { + transform: rotate(-135deg); +} + +.cm-editor .fold-gutter-icon:hover { + background-color: hsl(var(--color-gray-100)/0.2); + color: hsl(var(--color-gray-400)); +} + +.cm-editor.cm-focused .cm-gutters { color: hsl(var(--color-gray-300)); } +.cm-editor .cm-content { + padding-top: 0.4rem; +} + .cm-editor .cm-foldPlaceholder { background-color: hsl(var(--color-gray-100)); border: 1px solid hsl(var(--color-gray-200)); diff --git a/src-web/hooks/useCodemirror.ts b/src-web/hooks/useCodemirror.ts index 9b45edcc..5c93c35a 100644 --- a/src-web/hooks/useCodemirror.ts +++ b/src-web/hooks/useCodemirror.ts @@ -1,11 +1,40 @@ import { useEffect, useRef, useState } from 'react'; -import { EditorView, basicSetup } from 'codemirror'; +import { EditorView } from 'codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { json } from '@codemirror/lang-json'; import { html } from '@codemirror/lang-html'; -import { EditorState } from '@codemirror/state'; import { tags } from '@lezer/highlight'; -import { HighlightStyle, LanguageSupport, syntaxHighlighting } from '@codemirror/language'; +import { + bracketMatching, + defaultHighlightStyle, + foldGutter, + foldKeymap, + HighlightStyle, + indentOnInput, + LanguageSupport, + syntaxHighlighting, +} from '@codemirror/language'; +import { + crosshairCursor, + drawSelection, + dropCursor, + highlightActiveLine, + highlightActiveLineGutter, + highlightSpecialChars, + keymap, + lineNumbers, + rectangularSelection, +} from '@codemirror/view'; +import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'; +import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; +import { + autocompletion, + closeBrackets, + closeBracketsKeymap, + completionKeymap, +} from '@codemirror/autocomplete'; +import { lintKeymap } from '@codemirror/lint'; +import { EditorState } from '@codemirror/state'; const myHighlightStyle = HighlightStyle.define([ { @@ -26,7 +55,45 @@ const syntaxExtensions: Record = { 'text/html': html(), }; -const extensions = [basicSetup, syntaxHighlighting(myHighlightStyle)]; +const extensions = [ + lineNumbers(), + highlightActiveLineGutter(), + highlightSpecialChars(), + history(), + foldGutter({ + markerDOM: (open) => { + const el = document.createElement('div'); + el.classList.add('fold-gutter-icon'); + el.tabIndex = -1; + if (open) { + el.setAttribute('data-open', ''); + } + return el; + }, + }), + 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, + ]), + syntaxHighlighting(myHighlightStyle), +]; export default function useCodeMirror({ value,