Skip to content

Commit c5ea755

Browse files
committed
feat: v6.0.1
1 parent bbc8c1a commit c5ea755

File tree

10 files changed

+255
-188
lines changed

10 files changed

+255
-188
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## CHANGELOG
22

3+
### v6.0.1 (2022-07-22)
4+
5+
- feat: add `autoDestroy` prop for [#156](https://github.com/surmon-china/vue-codemirror/pull/156).
6+
- feat: refactoring component.
7+
- chore: upgrade deps and upgrade vite to v3.
8+
39
### v6.0.0 (2022-06-13)
410

511
**Breaking changes**
@@ -74,6 +80,6 @@ add props placeholder
7480

7581
#### project
7682

77-
- add brower support
83+
- add browser support
7884
- add test scripts
7985
- update babel and webpack configs

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ app.use(VueCodemirror, {
153153
| tabSize | Specify the indent when the Tab key is pressed. | `Number` | `2` |
154154
| placeholder | Display when empty. | `String` | `''` |
155155
| style | The CSS style object that acts on the CodeMirror itself. | `Object` | `{}` |
156+
| autoDestroy | Auto destroy the CodeMirror instance before the component unmount. | `Boolean` | `true` |
156157
| extensions | Passed to CodeMirror `EditorState.create({ extensions })` | `Extension` | `[]` |
157158
| selection | Passed to CodeMirror `EditorState.create({ selection })` | `EditorSelection` | - |
158159
| root | Passed to CodeMirror `new EditorView({ root })` | `ShadowRoot \| Document` | - |

dev/App.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
const consoleLog = console.log
1919
const code = shallowRef(`console.log('Hello World')`)
20-
const cm = shallowRef()
20+
const view = shallowRef()
2121
const state = reactive({
2222
disabled: false,
2323
indentWithTab: true,
@@ -29,6 +29,10 @@
2929
theme: 'oneDark'
3030
})
3131
32+
const handleReady = (payload: any) => {
33+
console.log('handleReady payload:', payload)
34+
}
35+
3236
const extensions = computed(() => {
3337
const result = []
3438
result.push(languages[state.language])
@@ -39,7 +43,7 @@
3943
})
4044
4145
onMounted(() => {
42-
console.log('cm', cm)
46+
console.log('mounted view:', view)
4347
})
4448
</script>
4549

@@ -108,7 +112,7 @@
108112
:style="{ backgroundColor: state.backgroundColor }"
109113
:extensions="extensions"
110114
v-model="code"
111-
@ready="consoleLog('ready', $event)"
115+
@ready="handleReady"
112116
@change="consoleLog('change', $event)"
113117
@focus="consoleLog('focus', $event)"
114118
@blur="consoleLog('blur', $event)"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vue-codemirror",
33
"description": "CodeMirror code editor component for Vue",
4-
"version": "6.0.0",
4+
"version": "6.0.1",
55
"homepage": "https://github.com/surmon-china/vue-codemirror#readme",
66
"license": "MIT",
77
"keywords": [

src/codemirror.ts

Lines changed: 83 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,125 @@
1+
import * as CSS from 'csstype'
12
import { EditorState, EditorStateConfig, Compartment, Extension, StateEffect } from '@codemirror/state'
2-
import { EditorView, ViewUpdate, keymap, placeholder } from '@codemirror/view'
3+
import { EditorView, EditorViewConfig, ViewUpdate, keymap, placeholder } from '@codemirror/view'
34
import { indentWithTab } from '@codemirror/commands'
45
import { indentUnit } from '@codemirror/language'
5-
import * as CSS from 'csstype'
66

7-
// state
8-
export interface EditorStateCreatorOptions {
9-
config: EditorStateConfig
10-
onUpdate(viewUpdate: ViewUpdate): void
7+
export interface CreateStateOptions extends EditorStateConfig {
118
onChange(doc: string, viewUpdate: ViewUpdate): void
9+
onUpdate(viewUpdate: ViewUpdate): void
1210
onFocus(viewUpdate: ViewUpdate): void
1311
onBlur(viewUpdate: ViewUpdate): void
1412
}
15-
export const createState = ({ config, ...events }: EditorStateCreatorOptions): EditorState => {
16-
const extensions = Array.isArray(config.extensions) ? config.extensions : [config.extensions]
13+
14+
export const createEditorState = ({ onUpdate, onChange, onFocus, onBlur, ...config }: CreateStateOptions) => {
1715
return EditorState.create({
1816
doc: config.doc,
1917
selection: config.selection,
2018
extensions: [
21-
...extensions,
19+
...(Array.isArray(config.extensions) ? config.extensions : [config.extensions]),
2220
EditorView.updateListener.of((viewUpdate) => {
2321
// https://discuss.codemirror.net/t/codemirror-6-proper-way-to-listen-for-changes/2395/11
24-
events.onUpdate(viewUpdate)
22+
onUpdate(viewUpdate)
23+
// doc changed
2524
if (viewUpdate.docChanged) {
26-
events.onChange(viewUpdate.state.doc.toString(), viewUpdate)
25+
onChange(viewUpdate.state.doc.toString(), viewUpdate)
2726
}
27+
// focus state change
2828
if (viewUpdate.focusChanged) {
29-
viewUpdate.view.hasFocus ? events.onFocus(viewUpdate) : events.onBlur(viewUpdate)
29+
viewUpdate.view.hasFocus ? onFocus(viewUpdate) : onBlur(viewUpdate)
3030
}
3131
})
3232
]
3333
})
3434
}
3535

36-
// doc
37-
export const getDoc = (view: EditorView) => view.state.doc.toString()
38-
export const setDoc = (view: EditorView, newDoc: string) => {
39-
return view.dispatch({
40-
changes: {
41-
from: 0,
42-
to: view.state.doc.length,
43-
insert: newDoc
44-
}
45-
})
36+
export const destroyEditorView = (view: EditorView) => view.destroy()
37+
export const createEditorView = (config: EditorViewConfig) => {
38+
return new EditorView({ ...config })
4639
}
4740

48-
// effects
49-
export const destroy = (view: EditorView) => view.destroy()
50-
export const focus = (view: EditorView) => view.focus() // TODO: focus on the last word
51-
5241
// https://codemirror.net/examples/config/
5342
// https://github.com/uiwjs/react-codemirror/blob/22cc81971a/src/useCodeMirror.ts#L144
5443
// https://gist.github.com/s-cork/e7104bace090702f6acbc3004228f2cb
55-
const rerunCompartment = () => {
44+
export const createEditorCompartment = (view: EditorView) => {
5645
const compartment = new Compartment()
57-
const run = (view: EditorView, extension: Extension) => {
58-
if (compartment.get(view.state)) {
59-
// reconfigure
60-
view.dispatch({ effects: compartment.reconfigure(extension) })
61-
} else {
62-
// inject
63-
view.dispatch({ effects: StateEffect.appendConfig.of(compartment.of(extension)) })
64-
}
46+
const run = (extension: Extension) => {
47+
compartment.get(view.state)
48+
? view.dispatch({ effects: compartment.reconfigure(extension) }) // reconfigure
49+
: view.dispatch({ effects: StateEffect.appendConfig.of(compartment.of(extension)) }) // inject
6550
}
6651
return { compartment, run }
6752
}
6853

6954
// https://codemirror.net/examples/reconfigure/
70-
export const rerunExtension = () => rerunCompartment().run
71-
export const toggleExtension = (extension: Extension) => {
72-
const { compartment, run } = rerunCompartment()
73-
return (view: EditorView, targetApply?: boolean) => {
55+
export const createEditorExtensionToggler = (view: EditorView, extension: Extension) => {
56+
const { compartment, run } = createEditorCompartment(view)
57+
return (targetApply?: boolean) => {
7458
const exExtension = compartment.get(view.state)
7559
const apply = targetApply ?? exExtension !== extension
76-
run(view, apply ? extension : [])
60+
run(apply ? extension : [])
7761
}
7862
}
7963

80-
// extensions
81-
export const extensions = {
82-
placeholder: (string: string) => placeholder(string),
83-
disable: () => [EditorView.editable.of(false), EditorState.readOnly.of(true)],
84-
enable: () => [EditorView.editable.of(true), EditorState.readOnly.of(false)],
64+
export const createEditorTools = (view: EditorView) => {
65+
// UE state
66+
const focus = () => view.focus()
67+
68+
// doc state
69+
const getDoc = () => view.state.doc.toString()
70+
const setDoc = (newDoc: string) => {
71+
if (newDoc !== getDoc()) {
72+
view.dispatch({
73+
changes: {
74+
from: 0,
75+
to: view.state.doc.length,
76+
insert: newDoc
77+
}
78+
})
79+
}
80+
}
81+
82+
// reconfigure extension
83+
const { run: reExtensions } = createEditorCompartment(view)
84+
85+
// disabled editor
86+
const toggleDisabled = createEditorExtensionToggler(view, [
87+
EditorView.editable.of(false),
88+
EditorState.readOnly.of(true)
89+
])
90+
8591
// https://codemirror.net/examples/tab/
86-
indentWithTab: () => keymap.of([indentWithTab]),
87-
tabSize: (tabSize: number) => [EditorState.tabSize.of(tabSize), indentUnit.of(' '.repeat(tabSize))],
92+
const toggleIndentWithTab = createEditorExtensionToggler(view, keymap.of([indentWithTab]))
93+
94+
// tab size
95+
// https://gist.github.com/s-cork/e7104bace090702f6acbc3004228f2cb
96+
const { run: reTabSize } = createEditorCompartment(view)
97+
const setTabSize = (tabSize: number) => {
98+
reTabSize([EditorState.tabSize.of(tabSize), indentUnit.of(' '.repeat(tabSize))])
99+
}
100+
101+
// set editor's placeholder
102+
const { run: rePlaceholder } = createEditorCompartment(view)
103+
const setPlaceholder = (value: string) => {
104+
rePlaceholder(placeholder(value))
105+
}
106+
107+
// set style to editor element
88108
// https://codemirror.net/examples/styling/
89-
style: (style: CSS.Properties) => EditorView.theme({ '&': { ...style } })
109+
const { run: reStyle } = createEditorCompartment(view)
110+
const setStyle = (style: CSS.Properties = {}) => {
111+
reStyle(EditorView.theme({ '&': { ...style } }))
112+
}
113+
114+
return {
115+
focus,
116+
getDoc,
117+
setDoc,
118+
reExtensions,
119+
toggleDisabled,
120+
toggleIndentWithTab,
121+
setTabSize,
122+
setPlaceholder,
123+
setStyle
124+
}
90125
}

0 commit comments

Comments
 (0)