@milkdown/crepe 7.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/lib/apl-p0IPP13W.js +76 -0
- package/lib/asciiarmor-lJsBxlJJ.js +34 -0
- package/lib/asn1-Q9v1zIy5.js +102 -0
- package/lib/asterisk-foNkeTjy.js +273 -0
- package/lib/brainfuck-0XqyXpNS.js +35 -0
- package/lib/clike-ak6Z6Yhe.js +639 -0
- package/lib/clojure-iYO8U8Sg.js +810 -0
- package/lib/clsx-7d8NmkQq.js +21 -0
- package/lib/cmake-SVzjkxV_.js +28 -0
- package/lib/cobol-APHEnAOX.js +74 -0
- package/lib/coffeescript-KqQa0SYG.js +182 -0
- package/lib/commonlisp-bwqNqR5V.js +79 -0
- package/lib/core/crepe.d.ts +21 -0
- package/lib/core/crepe.d.ts.map +1 -0
- package/lib/core/index.d.ts +3 -0
- package/lib/core/index.d.ts.map +1 -0
- package/lib/core/slice.d.ts +12 -0
- package/lib/core/slice.d.ts.map +1 -0
- package/lib/crystal-BViWuDpA.js +217 -0
- package/lib/css-KHXHXfXg.js +1572 -0
- package/lib/cypher-XpTt4zQ3.js +69 -0
- package/lib/d-fLig6yqY.js +139 -0
- package/lib/diff-WoKGLpy6.js +18 -0
- package/lib/dockerfile-u6f6Vw2s.js +194 -0
- package/lib/dtd-SIJRUW6K.js +91 -0
- package/lib/dylan-4HCLhpWP.js +238 -0
- package/lib/ebnf-h_0lged5.js +77 -0
- package/lib/ecl-Lf4FF0lf.js +133 -0
- package/lib/eiffel-qlw8KUyf.js +112 -0
- package/lib/elm-QRnB3zXs.js +108 -0
- package/lib/erlang-fyVKb7eK.js +488 -0
- package/lib/factor-BEeN4upY.js +65 -0
- package/lib/fcl-lRek3hEb.js +106 -0
- package/lib/feature/block-edit/handle/component.d.ts +9 -0
- package/lib/feature/block-edit/handle/component.d.ts.map +1 -0
- package/lib/feature/block-edit/handle/index.d.ts +12 -0
- package/lib/feature/block-edit/handle/index.d.ts.map +1 -0
- package/lib/feature/block-edit/index.d.ts +3 -0
- package/lib/feature/block-edit/index.d.ts.map +1 -0
- package/lib/feature/block-edit/menu/component.d.ts +14 -0
- package/lib/feature/block-edit/menu/component.d.ts.map +1 -0
- package/lib/feature/block-edit/menu/config.d.ts +21 -0
- package/lib/feature/block-edit/menu/config.d.ts.map +1 -0
- package/lib/feature/block-edit/menu/icons.d.ts +14 -0
- package/lib/feature/block-edit/menu/icons.d.ts.map +1 -0
- package/lib/feature/block-edit/menu/index.d.ts +9 -0
- package/lib/feature/block-edit/menu/index.d.ts.map +1 -0
- package/lib/feature/code-mirror/index.d.ts +3 -0
- package/lib/feature/code-mirror/index.d.ts.map +1 -0
- package/lib/feature/gap-cursor/index.d.ts +3 -0
- package/lib/feature/gap-cursor/index.d.ts.map +1 -0
- package/lib/feature/image-block/index.d.ts +3 -0
- package/lib/feature/image-block/index.d.ts.map +1 -0
- package/lib/feature/index.d.ts +18 -0
- package/lib/feature/index.d.ts.map +1 -0
- package/lib/feature/link-tooltip/consts.d.ts +5 -0
- package/lib/feature/link-tooltip/consts.d.ts.map +1 -0
- package/lib/feature/link-tooltip/index.d.ts +3 -0
- package/lib/feature/link-tooltip/index.d.ts.map +1 -0
- package/lib/feature/list-item/consts.d.ts +2 -0
- package/lib/feature/list-item/consts.d.ts.map +1 -0
- package/lib/feature/list-item/index.d.ts +3 -0
- package/lib/feature/list-item/index.d.ts.map +1 -0
- package/lib/feature/placeholder/index.d.ts +10 -0
- package/lib/feature/placeholder/index.d.ts.map +1 -0
- package/lib/feature/shared.d.ts +3 -0
- package/lib/feature/shared.d.ts.map +1 -0
- package/lib/feature/toolbar/component.d.ts +13 -0
- package/lib/feature/toolbar/component.d.ts.map +1 -0
- package/lib/feature/toolbar/consts.d.ts +5 -0
- package/lib/feature/toolbar/consts.d.ts.map +1 -0
- package/lib/feature/toolbar/index.d.ts +3 -0
- package/lib/feature/toolbar/index.d.ts.map +1 -0
- package/lib/forth-ua2bRd8T.js +60 -0
- package/lib/fortran-WnF7znuN.js +443 -0
- package/lib/gas-wowve1o7.js +183 -0
- package/lib/gherkin-m7GIChu3.js +34 -0
- package/lib/go-th443Dhb.js +158 -0
- package/lib/groovy-tR4RiZnc.js +161 -0
- package/lib/haskell-jxVBofv5.js +375 -0
- package/lib/haxe-kWPI2tq3.js +390 -0
- package/lib/hooks-82sqkbtE.js +21 -0
- package/lib/http-3GIFWUlG.js +45 -0
- package/lib/icons-HYkfuR-O.js +50 -0
- package/lib/idl-PvpMZg-l.js +947 -0
- package/lib/index-0RbcZMbq.js +8 -0
- package/lib/index-4afXjFMY.js +517 -0
- package/lib/index-7MeyepDG.js +78 -0
- package/lib/index-7QgQq3x3.js +551 -0
- package/lib/index-7pgP6qYs.js +107 -0
- package/lib/index-8DvtgRVa.js +19511 -0
- package/lib/index-8Gg-jEP4.js +288 -0
- package/lib/index-8S8qcncB.js +507 -0
- package/lib/index-9A_GmGh4.js +1039 -0
- package/lib/index-EJJfYLzA.js +928 -0
- package/lib/index-Eg39w5kL.js +984 -0
- package/lib/index-FIk_7oPb.js +168 -0
- package/lib/index-LlbrXb_n.js +368 -0
- package/lib/index-MovKtgMG.js +121 -0
- package/lib/index-N9GtIS4X.js +64 -0
- package/lib/index-Pwn25-kf.js +8 -0
- package/lib/index-SdFSDosa.js +1295 -0
- package/lib/index-W5Th22-Z.js +1744 -0
- package/lib/index-XiXSFLmI.js +20975 -0
- package/lib/index-bknOViGv.js +47 -0
- package/lib/index-bkuIUPFS.js +275 -0
- package/lib/index-jPA8J9Eo.js +8 -0
- package/lib/index-lsG76a9s.js +552 -0
- package/lib/index-oTRzPo3B.js +146 -0
- package/lib/index-rrf6_6DC.js +317 -0
- package/lib/index-vJbZIHYF.js +81 -0
- package/lib/index-vPRh55CO.js +137 -0
- package/lib/index-vxy63hib.js +323 -0
- package/lib/index-wn1_LgCS.js +99 -0
- package/lib/index-xHADmDT3.js +12 -0
- package/lib/index-yt2EpMtv.js +141 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.es.js +7 -0
- package/lib/javascript-8ZHqHagw.js +758 -0
- package/lib/jinja2-vsOFe0qD.js +154 -0
- package/lib/julia-dlp_pbN1.js +241 -0
- package/lib/livescript-Gf5R-LT6.js +273 -0
- package/lib/lua-c5Y_JsBp.js +221 -0
- package/lib/mathematica-iiGTGmUs.js +35 -0
- package/lib/mbox-ZJh86H8B.js +78 -0
- package/lib/meta-tAGyVRPE.js +511 -0
- package/lib/mirc-i0qkCa0y.js +73 -0
- package/lib/mllike-Dy551fZW.js +275 -0
- package/lib/modelica-n6tGqUT9.js +94 -0
- package/lib/mscgen-aKSbB7D9.js +104 -0
- package/lib/mumps-lNiKA6sp.js +25 -0
- package/lib/nginx--YmuCfDj.js +93 -0
- package/lib/nsis-zhS8iA09.js +62 -0
- package/lib/ntriples-E3jQl3MC.js +79 -0
- package/lib/octave-EQvkGIeG.js +144 -0
- package/lib/oz-W2cpqFf6.js +152 -0
- package/lib/pascal-lCh6ouNZ.js +79 -0
- package/lib/perl-PxEQBX0B.js +915 -0
- package/lib/pig-Y_bNcrzS.js +56 -0
- package/lib/powershell-GaQP-TZr.js +249 -0
- package/lib/properties-mbRyn54L.js +26 -0
- package/lib/prosemirror-noTDkx-k.js +4 -0
- package/lib/protobuf-8CJideyJ.js +49 -0
- package/lib/puppet-ABBaChNZ.js +45 -0
- package/lib/python-sKdHg3Ka.js +321 -0
- package/lib/q-_1yG40Nm.js +89 -0
- package/lib/r-Ziz56bHT.js +108 -0
- package/lib/rpm-ORjGOHaQ.js +57 -0
- package/lib/ruby-jlbYq0dT.js +233 -0
- package/lib/sas-2n7xeUuO.js +107 -0
- package/lib/schema-tKk3m1fu.js +62 -0
- package/lib/scheme-XCs-NPeU.js +126 -0
- package/lib/shell-0_1Um7Dq.js +184 -0
- package/lib/sieve-7uyJD1x1.js +73 -0
- package/lib/simple-mode--HIzBxba.js +95 -0
- package/lib/smalltalk-PEFzrlQ-.js +48 -0
- package/lib/solr-BLBaHahN.js +41 -0
- package/lib/sparql-4F9ZWf1b.js +204 -0
- package/lib/spreadsheet-SGSo6blj.js +49 -0
- package/lib/sql-tebLBzN0.js +291 -0
- package/lib/stex-SFJcFGOO.js +130 -0
- package/lib/stylus-rwwWYWFm.js +256 -0
- package/lib/swift-eorJ0tCv.js +238 -0
- package/lib/tcl-IwXMB8U4.js +82 -0
- package/lib/textile-ok2VyjwC.js +299 -0
- package/lib/theme/classic/index.d.ts +3 -0
- package/lib/theme/classic/index.d.ts.map +1 -0
- package/lib/theme/classic-dark/index.d.ts +3 -0
- package/lib/theme/classic-dark/index.d.ts.map +1 -0
- package/lib/theme/headless/index.d.ts +3 -0
- package/lib/theme/headless/index.d.ts.map +1 -0
- package/lib/theme/index.d.ts +8 -0
- package/lib/theme/index.d.ts.map +1 -0
- package/lib/theme/shared.d.ts +3 -0
- package/lib/theme/shared.d.ts.map +1 -0
- package/lib/tiddlywiki-DLhz8_pc.js +156 -0
- package/lib/tiki-DFAqFElY.js +183 -0
- package/lib/tippy.esm-MZ2vxByW.js +1813 -0
- package/lib/toml-ryxpTZEV.js +49 -0
- package/lib/tooltip-plugin-gcwyQdiT.js +119 -0
- package/lib/troff-ZzZyvNct.js +36 -0
- package/lib/ttcn-6gvkqqpW.js +136 -0
- package/lib/ttcn-cfg-oSu-Dq5C.js +98 -0
- package/lib/turtle-10ofr5au.js +87 -0
- package/lib/use-css-light-dom-EKWZDmbJ.js +82 -0
- package/lib/utils/index.d.ts +4 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/vb-a6n6fzrD.js +74 -0
- package/lib/vbscript-dgvo8jPt.js +324 -0
- package/lib/velocity-CBncCrwO.js +97 -0
- package/lib/verilog-KlcACt6C.js +271 -0
- package/lib/vhdl-NMd7Gf35.js +117 -0
- package/lib/webidl-z1UE5DN_.js +160 -0
- package/lib/xquery-hDt5jWTp.js +431 -0
- package/lib/yacas-ftgh_qwr.js +74 -0
- package/lib/yaml-DnNTfjXK.js +53 -0
- package/lib/z80-dA1PqWe1.js +62 -0
- package/package.json +87 -0
- package/src/core/crepe.ts +98 -0
- package/src/core/index.ts +4 -0
- package/src/core/slice.ts +44 -0
- package/src/feature/block-edit/handle/component.ts +68 -0
- package/src/feature/block-edit/handle/index.ts +81 -0
- package/src/feature/block-edit/index.ts +17 -0
- package/src/feature/block-edit/menu/component.ts +210 -0
- package/src/feature/block-edit/menu/config.ts +335 -0
- package/src/feature/block-edit/menu/icons.ts +171 -0
- package/src/feature/block-edit/menu/index.ts +113 -0
- package/src/feature/block-edit/style.css +126 -0
- package/src/feature/code-mirror/index.ts +60 -0
- package/src/feature/code-mirror/style.css +159 -0
- package/src/feature/gap-cursor/index.ts +31 -0
- package/src/feature/image-block/index.ts +59 -0
- package/src/feature/image-block/style.css +215 -0
- package/src/feature/index.ts +66 -0
- package/src/feature/link-tooltip/consts.ts +47 -0
- package/src/feature/link-tooltip/index.ts +22 -0
- package/src/feature/link-tooltip/style.css +107 -0
- package/src/feature/list-item/consts.ts +15 -0
- package/src/feature/list-item/index.ts +30 -0
- package/src/feature/list-item/style.css +23 -0
- package/src/feature/placeholder/index.ts +87 -0
- package/src/feature/placeholder/style.css +9 -0
- package/src/feature/shared.ts +4 -0
- package/src/feature/toolbar/component.ts +101 -0
- package/src/feature/toolbar/consts.ts +26 -0
- package/src/feature/toolbar/index.ts +92 -0
- package/src/feature/toolbar/style.css +37 -0
- package/src/index.ts +5 -0
- package/src/theme/classic/index.ts +12 -0
- package/src/theme/classic/style.css +192 -0
- package/src/theme/classic-dark/index.ts +12 -0
- package/src/theme/classic-dark/style.css +197 -0
- package/src/theme/headless/index.ts +9 -0
- package/src/theme/index.ts +26 -0
- package/src/theme/shared.ts +4 -0
- package/src/utils/index.ts +12 -0
- package/src/vite-env.d.ts +2 -0
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@milkdown/crepe",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "7.3.3",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Milkdown/milkdown.git",
|
|
9
|
+
"directory": "packages/plugin-cursor"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"milkdown",
|
|
13
|
+
"milkdown plugin",
|
|
14
|
+
"crepe",
|
|
15
|
+
"editor"
|
|
16
|
+
],
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./lib/index.es.js",
|
|
21
|
+
"types": "./lib/index.d.ts"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "./lib/index.es.js",
|
|
25
|
+
"files": [
|
|
26
|
+
"lib",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"atomico": "^1.75.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@codemirror/commands": "^6.2.4",
|
|
34
|
+
"@codemirror/language-data": "^6.3.1",
|
|
35
|
+
"@codemirror/view": "^6.16.0",
|
|
36
|
+
"@emotion/css": "^11.11.2",
|
|
37
|
+
"clsx": "^2.0.0",
|
|
38
|
+
"codemirror": "^6.0.1",
|
|
39
|
+
"nanoid": "^5.0.0",
|
|
40
|
+
"thememirror": "^2.0.1",
|
|
41
|
+
"tslib": "^2.5.0",
|
|
42
|
+
"@milkdown/components": "7.3.3",
|
|
43
|
+
"@milkdown/core": "7.3.3",
|
|
44
|
+
"@milkdown/ctx": "7.3.3",
|
|
45
|
+
"@milkdown/plugin-block": "7.3.3",
|
|
46
|
+
"@milkdown/plugin-clipboard": "7.3.3",
|
|
47
|
+
"@milkdown/plugin-cursor": "7.3.3",
|
|
48
|
+
"@milkdown/plugin-indent": "7.3.3",
|
|
49
|
+
"@milkdown/plugin-history": "7.3.3",
|
|
50
|
+
"@milkdown/plugin-tooltip": "7.3.3",
|
|
51
|
+
"@milkdown/plugin-slash": "7.3.3",
|
|
52
|
+
"@milkdown/preset-commonmark": "7.3.3",
|
|
53
|
+
"@milkdown/prose": "7.3.3",
|
|
54
|
+
"@milkdown/utils": "7.3.3"
|
|
55
|
+
},
|
|
56
|
+
"nx": {
|
|
57
|
+
"targets": {
|
|
58
|
+
"build": {
|
|
59
|
+
"outputs": [
|
|
60
|
+
"{projectRoot}/lib"
|
|
61
|
+
],
|
|
62
|
+
"dependsOn": [
|
|
63
|
+
{
|
|
64
|
+
"target": "build",
|
|
65
|
+
"projects": "dependencies"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"tsc": {
|
|
70
|
+
"outputs": [],
|
|
71
|
+
"dependsOn": [
|
|
72
|
+
{
|
|
73
|
+
"target": "build",
|
|
74
|
+
"projects": "dependencies"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"scripts": {
|
|
81
|
+
"start": "concurrently -n es,dts \"vite build --watch\" \"tsc --emitDeclarationOnly --watch\"",
|
|
82
|
+
"test": "vitest",
|
|
83
|
+
"tsc": "tsc --noEmit && echo",
|
|
84
|
+
"build": "vite build && tsc --emitDeclarationOnly"
|
|
85
|
+
},
|
|
86
|
+
"types": "./lib/index.d.ts"
|
|
87
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { DefaultValue } from '@milkdown/core'
|
|
3
|
+
import { Editor, defaultValueCtx, editorViewOptionsCtx, rootCtx } from '@milkdown/core'
|
|
4
|
+
|
|
5
|
+
import { history } from '@milkdown/plugin-history'
|
|
6
|
+
import { commonmark } from '@milkdown/preset-commonmark'
|
|
7
|
+
import { indent, indentConfig } from '@milkdown/plugin-indent'
|
|
8
|
+
import { clipboard } from '@milkdown/plugin-clipboard'
|
|
9
|
+
import { getMarkdown } from '@milkdown/utils'
|
|
10
|
+
import { CrepeTheme, loadTheme } from '../theme'
|
|
11
|
+
import type { CrepeFeature, CrepeFeatureConfig } from '../feature'
|
|
12
|
+
import { defaultFeatures, loadFeature } from '../feature'
|
|
13
|
+
import { configureEmotion, configureFeatures, configureTheme } from './slice'
|
|
14
|
+
|
|
15
|
+
export interface CrepeConfig {
|
|
16
|
+
theme?: CrepeTheme
|
|
17
|
+
features?: Partial<Record<CrepeFeature, boolean>>
|
|
18
|
+
featureConfigs?: CrepeFeatureConfig
|
|
19
|
+
root?: Node | string | null
|
|
20
|
+
defaultValue?: DefaultValue
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class Crepe {
|
|
24
|
+
readonly #editor: Editor
|
|
25
|
+
readonly #initPromise: Promise<unknown>
|
|
26
|
+
readonly #rootElement: Node
|
|
27
|
+
#editable = true
|
|
28
|
+
|
|
29
|
+
constructor({
|
|
30
|
+
theme = CrepeTheme.Classic,
|
|
31
|
+
root,
|
|
32
|
+
features = {},
|
|
33
|
+
featureConfigs = {},
|
|
34
|
+
defaultValue = '',
|
|
35
|
+
}: CrepeConfig) {
|
|
36
|
+
const enabledFeatures = Object
|
|
37
|
+
.entries({
|
|
38
|
+
...defaultFeatures,
|
|
39
|
+
...features,
|
|
40
|
+
})
|
|
41
|
+
.filter(([, enabled]) => enabled)
|
|
42
|
+
.map(([feature]) => feature as CrepeFeature)
|
|
43
|
+
|
|
44
|
+
this.#rootElement = (typeof root === 'string' ? document.querySelector(root) : root) ?? document.body
|
|
45
|
+
this.#editor = Editor.make()
|
|
46
|
+
.config(configureFeatures(enabledFeatures))
|
|
47
|
+
.config(configureEmotion(this.#rootElement))
|
|
48
|
+
.config(configureTheme(theme))
|
|
49
|
+
.config((ctx) => {
|
|
50
|
+
ctx.set(rootCtx, this.#rootElement)
|
|
51
|
+
ctx.set(defaultValueCtx, defaultValue)
|
|
52
|
+
ctx.set(editorViewOptionsCtx, {
|
|
53
|
+
editable: () => this.#editable,
|
|
54
|
+
})
|
|
55
|
+
ctx.update(indentConfig.key, value => ({
|
|
56
|
+
...value,
|
|
57
|
+
size: 4,
|
|
58
|
+
}))
|
|
59
|
+
})
|
|
60
|
+
.use(commonmark)
|
|
61
|
+
.use(history)
|
|
62
|
+
.use(indent)
|
|
63
|
+
.use(clipboard)
|
|
64
|
+
|
|
65
|
+
const promiseList: Promise<unknown>[] = [loadTheme(theme, this.#editor)]
|
|
66
|
+
|
|
67
|
+
enabledFeatures.forEach((feature) => {
|
|
68
|
+
const config = (featureConfigs as Partial<Record<CrepeFeature, never>>)[feature]
|
|
69
|
+
promiseList.push(
|
|
70
|
+
loadFeature(feature, this.#editor, config),
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
this.#initPromise = Promise.all(promiseList)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async create() {
|
|
78
|
+
await this.#initPromise
|
|
79
|
+
return this.#editor.create()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async destroy() {
|
|
83
|
+
await this.#initPromise
|
|
84
|
+
return this.#editor.destroy()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get editor(): Editor {
|
|
88
|
+
return this.#editor
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setReadonly(value: boolean) {
|
|
92
|
+
this.#editable = !value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getMarkdown() {
|
|
96
|
+
return this.#editor.action(getMarkdown())
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { Ctx } from '@milkdown/ctx'
|
|
3
|
+
import { createSlice } from '@milkdown/ctx'
|
|
4
|
+
import type { Emotion } from '@emotion/css/create-instance'
|
|
5
|
+
import createEmotion from '@emotion/css/create-instance'
|
|
6
|
+
import { customAlphabet } from 'nanoid'
|
|
7
|
+
import { CrepeTheme } from '../theme'
|
|
8
|
+
import type { CrepeFeature } from '../feature'
|
|
9
|
+
|
|
10
|
+
export const ThemeCtx = createSlice(CrepeTheme.Classic, 'ThemeCtx')
|
|
11
|
+
|
|
12
|
+
export const FeaturesCtx = createSlice([] as CrepeFeature[], 'FeaturesCtx')
|
|
13
|
+
|
|
14
|
+
export const EmotionCtx = createSlice(null as unknown as Emotion, 'EmotionCtx')
|
|
15
|
+
|
|
16
|
+
export function configureTheme(theme: CrepeTheme) {
|
|
17
|
+
return (ctx: Ctx) => {
|
|
18
|
+
ctx.inject(ThemeCtx, theme)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 6)
|
|
23
|
+
export function configureEmotion(container: Node) {
|
|
24
|
+
return (ctx: Ctx) => {
|
|
25
|
+
const emotion = createEmotion({
|
|
26
|
+
key: `crepe-${nanoid()}`,
|
|
27
|
+
container,
|
|
28
|
+
})
|
|
29
|
+
ctx.inject(EmotionCtx, emotion)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function injectStyle(style: string) {
|
|
34
|
+
return (ctx: Ctx) => {
|
|
35
|
+
const emotion = ctx.get(EmotionCtx)
|
|
36
|
+
emotion.injectGlobal(style)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function configureFeatures(features: CrepeFeature[]) {
|
|
41
|
+
return (ctx: Ctx) => {
|
|
42
|
+
ctx.inject(FeaturesCtx, features)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { type Component, c, html, useEffect, useRef } from 'atomico'
|
|
3
|
+
|
|
4
|
+
const menuIcon = html`
|
|
5
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
6
|
+
<g clip-path="url(#clip0_971_7680)">
|
|
7
|
+
<path d="M11 18C11 19.1 10.1 20 9 20C7.9 20 7 19.1 7 18C7 16.9 7.9 16 9 16C10.1 16 11 16.9 11 18ZM9 10C7.9 10 7 10.9 7 12C7 13.1 7.9 14 9 14C10.1 14 11 13.1 11 12C11 10.9 10.1 10 9 10ZM9 4C7.9 4 7 4.9 7 6C7 7.1 7.9 8 9 8C10.1 8 11 7.1 11 6C11 4.9 10.1 4 9 4ZM15 8C16.1 8 17 7.1 17 6C17 4.9 16.1 4 15 4C13.9 4 13 4.9 13 6C13 7.1 13.9 8 15 8ZM15 10C13.9 10 13 10.9 13 12C13 13.1 13.9 14 15 14C16.1 14 17 13.1 17 12C17 10.9 16.1 10 15 10ZM15 16C13.9 16 13 16.9 13 18C13 19.1 13.9 20 15 20C16.1 20 17 19.1 17 18C17 16.9 16.1 16 15 16Z" fill="#817567"/>
|
|
8
|
+
</g>
|
|
9
|
+
<defs>
|
|
10
|
+
<clipPath id="clip0_971_7680">
|
|
11
|
+
<rect width="24" height="24" fill="white"/>
|
|
12
|
+
</clipPath>
|
|
13
|
+
</defs>
|
|
14
|
+
</svg>
|
|
15
|
+
`
|
|
16
|
+
|
|
17
|
+
const plusIcon = html`
|
|
18
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
19
|
+
<g clip-path="url(#clip0_971_7676)">
|
|
20
|
+
<path d="M18 13H13V18C13 18.55 12.55 19 12 19C11.45 19 11 18.55 11 18V13H6C5.45 13 5 12.55 5 12C5 11.45 5.45 11 6 11H11V6C11 5.45 11.45 5 12 5C12.55 5 13 5.45 13 6V11H18C18.55 11 19 11.45 19 12C19 12.55 18.55 13 18 13Z" fill="#817567"/>
|
|
21
|
+
</g>
|
|
22
|
+
<defs>
|
|
23
|
+
<clipPath id="clip0_971_7676">
|
|
24
|
+
<rect width="24" height="24" fill="white"/>
|
|
25
|
+
</clipPath>
|
|
26
|
+
</defs>
|
|
27
|
+
</svg>
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
export interface BlockHandleProps {
|
|
31
|
+
show: boolean
|
|
32
|
+
onAdd: () => void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const blockHandleComponent: Component<BlockHandleProps> = ({ onAdd }) => {
|
|
36
|
+
const ref = useRef<HTMLDivElement>()
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
ref.current?.classList.remove('active')
|
|
39
|
+
})
|
|
40
|
+
const onMouseDown = (e: MouseEvent) => {
|
|
41
|
+
e.preventDefault()
|
|
42
|
+
e.stopPropagation()
|
|
43
|
+
ref.current?.classList.add('active')
|
|
44
|
+
}
|
|
45
|
+
const onMouseUp = (e: MouseEvent) => {
|
|
46
|
+
e.preventDefault()
|
|
47
|
+
e.stopPropagation()
|
|
48
|
+
onAdd?.()
|
|
49
|
+
ref.current?.classList.remove('active')
|
|
50
|
+
}
|
|
51
|
+
return html`
|
|
52
|
+
<host>
|
|
53
|
+
<div ref=${ref} onmousedown=${onMouseDown} onmouseup=${onMouseUp} class="operation-item">
|
|
54
|
+
${plusIcon}
|
|
55
|
+
</div>
|
|
56
|
+
<div class="operation-item">
|
|
57
|
+
${menuIcon}
|
|
58
|
+
</div>
|
|
59
|
+
</host>
|
|
60
|
+
`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
blockHandleComponent.props = {
|
|
64
|
+
show: Boolean,
|
|
65
|
+
onAdd: Function,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const BlockHandleElement = c(blockHandleComponent)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { PluginView } from '@milkdown/prose/state'
|
|
3
|
+
import { TextSelection } from '@milkdown/prose/state'
|
|
4
|
+
import { BlockProvider, block } from '@milkdown/plugin-block'
|
|
5
|
+
import type { Ctx } from '@milkdown/ctx'
|
|
6
|
+
import type { EditorView } from '@milkdown/prose/view'
|
|
7
|
+
import type { AtomicoThis } from 'atomico/types/dom'
|
|
8
|
+
import { editorViewCtx } from '@milkdown/core'
|
|
9
|
+
import { paragraphSchema } from '@milkdown/preset-commonmark'
|
|
10
|
+
import { menuAPI } from '../menu'
|
|
11
|
+
import type { BlockHandleProps } from './component'
|
|
12
|
+
import { BlockHandleElement } from './component'
|
|
13
|
+
|
|
14
|
+
export class BlockHandleView implements PluginView {
|
|
15
|
+
#content: AtomicoThis<BlockHandleProps>
|
|
16
|
+
#provider: BlockProvider
|
|
17
|
+
#ctx: Ctx
|
|
18
|
+
|
|
19
|
+
constructor(ctx: Ctx, view: EditorView) {
|
|
20
|
+
this.#ctx = ctx
|
|
21
|
+
const content = new BlockHandleElement()
|
|
22
|
+
this.#content = content
|
|
23
|
+
this.#content.onAdd = this.onAdd
|
|
24
|
+
this.#provider = new BlockProvider({
|
|
25
|
+
ctx,
|
|
26
|
+
content,
|
|
27
|
+
tippyOptions: {
|
|
28
|
+
arrow: false,
|
|
29
|
+
delay: 0,
|
|
30
|
+
duration: 0,
|
|
31
|
+
onShow: () => {
|
|
32
|
+
this.#content.show = true
|
|
33
|
+
},
|
|
34
|
+
onHidden: () => {
|
|
35
|
+
this.#content.show = false
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
this.update(view)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
update = (view: EditorView) => {
|
|
43
|
+
this.#provider.update(view)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
destroy = () => {
|
|
47
|
+
this.#provider.destroy()
|
|
48
|
+
this.#content.remove()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
onAdd = () => {
|
|
52
|
+
const ctx = this.#ctx
|
|
53
|
+
const view = ctx.get(editorViewCtx)
|
|
54
|
+
if (!view.hasFocus())
|
|
55
|
+
view.focus()
|
|
56
|
+
|
|
57
|
+
const { state, dispatch } = view
|
|
58
|
+
const active = this.#provider.activeNode
|
|
59
|
+
if (!active)
|
|
60
|
+
return
|
|
61
|
+
const pos = active.$pos
|
|
62
|
+
const isNoneTextBlock = ['hr', 'image-block'].includes(active.node.type.name)
|
|
63
|
+
const nodeSize = isNoneTextBlock ? active.node.nodeSize : active.node.content.size
|
|
64
|
+
const side = pos.pos + nodeSize + (['blockquote'].includes(pos.parent.type.name) ? 1 : 0)
|
|
65
|
+
const offset
|
|
66
|
+
= ['blockquote'].includes(pos.parent.type.name) ? 1 : isNoneTextBlock ? 1 : 2
|
|
67
|
+
let tr = state.tr.insert(side, paragraphSchema.type(ctx).create())
|
|
68
|
+
tr = tr.setSelection(TextSelection.create(tr.doc, side + offset))
|
|
69
|
+
dispatch(tr.scrollIntoView())
|
|
70
|
+
|
|
71
|
+
this.#provider.hide()
|
|
72
|
+
ctx.get(menuAPI.key).show(tr.selection.from)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
customElements.define('milkdown-block-handle', BlockHandleElement)
|
|
77
|
+
export function configureBlockHandle(ctx: Ctx) {
|
|
78
|
+
ctx.set(block.key, {
|
|
79
|
+
view: view => new BlockHandleView(ctx, view),
|
|
80
|
+
})
|
|
81
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { block } from '@milkdown/plugin-block'
|
|
3
|
+
import type { DefineFeature } from '../shared'
|
|
4
|
+
import { injectStyle } from '../../core/slice'
|
|
5
|
+
import { configureBlockHandle } from './handle'
|
|
6
|
+
import { configureMenu, menu, menuAPI } from './menu'
|
|
7
|
+
import style from './style.css?inline'
|
|
8
|
+
|
|
9
|
+
export const defineFeature: DefineFeature = (editor) => {
|
|
10
|
+
editor
|
|
11
|
+
.config(injectStyle(style))
|
|
12
|
+
.config(configureBlockHandle)
|
|
13
|
+
.config(configureMenu)
|
|
14
|
+
.use(menuAPI)
|
|
15
|
+
.use(block)
|
|
16
|
+
.use(menu)
|
|
17
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { Component } from 'atomico'
|
|
3
|
+
import { c, html, useCallback, useEffect, useHost, useMemo, useRef, useState } from 'atomico'
|
|
4
|
+
import type { Ctx } from '@milkdown/ctx'
|
|
5
|
+
import { getGroups } from './config'
|
|
6
|
+
|
|
7
|
+
export interface MenuProps {
|
|
8
|
+
ctx: Ctx
|
|
9
|
+
show: boolean
|
|
10
|
+
filter: string
|
|
11
|
+
hide: () => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const menuComponent: Component<MenuProps> = ({
|
|
15
|
+
show,
|
|
16
|
+
hide,
|
|
17
|
+
ctx,
|
|
18
|
+
filter,
|
|
19
|
+
}) => {
|
|
20
|
+
const { groups, size } = useMemo(() => getGroups(filter), [filter])
|
|
21
|
+
|
|
22
|
+
const host = useHost()
|
|
23
|
+
const [hoverIndex, setHoverIndex] = useState(0)
|
|
24
|
+
|
|
25
|
+
const prevMousePosition = useRef({ x: -999, y: -999 })
|
|
26
|
+
|
|
27
|
+
const onMouseMove = useCallback((e: MouseEvent) => {
|
|
28
|
+
const prevPos = prevMousePosition.current
|
|
29
|
+
if (!prevPos)
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
const { x, y } = e
|
|
33
|
+
prevPos.x = x
|
|
34
|
+
prevPos.y = y
|
|
35
|
+
}, [])
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (size === 0 && show)
|
|
39
|
+
hide?.()
|
|
40
|
+
}, [size, show])
|
|
41
|
+
|
|
42
|
+
const onHover = useCallback((
|
|
43
|
+
index: number | ((prev: number) => number),
|
|
44
|
+
after?: (index: number) => void,
|
|
45
|
+
) => {
|
|
46
|
+
setHoverIndex((prev) => {
|
|
47
|
+
const next = typeof index === 'function' ? index(prev) : index
|
|
48
|
+
|
|
49
|
+
after?.(next)
|
|
50
|
+
return next
|
|
51
|
+
})
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
54
|
+
const scrollToIndex = useCallback((index: number) => {
|
|
55
|
+
host
|
|
56
|
+
.current
|
|
57
|
+
.querySelector(`[data-index="${index}"]`)
|
|
58
|
+
?.scrollIntoView({
|
|
59
|
+
behavior: 'smooth',
|
|
60
|
+
block: 'end',
|
|
61
|
+
})
|
|
62
|
+
}, [])
|
|
63
|
+
|
|
64
|
+
const runByIndex = useCallback((index: number) => {
|
|
65
|
+
const item = groups.flatMap(group => group.items).at(index)
|
|
66
|
+
if (item && ctx)
|
|
67
|
+
item.onRun(ctx)
|
|
68
|
+
|
|
69
|
+
hide?.()
|
|
70
|
+
}, [groups])
|
|
71
|
+
|
|
72
|
+
const onKeydown = useCallback((e: KeyboardEvent) => {
|
|
73
|
+
if (e.key === 'Escape') {
|
|
74
|
+
e.preventDefault()
|
|
75
|
+
hide?.()
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (e.key === 'ArrowDown') {
|
|
80
|
+
e.preventDefault()
|
|
81
|
+
return onHover(index => (index < size - 1) ? index + 1 : index, scrollToIndex)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (e.key === 'ArrowUp') {
|
|
85
|
+
e.preventDefault()
|
|
86
|
+
return onHover(index => index <= 0 ? index : index - 1, scrollToIndex)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (e.key === 'ArrowLeft') {
|
|
90
|
+
e.preventDefault()
|
|
91
|
+
return onHover((index) => {
|
|
92
|
+
const group = groups.find(group => group.range[0] <= index && group.range[1] > index)
|
|
93
|
+
if (!group)
|
|
94
|
+
return index
|
|
95
|
+
|
|
96
|
+
const prevGroup = groups[groups.indexOf(group) - 1]
|
|
97
|
+
if (!prevGroup)
|
|
98
|
+
return index
|
|
99
|
+
|
|
100
|
+
return prevGroup.range[1] - 1
|
|
101
|
+
}, scrollToIndex)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (e.key === 'ArrowRight') {
|
|
105
|
+
e.preventDefault()
|
|
106
|
+
return onHover((index) => {
|
|
107
|
+
const group = groups.find(group => group.range[0] <= index && group.range[1] > index)
|
|
108
|
+
if (!group)
|
|
109
|
+
return index
|
|
110
|
+
|
|
111
|
+
const nextGroup = groups[groups.indexOf(group) + 1]
|
|
112
|
+
if (!nextGroup)
|
|
113
|
+
return index
|
|
114
|
+
|
|
115
|
+
return nextGroup.range[0]
|
|
116
|
+
}, scrollToIndex)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (e.key === 'Enter') {
|
|
120
|
+
e.preventDefault()
|
|
121
|
+
runByIndex(hoverIndex)
|
|
122
|
+
}
|
|
123
|
+
}, [hide, groups, hoverIndex])
|
|
124
|
+
|
|
125
|
+
const onMouseEnter = useCallback((index: number) => {
|
|
126
|
+
return (e: MouseEvent) => {
|
|
127
|
+
const prevPos = prevMousePosition.current
|
|
128
|
+
if (!prevPos)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
const { x, y } = e
|
|
132
|
+
if (x === prevPos.x && y === prevPos.y)
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
onHover(index)
|
|
136
|
+
}
|
|
137
|
+
}, [])
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (show)
|
|
141
|
+
document.addEventListener('keydown', onKeydown, { capture: true })
|
|
142
|
+
|
|
143
|
+
else document.removeEventListener('keydown', onKeydown, { capture: true })
|
|
144
|
+
|
|
145
|
+
return () => {
|
|
146
|
+
document.removeEventListener('keydown', onKeydown, { capture: true })
|
|
147
|
+
}
|
|
148
|
+
}, [show, onKeydown])
|
|
149
|
+
|
|
150
|
+
return html`
|
|
151
|
+
<host onmousedown=${(e: MouseEvent) => e.preventDefault()}>
|
|
152
|
+
<nav class="tab-group">
|
|
153
|
+
<ul>
|
|
154
|
+
${groups.map(group =>
|
|
155
|
+
html`<li
|
|
156
|
+
key=${group.key}
|
|
157
|
+
onmousedown=${() => onHover(group.range[0], scrollToIndex)}
|
|
158
|
+
class=${hoverIndex >= group.range[0] && hoverIndex < group.range[1] ? 'selected' : ''}
|
|
159
|
+
>
|
|
160
|
+
${group.label}
|
|
161
|
+
</li>`)}
|
|
162
|
+
</ul>
|
|
163
|
+
</nav>
|
|
164
|
+
<div class="menu-groups" onmousemove=${onMouseMove}>
|
|
165
|
+
${groups.map((group) => {
|
|
166
|
+
return html`
|
|
167
|
+
<div key=${group.key} class="menu-group">
|
|
168
|
+
<h6>${group.label}</h6>
|
|
169
|
+
<ul>
|
|
170
|
+
${group.items.map(item =>
|
|
171
|
+
html`<li
|
|
172
|
+
key=${item.key}
|
|
173
|
+
data-index=${item.index}
|
|
174
|
+
class=${hoverIndex === item.index ? 'hover' : ''}
|
|
175
|
+
onmouseenter=${onMouseEnter(item.index)}
|
|
176
|
+
onmousedown=${() => {
|
|
177
|
+
host
|
|
178
|
+
.current
|
|
179
|
+
.querySelector(`[data-index="${item.index}"]`)
|
|
180
|
+
?.classList.add('active')
|
|
181
|
+
}}
|
|
182
|
+
onmouseup=${() => {
|
|
183
|
+
host
|
|
184
|
+
.current
|
|
185
|
+
.querySelector(`[data-index="${item.index}"]`)
|
|
186
|
+
?.classList.remove('active')
|
|
187
|
+
runByIndex(item.index)
|
|
188
|
+
}}
|
|
189
|
+
>
|
|
190
|
+
${item.icon}
|
|
191
|
+
<span>${item.label}</span>
|
|
192
|
+
</li>`,
|
|
193
|
+
)}
|
|
194
|
+
</ul>
|
|
195
|
+
</div>
|
|
196
|
+
`
|
|
197
|
+
})}
|
|
198
|
+
</div>
|
|
199
|
+
</host>
|
|
200
|
+
`
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
menuComponent.props = {
|
|
204
|
+
ctx: Object,
|
|
205
|
+
show: Boolean,
|
|
206
|
+
filter: String,
|
|
207
|
+
hide: Function,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export const MenuElement = c(menuComponent)
|