@scalar/use-codemirror 0.5.0 → 0.5.1

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/README.md CHANGED
@@ -15,7 +15,7 @@ npm install @scalar/use-codemirror
15
15
 
16
16
  ```vue
17
17
  <script setup>
18
- import { CodeMirror } from '../CodeMirror'
18
+ import { CodeMirror } from '@scalar/use-codemirror'
19
19
  </script>
20
20
 
21
21
  <CodeMirror
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "composable",
8
8
  "codemirror"
9
9
  ],
10
- "version": "0.5.0",
10
+ "version": "0.5.1",
11
11
  "author": "Scalar (https://github.com/scalar)",
12
12
  "homepage": "https://github.com/scalar/scalar",
13
13
  "repository": {
@@ -26,11 +26,9 @@
26
26
  "main": "dist/index.js",
27
27
  "module": "dist/index.js",
28
28
  "files": [
29
- "src",
30
29
  "dist"
31
30
  ],
32
31
  "exports": {
33
- "development": "./src/index.ts",
34
32
  "import": "./dist/index.js"
35
33
  },
36
34
  "dependencies": {
@@ -62,6 +60,7 @@
62
60
  "tsc-alias": "1.8.6",
63
61
  "vite": "4.4.8",
64
62
  "vitest": "0.34.1",
63
+ "@vitest/coverage-v8": "^0.34.4",
65
64
  "vue-tsc": "1.8.8"
66
65
  },
67
66
  "peerDependencies": {
@@ -1,249 +0,0 @@
1
- <script lang="ts" setup>
2
- import { java } from '@codemirror/lang-java'
3
- import { javascript } from '@codemirror/lang-javascript'
4
- import { json } from '@codemirror/lang-json'
5
- import { python } from '@codemirror/lang-python'
6
- import { type LanguageSupport, StreamLanguage } from '@codemirror/language'
7
- import {
8
- c,
9
- csharp,
10
- kotlin,
11
- objectiveC,
12
- } from '@codemirror/legacy-modes/mode/clike'
13
- import { clojure } from '@codemirror/legacy-modes/mode/clojure'
14
- import { go } from '@codemirror/legacy-modes/mode/go'
15
- import { http } from '@codemirror/legacy-modes/mode/http'
16
- import { oCaml } from '@codemirror/legacy-modes/mode/mllike'
17
- import { powerShell } from '@codemirror/legacy-modes/mode/powershell'
18
- import { r } from '@codemirror/legacy-modes/mode/r'
19
- import { ruby } from '@codemirror/legacy-modes/mode/ruby'
20
- import { shell } from '@codemirror/legacy-modes/mode/shell'
21
- import { swift } from '@codemirror/legacy-modes/mode/swift'
22
- import { type Extension } from '@codemirror/state'
23
- import {
24
- EditorView,
25
- type ViewUpdate,
26
- keymap,
27
- lineNumbers as lineNumbersExtension,
28
- } from '@codemirror/view'
29
- import { watch } from 'vue'
30
-
31
- import { useCodeMirror } from '../../hooks'
32
- import { variables } from './extensions/variables'
33
-
34
- const props = withDefaults(
35
- defineProps<{
36
- extensions?: Extension[]
37
- content?: string
38
- readOnly?: boolean
39
- languages?: Language[]
40
- withVariables?: boolean
41
- lineNumbers?: boolean
42
- withoutTheme?: boolean
43
- disableEnter?: boolean
44
- forceDarkMode?: boolean
45
- }>(),
46
- {
47
- disableEnter: false,
48
- forceDarkMode: false,
49
- },
50
- )
51
-
52
- const emit = defineEmits<{
53
- (e: 'change', value: string): void
54
- }>()
55
-
56
- // TODO: Add 'php' and 'laravel'
57
- const syntaxHighlighting: Partial<
58
- Record<Language, LanguageSupport | StreamLanguage<any>>
59
- > = {
60
- axios: javascript(),
61
- c: StreamLanguage.define(c),
62
- clojure: StreamLanguage.define(clojure),
63
- csharp: StreamLanguage.define(csharp),
64
- go: StreamLanguage.define(go),
65
- http: StreamLanguage.define(http),
66
- java: java(),
67
- javascript: javascript(),
68
- json: json(),
69
- kotlin: StreamLanguage.define(kotlin),
70
- node: javascript(),
71
- objc: StreamLanguage.define(objectiveC),
72
- ocaml: StreamLanguage.define(oCaml),
73
- powershell: StreamLanguage.define(powerShell),
74
- python: python(),
75
- r: StreamLanguage.define(r),
76
- ruby: StreamLanguage.define(ruby),
77
- shell: StreamLanguage.define(shell),
78
- swift: StreamLanguage.define(swift),
79
- }
80
-
81
- type Language =
82
- | 'axios'
83
- | 'c'
84
- | 'clojure'
85
- | 'csharp'
86
- | 'go'
87
- | 'http'
88
- | 'java'
89
- | 'javascript'
90
- | 'json'
91
- | 'kotlin'
92
- | 'node'
93
- | 'objc'
94
- | 'ocaml'
95
- | 'powershell'
96
- | 'python'
97
- | 'r'
98
- | 'ruby'
99
- | 'shell'
100
- | 'swift'
101
- | 'php'
102
-
103
- // CSS Class
104
- const classes = ['scalar-api-client__codemirror']
105
-
106
- if (props.readOnly) {
107
- classes.push('scalar-api-client__codemirror--read-only')
108
- }
109
-
110
- const getCodeMirrorExtensions = () => {
111
- const extensions: Extension[] = []
112
-
113
- extensions.push(EditorView.editorAttributes.of({ class: classes.join(' ') }))
114
-
115
- // Custom extensions
116
- if (props.extensions) {
117
- props.extensions.forEach((extension) => {
118
- extensions.push(extension)
119
- })
120
- }
121
-
122
- // Read only
123
- if (props.readOnly) {
124
- extensions.push(EditorView.editable.of(false))
125
- }
126
-
127
- // Syntax highlighting
128
- if (props.languages) {
129
- props.languages
130
- .filter((language) => typeof syntaxHighlighting[language] !== 'undefined')
131
- .forEach((language) => {
132
- extensions.push(syntaxHighlighting[language] as Extension)
133
- })
134
- }
135
-
136
- // Line numbers
137
- if (props.lineNumbers) {
138
- extensions.push(lineNumbersExtension())
139
- }
140
-
141
- // Highlight variables
142
- if (props.withVariables) {
143
- extensions.push(variables())
144
- }
145
-
146
- if (props.disableEnter) {
147
- extensions.push(
148
- keymap.of([
149
- {
150
- key: 'Enter',
151
- run: () => {
152
- return true
153
- },
154
- },
155
- {
156
- key: 'Ctrl-Enter',
157
- mac: 'Cmd-Enter',
158
- run: () => {
159
- return true
160
- },
161
- },
162
- {
163
- key: 'Shift-Enter',
164
- run: () => {
165
- return true
166
- },
167
- },
168
- ]),
169
- )
170
- }
171
-
172
- // Listen to updates
173
- extensions.push(
174
- EditorView.updateListener.of((v: ViewUpdate) => {
175
- if (!v.docChanged) {
176
- return
177
- }
178
-
179
- emit('change', v.state.doc.toString())
180
- }),
181
- )
182
-
183
- return extensions
184
- }
185
-
186
- const { codeMirrorRef, setCodeMirrorContent, reconfigureCodeMirror } =
187
- useCodeMirror({
188
- content: props.content ?? '',
189
- extensions: getCodeMirrorExtensions(),
190
- withoutTheme: props.withoutTheme,
191
- forceDarkMode: props.forceDarkMode,
192
- })
193
-
194
- watch(props, () => {
195
- setCodeMirrorContent(props.content ?? '')
196
- reconfigureCodeMirror(getCodeMirrorExtensions())
197
- })
198
-
199
- defineExpose({
200
- setCodeMirrorContent,
201
- })
202
- </script>
203
-
204
- <template>
205
- <div
206
- ref="codeMirrorRef"
207
- class="scalar-api-client__codemirror__wrapper" />
208
- </template>
209
-
210
- <style>
211
- /** Basics */
212
- .scalar-api-client__codemirror__wrapper {
213
- width: 100%;
214
- display: flex;
215
- align-items: stretch;
216
- }
217
-
218
- .scalar-api-client__codemirror {
219
- flex-grow: 1;
220
- max-width: 100%;
221
-
222
- font-size: var(--theme-small);
223
- }
224
-
225
- /* .scalar-api-client__codemirror.ͼw {
226
- background-color: var(--theme-background-1);
227
- }
228
-
229
- .scalar-api-client__codemirror--read-only.ͼw {
230
- background-color: var(--theme-background-2);
231
- } */
232
-
233
- /** URL input */
234
- .scalar-api-client__url-input {
235
- font-weight: var(--theme-semibold);
236
- }
237
-
238
- /* .scalar-api-client__url-input .cm-scroller {
239
- padding-left: 6px;
240
- }
241
-
242
- .scalar-api-client__url-input .ͼ1 .cm-scroller {
243
- align-items: center !important;
244
- } */
245
-
246
- .scalar-api-client__variable {
247
- color: var(--scalar-api-client-color);
248
- }
249
- </style>
@@ -1,41 +0,0 @@
1
- import {
2
- Decoration,
3
- type DecorationSet,
4
- EditorView,
5
- MatchDecorator,
6
- ViewPlugin,
7
- type ViewUpdate,
8
- } from '@codemirror/view'
9
-
10
- const variableHighlighterDecoration = new MatchDecorator({
11
- regexp: /(\{[^}]+\})/g,
12
- decoration: () =>
13
- Decoration.mark({
14
- attributes: {
15
- class: 'scalar-api-client__variable',
16
- },
17
- }),
18
- })
19
-
20
- export const variables = () =>
21
- ViewPlugin.fromClass(
22
- class {
23
- variables: DecorationSet
24
- constructor(view: EditorView) {
25
- this.variables = variableHighlighterDecoration.createDeco(view)
26
- }
27
- update(update: ViewUpdate) {
28
- this.variables = variableHighlighterDecoration.updateDeco(
29
- update,
30
- this.variables,
31
- )
32
- }
33
- },
34
- {
35
- decorations: (instance) => instance.variables,
36
- provide: (plugin) =>
37
- EditorView.atomicRanges.of(
38
- (view) => view.plugin(plugin)?.variables || Decoration.none,
39
- ),
40
- },
41
- )
@@ -1 +0,0 @@
1
- export { default as CodeMirror } from './CodeMirror.vue'
@@ -1 +0,0 @@
1
- export * from './useCodeMirror'
@@ -1,7 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- describe('example', () => {
4
- it('executes tests', () => {
5
- expect(true).toBe(true)
6
- })
7
- })
@@ -1,181 +0,0 @@
1
- import { type Extension, StateEffect } from '@codemirror/state'
2
- import { type EditorViewConfig } from '@codemirror/view'
3
- import { EditorView } from 'codemirror'
4
- import { type Ref, ref, watch } from 'vue'
5
-
6
- import { darkTheme, lightTheme } from '../themes'
7
-
8
- /** TODO: This is a static value, make it work with a dynamic parameter. */
9
- const isDark = ref(false)
10
-
11
- type UseCodeMirrorParameters = {
12
- /**
13
- * Some additional CodeMirror extensions.
14
- */
15
- extensions: Extension[]
16
- /**
17
- * Prefill the content. Will be ignored when a provider is given.
18
- */
19
- content?: string
20
- /**
21
- * Force the dark mode.
22
- */
23
- forceDarkMode?: boolean
24
- /**
25
- * Force the light mode.
26
- */
27
- forceLightMode?: boolean
28
- /**
29
- * Whether to load a theme.
30
- */
31
- withoutTheme?: boolean
32
- }
33
-
34
- export const useCodeMirror = (
35
- parameters: UseCodeMirrorParameters,
36
- ): {
37
- value: Ref<string>
38
- codeMirrorRef: Ref<HTMLDivElement | null>
39
- codeMirror: Ref<EditorView | null>
40
- setCodeMirrorContent: (content: string) => void
41
- reconfigureCodeMirror: (newExtensions: Extension[]) => void
42
- restartCodeMirror: (newExtensions: Extension[]) => void
43
- } => {
44
- const { extensions, content, forceDarkMode, forceLightMode, withoutTheme } =
45
- parameters
46
- const value = ref(content ?? '')
47
- const codeMirrorRef = ref<HTMLDivElement | null>(null)
48
- const codeMirror = ref<EditorView | null>(null)
49
-
50
- // Unmounts CodeMirror if it’s mounted already, and mounts CodeMirror, if the given ref exists.
51
- watch(codeMirrorRef, () => {
52
- destroyCodeMirror()
53
- mountCodeMirror(extensions)
54
- })
55
-
56
- // Initializes CodeMirror.
57
- const mountCodeMirror = (withCustomExtensions: Extension[]) => {
58
- if (codeMirrorRef.value) {
59
- const configuration: EditorViewConfig = {
60
- parent: codeMirrorRef.value,
61
- extensions: addDefaultExtensions(withCustomExtensions),
62
- }
63
-
64
- // Only set the content, when not in collaborative editing mode
65
- if (content) {
66
- configuration.doc = content
67
- }
68
-
69
- codeMirror.value = new EditorView(configuration)
70
- }
71
- }
72
-
73
- const getCurrentTheme = () => {
74
- if (withoutTheme) {
75
- return null
76
- }
77
-
78
- if (forceDarkMode) {
79
- return darkTheme
80
- }
81
-
82
- if (forceLightMode) {
83
- return lightTheme
84
- }
85
-
86
- if (isDark.value) {
87
- return darkTheme
88
- }
89
-
90
- return lightTheme
91
- }
92
-
93
- // Extend the given extension list with a dark/light theme.
94
- const addDefaultExtensions = (newExtensions: Extension[] = []) => {
95
- // Themes
96
- const defaultExtensions: Extension[] = [
97
- EditorView.theme({}, { dark: forceDarkMode ? false : isDark.value }),
98
- getCurrentTheme(),
99
- ].filter((extension) => extension !== null) as Extension[]
100
-
101
- return [...defaultExtensions, newExtensions]
102
- }
103
-
104
- watch(isDark, () => {
105
- const { extensions: configuredExtensions } = parameters
106
-
107
- if (!forceDarkMode) {
108
- reconfigureCodeMirror(configuredExtensions)
109
- }
110
- })
111
-
112
- // Removes CodeMirror.
113
- const destroyCodeMirror = () => {
114
- codeMirror.value?.destroy()
115
- }
116
-
117
- const setCodeMirrorContent = (newValue: string) => {
118
- if (!codeMirror.value) {
119
- return
120
- }
121
-
122
- value.value = newValue
123
-
124
- codeMirror.value.dispatch({
125
- changes: {
126
- from: 0,
127
- to: codeMirror.value.state.doc.length,
128
- insert: newValue,
129
- },
130
- selection: {
131
- anchor: Math.min(
132
- codeMirror.value.state.selection.main.anchor,
133
- newValue.length,
134
- ),
135
- },
136
- })
137
- }
138
-
139
- const reconfigureCodeMirror = (newExtensions: Extension[]) => {
140
- if (!codeMirror.value) {
141
- return
142
- }
143
-
144
- codeMirror.value.dispatch({
145
- effects: StateEffect.reconfigure.of(addDefaultExtensions(newExtensions)),
146
- })
147
- }
148
-
149
- const restartCodeMirror = (newExtensions: Extension[]) => {
150
- destroyCodeMirror()
151
- mountCodeMirror(newExtensions)
152
- }
153
-
154
- return {
155
- /**
156
- * The current value
157
- */
158
- value,
159
- /**
160
- * An empty reference used to mount CodeMirror when bound to the DOM.
161
- */
162
- codeMirrorRef,
163
- /**
164
- * The CodeMirror instance.
165
- */
166
- // @ts-ignore
167
- codeMirror,
168
- /**
169
- * Replaces the current content with the given value.
170
- */
171
- setCodeMirrorContent,
172
- /**
173
- * Reconfigure the used extensions.
174
- */
175
- reconfigureCodeMirror,
176
- /**
177
- * Restarts CodeMirror (destroy + mount)
178
- */
179
- restartCodeMirror,
180
- }
181
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { CodeMirror } from './components/CodeMirror'
2
- export * from './hooks/useCodeMirror'
@@ -1,77 +0,0 @@
1
- import { tags as t } from '@lezer/highlight'
2
- import { createTheme } from '@uiw/codemirror-themes'
3
-
4
- export const lightTheme = createTheme({
5
- theme: 'light',
6
- settings: {
7
- background: 'var(--theme-background-2)',
8
- foreground: 'var(--theme-color-1)',
9
- caret: '#93abdc',
10
- selection: '#e3dcce',
11
- selectionMatch: '#e3dcce',
12
- gutterBackground: 'var(--theme-background-2)',
13
- gutterForeground: 'var(--theme-color-2)',
14
- gutterBorder: 'transparent',
15
- lineHighlight: '#EFEFEF',
16
- fontFamily: 'var(--theme-font-code)',
17
- },
18
- styles: [
19
- { tag: [t.standard(t.tagName), t.tagName], color: '#116329' },
20
- { tag: [t.comment, t.bracket], color: '#6a737d' },
21
- { tag: [t.className, t.propertyName], color: '#6f42c1' },
22
- {
23
- tag: [t.variableName, t.attributeName, t.number, t.operator],
24
- color: '#005cc5',
25
- },
26
- {
27
- tag: [t.keyword, t.typeName, t.typeOperator, t.typeName],
28
- color: '#d73a49',
29
- },
30
- { tag: [t.string, t.meta, t.regexp], color: '#032f62' },
31
- { tag: [t.name, t.quote], color: '#22863a' },
32
- { tag: [t.heading], color: '#24292e', fontWeight: 'bold' },
33
- { tag: [t.emphasis], color: '#24292e', fontStyle: 'italic' },
34
- { tag: [t.deleted], color: '#b31d28', backgroundColor: 'ffeef0' },
35
- { tag: [t.atom, t.bool, t.special(t.variableName)], color: '#e36209' },
36
- { tag: [t.url, t.escape, t.regexp, t.link], color: '#032f62' },
37
- { tag: t.link, textDecoration: 'underline' },
38
- { tag: t.strikethrough, textDecoration: 'line-through' },
39
- { tag: t.invalid, color: '#cb2431' },
40
- ],
41
- })
42
-
43
- export const darkTheme = createTheme({
44
- theme: 'dark',
45
- settings: {
46
- background: 'var(--theme-background-2)',
47
- foreground: 'var(--theme-color-1)',
48
- caret: '#ffad5c',
49
- selection: 'rgba(255, 255, 255, 0.1)',
50
- gutterBackground: 'var(--theme-background-2)',
51
- gutterForeground: 'var(--theme-color-2)',
52
- lineHighlight: '#36334280',
53
- fontFamily: 'var(--theme-font-code)',
54
- },
55
- styles: [
56
- { tag: [t.standard(t.tagName), t.tagName], color: '#7ee787' },
57
- { tag: [t.comment, t.bracket], color: '#8b949e' },
58
- { tag: [t.className, t.propertyName], color: '#d2a8ff' },
59
- {
60
- tag: [t.variableName, t.attributeName, t.number, t.operator],
61
- color: '#79c0ff',
62
- },
63
- {
64
- tag: [t.keyword, t.typeName, t.typeOperator, t.typeName],
65
- color: '#ff7b72',
66
- },
67
- { tag: [t.string, t.meta, t.regexp], color: '#a5d6ff' },
68
- { tag: [t.name, t.quote], color: '#7ee787' },
69
- { tag: [t.heading], color: '#d2a8ff', fontWeight: 'bold' },
70
- { tag: [t.emphasis], color: '#d2a8ff', fontStyle: 'italic' },
71
- { tag: [t.deleted], color: '#ffdcd7', backgroundColor: 'ffeef0' },
72
- { tag: [t.atom, t.bool, t.special(t.variableName)], color: '#ffab70' },
73
- { tag: t.link, textDecoration: 'underline' },
74
- { tag: t.strikethrough, textDecoration: 'line-through' },
75
- { tag: t.invalid, color: '#f97583' },
76
- ],
77
- })