Skip to content

Commit fe0d33e

Browse files
committed
feat: properly configure monaco editors
1 parent c47f3d4 commit fe0d33e

File tree

7 files changed

+161
-95
lines changed

7 files changed

+161
-95
lines changed

docs/.vuepress/components/Demo/Demo.vue

+53-87
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<section>
33
<MonacoEditor
44
language="json"
5-
:value="jsonData"
5+
v-model="state.jsonData"
66
id="json-list-monaco-editor"
77
file-name="list.json"
88
file-description="list of items to search"
@@ -13,16 +13,16 @@
1313
<input
1414
type="text"
1515
class="search-section-input"
16-
v-model="searchPattern"
16+
v-model="state.searchPattern"
1717
@keyup="onSearchPatternKeyUp"
1818
placeholder="Search..."
1919
/>
2020
</section>
2121

2222
<section>
2323
<MonacoEditor
24-
language="typescript"
25-
:value="mainJsData"
24+
language="javascript"
25+
v-model="state.mainJsData"
2626
id="main-monaco-editor"
2727
file-name="main.js"
2828
file-description="entry module"
@@ -32,13 +32,13 @@
3232
<section class="monaco-editor-results">
3333
<MonacoEditor
3434
language="json"
35-
:value="resultsData"
35+
v-model="state.resultsData"
3636
id="main-monaco-editor"
3737
file-name="Results:"
3838
:file-description="
39-
isNullish(count) || isNullish(searchTime)
39+
isNullish(state.count) || isNullish(state.searchTime)
4040
? ''
41-
: 'found ' + count + ' in ' + searchTime + 'ms'
41+
: 'found ' + state.count + ' in ' + state.searchTime + 'ms'
4242
"
4343
readonly
4444
></MonacoEditor>
@@ -47,13 +47,23 @@
4747

