sh-view 1.5.2 → 1.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-view",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "description": "基于vxe-table、view-ui-plus二次封装",
5
5
  "main": "packages/index.js",
6
6
  "scripts": {
@@ -10,10 +10,10 @@ import { basicSetup } from 'codemirror'
10
10
  import { keymap, placeholder, drawSelection, lineNumbers, EditorView } from '@codemirror/view'
11
11
  import { Compartment, EditorState, StateEffect } from '@codemirror/state'
12
12
  import { defaultKeymap, indentWithTab, historyKeymap, history } from '@codemirror/commands'
13
+ import themes from './themes'
13
14
  import { javascript } from '@codemirror/lang-javascript'
14
15
  import { sql } from '@codemirror/lang-sql'
15
16
  import { json } from '@codemirror/lang-json'
16
- const language = new Compartment()
17
17
  const tabSize = new Compartment()
18
18
  export default {
19
19
  name: 'ShCodeEditor',
@@ -34,7 +34,7 @@ export default {
34
34
  },
35
35
  theme: {
36
36
  type: String,
37
- default: 'default'
37
+ default: ''
38
38
  },
39
39
  placeholder: {
40
40
  type: String,
@@ -76,12 +76,11 @@ export default {
76
76
  default: 'auto'
77
77
  }
78
78
  },
79
- emits: ['update:modelValue', 'change', 'loaded', 'focus', 'destroy'],
79
+ emits: ['update:modelValue', 'change', 'loaded', 'focus', 'blur', 'destroy'],
80
80
  data() {
81
81
  return {
82
82
  codeEditor: null,
83
83
  codeLength: 0,
84
- result: '',
85
84
  error: null
86
85
  }
87
86
  },
@@ -93,48 +92,42 @@ export default {
93
92
  border: this.border ? '1px solid var(--border-color)' : 'none'
94
93
  }
95
94
  },
96
- codeFocus() {
97
- return this.codeEditor && this.codeEditor?.hasFocus
98
- },
99
95
  codeExtensions() {
96
+ const { mode, disabled, multipleSelection, indent, theme, tab, wrap, extensions } = this
100
97
  let defaultExtensions = [basicSetup, history(), drawSelection(), lineNumbers(), placeholder(this.placeholder), keymap.of([...defaultKeymap, ...historyKeymap])]
101
- if (['javascript', 'js'].includes(this.mode.toLowerCase())) {
98
+ if (['javascript', 'js'].includes(mode.toLowerCase())) {
102
99
  defaultExtensions.push(javascript())
103
- } else if (['mysql', 'sql'].includes(this.mode.toLowerCase())) {
100
+ } else if (['mysql', 'sql'].includes(mode.toLowerCase())) {
104
101
  defaultExtensions.push(sql())
105
- } else if (['json'].includes(this.mode.toLowerCase())) {
102
+ } else if (['json'].includes(mode.toLowerCase())) {
106
103
  defaultExtensions.push(json())
107
104
  }
108
105
  return [
109
106
  ...defaultExtensions,
110
107
  EditorView.updateListener.of(this.updateListener),
111
- EditorView.theme(null, { dark: this.theme === 'dark' }),
112
- EditorView.editable.of(!this.disabled),
113
- EditorState.allowMultipleSelections.of(this.multipleSelection),
114
- tabSize.of(EditorState.tabSize.of(this.indent)),
115
- this.tab ? keymap.of([indentWithTab]) : undefined,
116
- this.wrap ? EditorView.lineWrapping : undefined,
117
- ...this.extensions
108
+ EditorView.focusChangeEffect.of(this.focusListener),
109
+ EditorView.editable.of(!disabled),
110
+ EditorState.allowMultipleSelections.of(multipleSelection),
111
+ tabSize.of(EditorState.tabSize.of(indent)),
112
+ theme && themes[theme] ? themes[theme] : undefined,
113
+ tab ? keymap.of([indentWithTab]) : undefined,
114
+ wrap ? EditorView.lineWrapping : undefined,
115
+ ...extensions
118
116
  ].filter(item => !!item)
119
117
  }
120
118
  },
121
119
  watch: {
122
- modelValue: {
123
- handler(value) {
124
- if (this.codeEditor) {
125
- if (this.codeEditor.composing) return
126
- // this.codeEditor.dispatch({
127
- // changes: { from: 0, to: this.codeEditor.state.doc.length, insert: value },
128
- // selection: this.codeEditor.state.selection,
129
- // scrollIntoView: true
130
- // })
131
- this.codeLength = this.codeEditor.state.doc.length
132
- }
133
- },
134
- immediate: true
135
- },
136
- codeFocus(value) {
137
- this.emitFocus(value)
120
+ modelValue(value) {
121
+ if (this.codeEditor && !this.codeEditor.composing) {
122
+ let docLength = this.codeEditor.state.doc.length
123
+ let docValue = this.getTransformValue(value)
124
+ this.codeEditor.dispatch({
125
+ changes: { from: 0, to: docLength, insert: docValue },
126
+ selection: this.codeEditor.state.selection,
127
+ scrollIntoView: true
128
+ })
129
+ this.codeLength = docLength
130
+ }
138
131
  },
139
132
  codeExtensions: {
140
133
  handler(exts) {
@@ -158,9 +151,9 @@ export default {
158
151
  },
159
152
  async codeRender() {
160
153
  const { codeRef, codeExtensions, modelValue, emitLoaded } = this
161
- let docText = typeof modelValue === 'object' ? JSON.stringify(modelValue) : modelValue
154
+ let docValue = this.getTransformValue(modelValue)
162
155
  let codeState = EditorState.create({
163
- doc: docText,
156
+ doc: docValue,
164
157
  extensions: codeExtensions
165
158
  })
166
159
  this.codeEditor = new EditorView({
@@ -170,6 +163,15 @@ export default {
170
163
  await this.$nextTick()
171
164
  emitLoaded()
172
165
  },
166
+ focusListener(state, focusing) {
167
+ let valueStr = state.doc.toString()
168
+ if (focusing) {
169
+ this.emitFocus(valueStr)
170
+ } else {
171
+ this.emitValue(valueStr)
172
+ this.emitBlur(valueStr)
173
+ }
174
+ },
173
175
  async updateListener({ state, changes, docChanged }) {
174
176
  if (changes.empty || !docChanged) {
175
177
  return
@@ -186,22 +188,44 @@ export default {
186
188
  // props.linter(view.value) as readonly Diagnostic[]
187
189
  // ).length;
188
190
  // }
189
- this.emitValue(valueStr)
190
191
  this.emitChange(valueStr)
191
192
  },
192
193
  focus() {
193
194
  this.codeEditor && this.codeEditor.focus()
194
195
  },
196
+ getTransformValue(value, out) {
197
+ const { modelValue, indent } = this
198
+ let result = '',
199
+ error = null
200
+ try {
201
+ if (typeof modelValue === 'object') {
202
+ result = out ? JSON.parse(value, null, indent) : JSON.stringify(value, null, indent)
203
+ } else {
204
+ result = value
205
+ }
206
+ } catch (e) {
207
+ error = e
208
+ }
209
+ this.error = error
210
+ return result
211
+ },
195
212
  emitValue(value) {
196
- let emitValue = typeof this.modelValue === 'object' ? JSON.parse(value) : value
197
- this.$emit('update:modelValue', emitValue)
213
+ let outValue = this.getTransformValue(value, true)
214
+ if (this.error) return
215
+ this.$emit('update:modelValue', outValue)
198
216
  },
199
217
  emitChange(value) {
200
218
  this.$emit('change', { value, $event: this.codeEditor })
201
- this.emitValue(value)
202
219
  },
203
220
  emitFocus(value) {
204
- this.$emit('focus', value)
221
+ let outValue = this.getTransformValue(value, true)
222
+ if (this.error) return
223
+ this.$emit('focus', { value: outValue, $event: this.codeEditor })
224
+ },
225
+ emitBlur(value) {
226
+ let outValue = this.getTransformValue(value, true)
227
+ if (this.error) return
228
+ this.$emit('blur', { value: outValue, $event: this.codeEditor })
205
229
  },
206
230
  emitLoaded() {
207
231
  this.$emit('loaded', { value: this.modelValue, $event: this.codeEditor })
@@ -0,0 +1,100 @@
1
+ import { EditorView } from '@codemirror/view'
2
+ import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
3
+ import { tags } from '@lezer/highlight'
4
+
5
+ const chalky = '#e5c07b',
6
+ coral = '#e06c75',
7
+ cyan = '#56b6c2',
8
+ invalid = '#ffffff',
9
+ ivory = '#abb2bf',
10
+ stone = '#7d8799', // Brightened compared to original to increase contrast
11
+ malibu = '#61afef',
12
+ sage = '#98c379',
13
+ whiskey = '#d19a66',
14
+ violet = '#c678dd',
15
+ darkBackground = '#21252b',
16
+ highlightBackground = '#2c313a',
17
+ background = '#282c34',
18
+ tooltipBackground = '#353a42',
19
+ selection = '#3E4451',
20
+ cursor = '#528bff'
21
+
22
+ const theme = EditorView.theme({
23
+ '&': {
24
+ color: ivory,
25
+ backgroundColor: background,
26
+ height: '100%'
27
+ },
28
+ '.cm-content': {
29
+ caretColor: cursor
30
+ },
31
+ '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
32
+ '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': { backgroundColor: selection },
33
+ '.cm-panels': { backgroundColor: darkBackground, color: ivory },
34
+ '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
35
+ '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
36
+ '.cm-searchMatch': {
37
+ backgroundColor: '#72a1ff59',
38
+ outline: '1px solid #457dff'
39
+ },
40
+ '.cm-searchMatch.cm-searchMatch-selected': {
41
+ backgroundColor: '#6199ff2f'
42
+ },
43
+ '.cm-activeLine': { backgroundColor: '#6699ff0b' },
44
+ '.cm-selectionMatch': { backgroundColor: '#aafe661a' },
45
+ '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
46
+ backgroundColor: '#bad0f847'
47
+ },
48
+ '.cm-gutters': {
49
+ backgroundColor: background,
50
+ color: stone,
51
+ border: 'none'
52
+ },
53
+ '.cm-activeLineGutter': {
54
+ backgroundColor: highlightBackground
55
+ },
56
+ '.cm-foldPlaceholder': {
57
+ backgroundColor: 'transparent',
58
+ border: 'none',
59
+ color: '#ddd'
60
+ },
61
+ '.cm-tooltip': {
62
+ border: 'none',
63
+ backgroundColor: tooltipBackground
64
+ },
65
+ '.cm-tooltip .cm-tooltip-arrow:before': {
66
+ borderTopColor: 'transparent',
67
+ borderBottomColor: 'transparent'
68
+ },
69
+ '.cm-tooltip .cm-tooltip-arrow:after': {
70
+ borderTopColor: tooltipBackground,
71
+ borderBottomColor: tooltipBackground
72
+ },
73
+ '.cm-tooltip-autocomplete': {
74
+ '& > ul > li[aria-selected]': {
75
+ backgroundColor: highlightBackground,
76
+ color: ivory
77
+ }
78
+ }
79
+ })
80
+
81
+ const themeHighlightStyle = HighlightStyle.define([
82
+ { tag: tags.keyword, color: violet },
83
+ { tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: coral },
84
+ { tag: [tags.function(tags.variableName), tags.labelName], color: malibu },
85
+ { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: whiskey },
86
+ { tag: [tags.definition(tags.name), tags.separator], color: ivory },
87
+ { tag: [tags.typeName, tags.className, tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: chalky },
88
+ { tag: [tags.operator, tags.operatorKeyword, tags.url, tags.escape, tags.regexp, tags.link, tags.special(tags.string)], color: cyan },
89
+ { tag: [tags.meta, tags.comment], color: stone },
90
+ { tag: tags.strong, fontWeight: 'bold' },
91
+ { tag: tags.emphasis, fontStyle: 'italic' },
92
+ { tag: tags.strikethrough, textDecoration: 'line-through' },
93
+ { tag: tags.link, color: stone, textDecoration: 'underline' },
94
+ { tag: tags.heading, fontWeight: 'bold', color: coral },
95
+ { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: whiskey },
96
+ { tag: [tags.processingInstruction, tags.string, tags.inserted], color: sage },
97
+ { tag: tags.invalid, color: invalid }
98
+ ])
99
+
100
+ export default [theme, syntaxHighlighting(themeHighlightStyle)]
@@ -0,0 +1,100 @@
1
+ import { EditorView } from '@codemirror/view'
2
+ import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
3
+ import { tags } from '@lezer/highlight'
4
+
5
+ const chalky = '#bd93f9',
6
+ coral = '#e06c75',
7
+ cyan = '#56b6c2',
8
+ invalid = '#ffffff',
9
+ ivory = '#f8f8f2',
10
+ stone = '#7d8799', // Brightened compared to original to increase contrast
11
+ malibu = '#61afef',
12
+ sage = '#66d9ef',
13
+ whiskey = '#d19a66',
14
+ violet = '#c678dd',
15
+ darkBackground = '#21252b',
16
+ highlightBackground = '#2c313a',
17
+ background = '#282a36',
18
+ tooltipBackground = '#353a42',
19
+ selection = '#3E4451',
20
+ cursor = '#528bff'
21
+
22
+ const theme = EditorView.theme({
23
+ '&': {
24
+ color: ivory,
25
+ backgroundColor: background,
26
+ height: '100%'
27
+ },
28
+ '.cm-content': {
29
+ caretColor: cursor
30
+ },
31
+ '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
32
+ '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': { backgroundColor: selection },
33
+ '.cm-panels': { backgroundColor: darkBackground, color: ivory },
34
+ '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
35
+ '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
36
+ '.cm-searchMatch': {
37
+ backgroundColor: '#72a1ff59',
38
+ outline: '1px solid #457dff'
39
+ },
40
+ '.cm-searchMatch.cm-searchMatch-selected': {
41
+ backgroundColor: '#6199ff2f'
42
+ },
43
+ '.cm-activeLine': { backgroundColor: '#6699ff0b' },
44
+ '.cm-selectionMatch': { backgroundColor: '#aafe661a' },
45
+ '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
46
+ backgroundColor: '#bad0f847'
47
+ },
48
+ '.cm-gutters': {
49
+ backgroundColor: background,
50
+ color: stone,
51
+ border: 'none'
52
+ },
53
+ '.cm-activeLineGutter': {
54
+ backgroundColor: highlightBackground
55
+ },
56
+ '.cm-foldPlaceholder': {
57
+ backgroundColor: 'transparent',
58
+ border: 'none',
59
+ color: '#ddd'
60
+ },
61
+ '.cm-tooltip': {
62
+ border: 'none',
63
+ backgroundColor: tooltipBackground
64
+ },
65
+ '.cm-tooltip .cm-tooltip-arrow:before': {
66
+ borderTopColor: 'transparent',
67
+ borderBottomColor: 'transparent'
68
+ },
69
+ '.cm-tooltip .cm-tooltip-arrow:after': {
70
+ borderTopColor: tooltipBackground,
71
+ borderBottomColor: tooltipBackground
72
+ },
73
+ '.cm-tooltip-autocomplete': {
74
+ '& > ul > li[aria-selected]': {
75
+ backgroundColor: highlightBackground,
76
+ color: ivory
77
+ }
78
+ }
79
+ })
80
+
81
+ const themeHighlightStyle = HighlightStyle.define([
82
+ { tag: tags.keyword, color: violet },
83
+ { tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: coral },
84
+ { tag: [tags.function(tags.variableName), tags.labelName], color: malibu },
85
+ { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: whiskey },
86
+ { tag: [tags.definition(tags.name), tags.separator], color: ivory },
87
+ { tag: [tags.typeName, tags.className, tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: chalky },
88
+ { tag: [tags.operator, tags.operatorKeyword, tags.url, tags.escape, tags.regexp, tags.link, tags.special(tags.string)], color: cyan },
89
+ { tag: [tags.meta, tags.comment], color: stone },
90
+ { tag: tags.strong, fontWeight: 'bold' },
91
+ { tag: tags.emphasis, fontStyle: 'italic' },
92
+ { tag: tags.strikethrough, textDecoration: 'line-through' },
93
+ { tag: tags.link, color: stone, textDecoration: 'underline' },
94
+ { tag: tags.heading, fontWeight: 'bold', color: coral },
95
+ { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: whiskey },
96
+ { tag: [tags.processingInstruction, tags.string, tags.inserted], color: sage },
97
+ { tag: tags.invalid, color: invalid }
98
+ ])
99
+
100
+ export default [theme, syntaxHighlighting(themeHighlightStyle)]
@@ -0,0 +1,7 @@
1
+ import dark from './dark'
2
+ import dracula from './dracula'
3
+
4
+ export default {
5
+ dark,
6
+ dracula
7
+ }