From 0a55442dc42ecc7146f6c147f63c335f3e53502d Mon Sep 17 00:00:00 2001 From: yutent Date: Thu, 13 Apr 2023 16:08:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AC=AC=E4=B8=80=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 19 +++++ .prettierrc.yaml | 10 +++ LICENSE | 21 ++++++ Readme.md | 34 +++++++++ index.js | 176 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 24 +++++++ 6 files changed, 284 insertions(+) create mode 100644 .gitignore create mode 100644 .prettierrc.yaml create mode 100644 LICENSE create mode 100644 Readme.md create mode 100644 index.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac30e41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.min.js +.httpserver +index.html +test.js +.vscode +node_modules/ +dist/ +*.sublime-project +*.sublime-workspace +package-lock.json + + +._* + +.Spotlight-V100 +.Trashes +.DS_Store +.AppleDouble +.LSOverride \ No newline at end of file diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..b007fb1 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,10 @@ +jsxBracketSameLine: true +jsxSingleQuote: true +semi: false +singleQuote: true +printWidth: 80 +useTabs: false +tabWidth: 2 +trailingComma: none +bracketSpacing: true +arrowParens: avoid \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ab60297 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..85ff75f --- /dev/null +++ b/Readme.md @@ -0,0 +1,34 @@ +## @bytedo/editor +> 定制版的前端代码编辑器, 基于`CodeMirror 6.0`,提供`html,css,js, vue`的语法高亮和最基本的键盘快捷键。 + + +### 用法 + +```js +// 或者从CDN地址中获取 +import { EditorView, minimalSetup, vue, js, css, html } from '@bytedo/editor' + + +let view = new EditorView({ + doc: '', //默认显示的代码, + extensions: minimalSetup(vue()), // 需要高亮什么文件, 就传什么进去 + parent: document.body // 创建的编辑器实例, 被包裹在哪个节点上 +}) + + +console.log(view.state.doc.toString()) // 获取编辑器的代码 + +``` + +### 支持的键盘快捷键 + +- `Alt + Left/Right` 将光标按单词边界移动 +- `Alt + Up/Down` 将当前行代码与`上一行/下一行`互换 +- `Alt + Shift + Up/Down` 将当前行代码在`上一行/下一行`中复制一份, 并将光标移动到`上一行/下一行` +- `Alt + l` (在`macos`中是`Ctrl + l`) 选中当前行 +- `Alt + i` (在`macos`中是`Ctrl + i`) 按单词边界选中内容, 连续按则父级的块作用域选中 +- `Alt + /` (在`macos`中是`Ctrl + /`) 注释当前行 +- `Ctrl + Shift + k` (在`macos`中是`Cmd + Shift + k`) 删除当前行 +- `Ctrl + Shift + \` (在`macos`中是`Cmd + Shift + \`) 在成对的符号前后移动光标 +- `Tab` 增加缩进 +- `Shift + Tab` 减少缩进 diff --git a/index.js b/index.js new file mode 100644 index 0000000..7c1e533 --- /dev/null +++ b/index.js @@ -0,0 +1,176 @@ +import { + EditorView, + lineNumbers, + drawSelection, + keymap +} from '@codemirror/view' +import { + history, + defaultKeymap, + standardKeymap, + historyKeymap, + indentWithTab +} from '@codemirror/commands' +import { + foldGutter, + indentOnInput, + syntaxHighlighting, + HighlightStyle +} from '@codemirror/language' +import { tags as t } from '@lezer/highlight' +import { css } from '@codemirror/lang-css' +import { javascript } from '@codemirror/lang-javascript' +import { vue } from '@codemirror/lang-vue' +import { html } from '@codemirror/lang-html' + +const chalky = '#e5c07b', + blue = '#0096ff', + strings = '#53c659', + whiskey = '#d19a66', + darkBackground = '#f2f5fc', + highlightBackground = '#80CBC440', + foreground = '#546e7a', // + background = '#fff', + tooltipBackground = '#353a42', + selection = '#80CBC440', + cursor = '#35373b', + keyword = '#ff5370', + property = '#8796B0' + +const onePlain = EditorView.theme({ + '&': { + color: foreground, + backgroundColor: background + }, + + '.cm-content': { + caretColor: cursor + }, + + '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor }, + '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': + { backgroundColor: selection }, + + '.cm-panels': { backgroundColor: darkBackground, color: foreground }, + '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' }, + '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' }, + + '.cm-searchMatch': { + backgroundColor: '#72a1ff59', + outline: '1px solid #457dff' + }, + '.cm-searchMatch.cm-searchMatch-selected': { + backgroundColor: '#6199ff2f' + }, + + '.cm-activeLine': { backgroundColor: '#6699ff0b' }, + '.cm-selectionMatch': { backgroundColor: '#aafe661a' }, + + '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': { + backgroundColor: '#bad0f847' + }, + + '.cm-gutters': { + backgroundColor: darkBackground, + color: foreground, + border: 'none' + }, + + '.cm-activeLineGutter': { + backgroundColor: highlightBackground + }, + + '.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: foreground + } + } +}) + +const onePlainHighlight = HighlightStyle.define([ + { tag: t.keyword, color: keyword }, + { + tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName], + color: property, + fontWeight: 'bold' + }, + { + tag: [t.attributeName], + color: '#ffb62c' + }, + { tag: [t.function(t.variableName), t.labelName], color: blue }, + { tag: [t.color, t.constant(t.name), t.standard(t.name)], color: whiskey }, + { tag: [t.definition(t.name), t.separator], color: foreground }, + { tag: [t.typeName], color: keyword }, + { tag: [t.number, t.atom, t.bool], fontStyle: 'italic', color: '#7c4dff' }, + { + tag: [t.className, t.namespace, t.self], + fontStyle: 'italic', + fontWeight: 'bold', + color: '#ffb62c' + }, + { + tag: [t.changed, t.annotation, t.modifier], + color: chalky + }, + { + tag: [ + t.operator, + t.operatorKeyword, + t.url, + t.escape, + t.regexp, + t.link, + t.special(t.string) + ], + color: keyword + }, + { tag: [t.meta, t.comment], fontStyle: 'italic', color: '#b6d5e0' }, + { tag: t.strong, fontWeight: 'bold' }, + { tag: t.emphasis, fontStyle: 'italic' }, + { tag: t.strikethrough, textDecoration: 'line-through' }, + { tag: t.link, color: foreground, textDecoration: 'underline' }, + { tag: t.heading, fontWeight: 'bold', color: property }, + { tag: [t.special(t.variableName)], color: whiskey }, + { tag: [t.processingInstruction, t.string, t.inserted], color: strings }, + { tag: t.invalid, color: foreground } +]) + +export function minimalSetup(...args) { + return [ + lineNumbers(), + foldGutter(), + indentOnInput(), + history(), + drawSelection(), + ...args, + [onePlain, syntaxHighlighting(onePlainHighlight)], + keymap.of([ + ...standardKeymap, + ...defaultKeymap, + indentWithTab, + ...historyKeymap + ]) + ] +} + +export { EditorView, css, html, javascript, vue } diff --git a/package.json b/package.json new file mode 100644 index 0000000..7ca0313 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "@bytedo/editor", + "description": "定制版的前端代码编辑器, 基于`CodeMirror 6.0`", + "version": "1.0.0", + "type": "module", + "main": "dist/index.js", + "files": [ + "dist/*" + ], + "devDependencies": { + "@codemirror/commands": "^6.2.2", + "@codemirror/lang-css": "^6.1.1", + "@codemirror/lang-html": "^6.4.3", + "@codemirror/lang-javascript": "^6.1.5", + "@codemirror/lang-vue": "^0.1.1", + "@codemirror/language": "^6.6.0", + "@codemirror/view": "^6.9.4" + }, + "scripts": { + "start": "esbuild index.js --bundle --target=esnext --format=esm --outfile=dist/index.js --watch", + "build": "esbuild index.js --minify --bundle --target=esnext --format=esm --outfile=dist/index.js" + }, + "license": "MIT" +}