4848
<script setup lang="ts">
4949
import { Stopwatch } from '@sapphire/stopwatch'
50-
import { ref } from 'vue'
50+
import { reactive } from 'vue'
51+
import type FuseTypes from '../../../../dist/fuse'
5152
import Fuse from '../../../../dist/fuse.esm.js'
5253
import Books from './books.js'
5354
import MonacoEditor from './MonacoEditor.vue'
5455
55-
const searchPattern = ref('')
56-
const fuseSearchOptions = ref({
56+
interface State {
57+
searchPattern: string
58+
jsonData: string
59+
mainJsData: string
60+
resultsData: string
61+
count: number | null
62+
searchTime: number | null
63+
fuseSearchOptions: FuseTypes.IFuseOptions<never>
64+
}
65+
66+
const defaultFuseSearchOptions: FuseTypes.IFuseOptions<never> = {
5767
isCaseSensitive: false,
5868
includeScore: false,
5969
shouldSort: true,
@@ -66,15 +76,21 @@ const fuseSearchOptions = ref({
6676
useExtendedSearch: false,
6777
ignoreLocation: false,
6878
ignoreFieldNorm: false,
69-
fieldNormWeight: 1
70-
})
79+
fieldNormWeight: 1,
80+
keys: ['title', 'author.firstName']
81+
}
7182
72-
let codify = () => {
83+
let codify = (
84+
searchPattern: string,
85+
fuseSearchOptions: FuseTypes.IFuseOptions<never> = defaultFuseSearchOptions
86+
): string => {
7387
return `
7488
const Fuse = require('fuse.js');
7589
7690
const fuseOptions = {
77-
${Object.entries(fuseSearchOptions).map(([key, value]) => `\t// ${key}: ${value},`).join('\n')}
91+
${Object.entries(fuseSearchOptions)
92+
.map(([key, value]) => `\t// ${key}: ${value},`)
93+
.join('\n')}
7894
\tkeys: [
7995
\t\t"title",
8096
\t\t"author.firstName"
@@ -84,105 +100,55 @@ ${Object.entries(fuseSearchOptions).map(([key, value]) => `\t// ${key}: ${value}
84100
const fuse = new Fuse(list, fuseOptions);
85101
86102
// Change the pattern
87-
const pattern = "${searchPattern.value}"
103+
const searchPattern = "${searchPattern}"
88104
89-
return fuse.search(pattern)`
105+
return fuse.search(searchPattern)`
90106
}
91107
108+
const state = reactive<State>({
109+
searchPattern: '',
110+
jsonData: JSON.stringify(Books, null, 2),
111+
mainJsData: codify(''),
112+
resultsData: JSON.stringify({}, null, 2),
113+
count: null,
114+
searchTime: null,
115+
fuseSearchOptions: defaultFuseSearchOptions
116+
})
117+
92118
const isNullish = <T>(
93119
value: null | undefined | T
94120
): value is null | undefined => {
95121
return value === null || value === undefined
96122
}
97123
98-
const jsonData = ref(JSON.stringify(Books, null, 2))
99-
const mainJsData = ref(codify())
100-
const resultsData = ref(JSON.stringify({}, null, 2))
101-
const count = ref<number | null>(null)
102-
const searchTime = ref<number | null>(null)
103-
104-
console.log('>>>>', resultsData.value)
105-
106124
function onSearchPatternKeyUp() {
107-
mainJsData.value = codify()
125+
state.mainJsData = codify(state.searchPattern, state.fuseSearchOptions)
108126
109127
doFuseSearch()
110128
}
111129
112130
function doFuseSearch() {
113131
try {
114-
const fuseOptions = {
115-
// isCaseSensitive: false,
116-
// includeScore: false,
117-
// shouldSort: true,
118-
// includeMatches: false,
119-
// findAllMatches: false,
120-
// minMatchCharLength: 1,
121-
// location: 0,
122-
// threshold: 0.6,
123-
// distance: 100,
124-
// useExtendedSearch: false,
125-
// ignoreLocation: false,
126-
// ignoreFieldNorm: false,
127-
// fieldNormWeight: 1,
132+
const fuseOptions: FuseTypes.IFuseOptions<never> = {
133+
...state.fuseSearchOptions,
128134
keys: ['title', 'author.firstName']
129135
}
130136
131-
const fuse = new Fuse(JSON.parse(jsonData.value), fuseOptions)
137+
const fuse = new Fuse(JSON.parse(state.jsonData), state.fuseSearchOptions)
132138
133139
const stopwatch = new Stopwatch()
134140
135-
const result = fuse.search(searchPattern.value)
141+
const result = fuse.search(state.searchPattern)
136142
137-
count.value = result.length
138-
searchTime.value = Math.floor(stopwatch.stop().duration)
139-
resultsData.value = JSON.stringify(result, null, 2)
143+
state.count = result.length
144+
state.searchTime = Math.floor(stopwatch.stop().duration)
145+
state.resultsData = JSON.stringify(result, null, 2)
140146
} catch {
141-
count.value = null
142-
searchTime.value = null
143-
resultsData.value = JSON.stringify({}, null, 2)
147+
state.count = null
148+
state.searchTime = null
149+
state.resultsData = JSON.stringify({}, null, 2)
144150
}
145151
}
146-
147-
// function onCmCodeChange(newCode) {
148-
// code.value = newCode
149-
// try {
150-
// parse()
151-
// update()
152-
// } catch (err) {}
153-
// }
154-
155-
// function onCmListChange(newCode) {
156-
// try {
157-
// list.value = eval(newCode)
158-
// listErrorMessage.value = null
159-
// hasErrors.value = !!codeErrorMessage.value
160-
// update()
161-
// } catch (err) {
162-
// listErrorMessage.value = err
163-
// hasErrors.value = true
164-
// outputHtml.value = ''
165-
// throw err
166-
// }
167-
// }
168-
169-
// function update() {
170-
// if (hasErrors.value) {
171-
// return
172-
// }
173-
// const html = Prism.highlight(
174-
// JSON.stringify(result.value, null, 2),
175-
// Prism.languages.json,
176-
// 'json'
177-
// )
178-
// count.value = result.value.length
179-
// outputHtml.value = html
180-
// }
181-
182-
// onMounted(() => {
183-
// // parse()
184-
// // update()
185-
// })
186152
</script>
187153

188154
<style scoped lang="css">

docs/.vuepress/components/Demo/MonacoEditor.vue

+61-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,63 @@
11
<script setup lang="ts">
2-
import * as monaco from 'monaco-editor'
3-
import { defineProps, onMounted, ref } from 'vue'
2+
import * as Monaco from 'monaco-editor'
3+
import { computed, defineProps, onMounted, ref, watch } from 'vue'
4+
import loader from '@monaco-editor/loader';
5+
6+
interface Emits {
7+
(event: 'update:modelValue', value: string): void
8+
(event: 'load', editor: Monaco.editor.IStandaloneCodeEditor): void
9+
}
410
5-
const editorRef = ref()
611
const props = defineProps<{
712
language: string
8-
value: any
13+
modelValue: string
914
id: string
1015
fileName: string
1116
fileDescription: string
1217
readonly?: boolean
1318
}>()
1419
20+
const loadedMonaco = await loader.init();
21+
22+
const emit = defineEmits<Emits>()
23+
const isLoading = ref(true)
24+
const lang = computed(() => props.language)
25+
const editorElement = ref<HTMLDivElement>()
26+
const monaco = ref(loadedMonaco)
27+
28+
let editor: Monaco.editor.IStandaloneCodeEditor
29+
let model: Monaco.editor.ITextModel
30+
const editorRef = ref()
31+
32+
watch(
33+
() => props.modelValue,
34+
() => {
35+
if (editor?.getValue() !== props.modelValue) {
36+
editor?.setValue(props.modelValue)
37+
}
38+
}
39+
)
40+
41+
watch(
42+
() => props.language,
43+
() => {
44+
if (model) {
45+
model.dispose()
46+
}
47+
model = monaco.value.editor.createModel(props.modelValue, lang.value)
48+
editor?.setModel(model)
49+
}
50+
)
51+
52+
defineExpose({
53+
/**
54+
* Monaco editor instance
55+
*/
56+
$editor: editorRef
57+
})
58+
1559
onMounted(() => {
16-
monaco.editor.create(editorRef.value, {
17-
value: props.value,
60+
editor = monaco.value.editor.create(editorElement.value, {
1861
language: props.language,
1962
automaticLayout: true,
2063
selectOnLineNumbers: true,
@@ -49,6 +92,15 @@ onMounted(() => {
4992
contextmenu: false
5093
})
5194
})
95+
96+
editorRef.value = editor
97+
model = monaco.value.editor.createModel(props.modelValue, lang.value)
98+
editor.setModel(model)
99+
editor.onDidChangeModelContent(() => {
100+
emit('update:modelValue', editor.getValue())
101+
})
102+
isLoading.value = false
103+
emit('load', editor)
52104
})
53105
</script>
54106

@@ -57,7 +109,9 @@ onMounted(() => {
57109
<div>{{ props.fileName }}</div>
58110
<div>{{ props.fileDescription }}</div>
59111
</div>
60-
<div :id="props.id" class="editor" ref="editorRef"></div>
112+
<div :id="props.id" class="editor" ref="editorElement">
113+
<slot v-if="isLoading" />
114+
</div>
61115
</template>
62116

63117
<style scoped>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<template>
2+
<Suspense>
3+
<Demo />
4+
<template #fallback>Loading demo...</template>
5+
</Suspense>
6+
</template>
7+
8+
<script setup lang="ts">
9+
import Demo from '../Demo/Demo.vue'
10+
</script>

docs/.vuepress/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ function getPlugins(): PluginConfig {
106106
...getComponent('Stories'),
107107
...getComponent('Sponsors'),
108108
...getComponent('Demo'),
109+
...getComponent('SuspensefulDemo'),
109110
...getComponent('Team'),
110111
...getComponent('Jobs'),
111112
...getComponent('Donate'),

docs/demo.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
Play around with a live demo of Fuse.js. Have a look at the [options](api/options.html) to understand what they mean.
66

7-
<Demo />
7+
<SuspensefulDemo />
88

99
<Donate />

0 commit comments

Comments
 (0)