yh-codemirror 1.0.0 → 1.0.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/CodeMirror.vue +174 -10
- package/package.json +26 -25
package/CodeMirror.vue
CHANGED
|
@@ -1,16 +1,45 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="yh-code-mirror-container"
|
|
4
|
+
ref="YhCodemirrorContainer"
|
|
5
|
+
:style="codeMirrorStyle">
|
|
3
6
|
<div class="code-slot">
|
|
4
7
|
<slot name="pre-code"></slot>
|
|
5
8
|
</div>
|
|
6
|
-
<div
|
|
9
|
+
<div
|
|
10
|
+
class="codemirror-editor"
|
|
11
|
+
ref="codeMirrorEditorRef"
|
|
12
|
+
:style="codeMirrorEditorStyle"></div>
|
|
7
13
|
<div class="code-slot">
|
|
8
14
|
<slot name="next-code"></slot>
|
|
9
15
|
</div>
|
|
16
|
+
<div class="editor-operation-btn">
|
|
17
|
+
<i
|
|
18
|
+
title="全屏"
|
|
19
|
+
class="iconfont icon-fullscreen"
|
|
20
|
+
@click="fullscreen"></i>
|
|
21
|
+
<i
|
|
22
|
+
title="美化"
|
|
23
|
+
class="iconfont icon-magic-stick"
|
|
24
|
+
@click="onEditorBtnClick('beautify')"></i>
|
|
25
|
+
<i
|
|
26
|
+
title="全选"
|
|
27
|
+
class="iconfont icon-check-square"
|
|
28
|
+
@click="onEditorBtnClick('checkAll')"></i>
|
|
29
|
+
<i
|
|
30
|
+
title="复制"
|
|
31
|
+
class="iconfont icon-document-copy"
|
|
32
|
+
@click="onEditorBtnClick('copy')"></i>
|
|
33
|
+
<i
|
|
34
|
+
title="清空"
|
|
35
|
+
class="iconfont icon-clear"
|
|
36
|
+
@click="onEditorBtnClick('clear')"></i>
|
|
37
|
+
<slot name="operation-btn"></slot>
|
|
38
|
+
</div>
|
|
10
39
|
</div>
|
|
11
40
|
</template>
|
|
12
41
|
<script setup lang="ts">
|
|
13
|
-
import { ref, onMounted } from "vue";
|
|
42
|
+
import { ref, onMounted, toRaw } from "vue";
|
|
14
43
|
// @ts-ignore
|
|
15
44
|
import type { Extension } from "codemirror";
|
|
16
45
|
import { EditorView, basicSetup } from "codemirror";
|
|
@@ -19,17 +48,35 @@ import { EditorState, EditorSelection } from "@codemirror/state";
|
|
|
19
48
|
import { javascriptLanguage } from "@codemirror/lang-javascript";
|
|
20
49
|
import { solarizedDark } from "cm6-theme-solarized-dark";
|
|
21
50
|
import { getCodeLanguagePlugin } from "./util";
|
|
22
|
-
import { watch } from "vue";
|
|
51
|
+
import { watch, computed } from "vue";
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
import { js_beautify } from "js-beautify";
|
|
54
|
+
import { ElMessage } from "element-plus";
|
|
55
|
+
|
|
56
|
+
const YhCodemirrorContainer = ref();
|
|
57
|
+
function fullscreen() {
|
|
58
|
+
if (document.fullscreenElement && document.fullscreenElement === YhCodemirrorContainer.value) {
|
|
59
|
+
document.exitFullscreen();
|
|
60
|
+
} else {
|
|
61
|
+
YhCodemirrorContainer.value.requestFullscreen();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
23
64
|
|
|
24
65
|
const codeMirrorEditorRef = ref();
|
|
66
|
+
|
|
25
67
|
let view: null | EditorView = null;
|
|
26
68
|
let state: null | EditorState = null;
|
|
69
|
+
// js-beautify 自定义配置
|
|
70
|
+
const codeBeautifyConfig = {
|
|
71
|
+
indent_size: 2,
|
|
72
|
+
};
|
|
27
73
|
|
|
28
74
|
const props = withDefaults(
|
|
29
75
|
defineProps<{
|
|
30
76
|
modelValue: string;
|
|
31
77
|
language?: string | string[];
|
|
32
78
|
autocomplete?: any;
|
|
79
|
+
height?: number;
|
|
33
80
|
}>(),
|
|
34
81
|
{
|
|
35
82
|
modelValue: "",
|
|
@@ -38,12 +85,31 @@ const props = withDefaults(
|
|
|
38
85
|
}
|
|
39
86
|
);
|
|
40
87
|
|
|
88
|
+
const codeMirrorStyle = computed(() => {
|
|
89
|
+
let style: any = {};
|
|
90
|
+
if (props.height !== undefined && !isNaN(props.height)) {
|
|
91
|
+
style.height = `${props.height}px`;
|
|
92
|
+
style.display = "flex";
|
|
93
|
+
style.flexDirection = "column";
|
|
94
|
+
}
|
|
95
|
+
return style;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const codeMirrorEditorStyle = computed(() => {
|
|
99
|
+
let style: any = {};
|
|
100
|
+
if (props.height !== undefined && !isNaN(props.height)) {
|
|
101
|
+
style.flex = `1`;
|
|
102
|
+
style.overflow = "auto";
|
|
103
|
+
}
|
|
104
|
+
return style;
|
|
105
|
+
});
|
|
106
|
+
|
|
41
107
|
watch(
|
|
42
108
|
() => props.modelValue,
|
|
43
109
|
(val) => {
|
|
44
|
-
if (state) {
|
|
45
|
-
let end = state.doc.length;
|
|
46
|
-
|
|
110
|
+
if (view && state && val != view.state.doc.toString()) {
|
|
111
|
+
let end = view.state.doc.toString().length;
|
|
112
|
+
view.dispatch({
|
|
47
113
|
changes: [
|
|
48
114
|
{
|
|
49
115
|
from: 0,
|
|
@@ -56,7 +122,58 @@ watch(
|
|
|
56
122
|
}
|
|
57
123
|
);
|
|
58
124
|
|
|
59
|
-
const emits = defineEmits(["update:
|
|
125
|
+
const emits = defineEmits(["update:modelValue"]);
|
|
126
|
+
|
|
127
|
+
// 代码编辑器操作按钮
|
|
128
|
+
const onEditorBtnClick = (type) => {
|
|
129
|
+
if (view) {
|
|
130
|
+
const state = toRaw(view.state);
|
|
131
|
+
const pos = state.doc.toString().length;
|
|
132
|
+
if (type == "beautify") {
|
|
133
|
+
const beautifyCode = js_beautify(props.modelValue, codeBeautifyConfig);
|
|
134
|
+
view.dispatch({
|
|
135
|
+
changes: [
|
|
136
|
+
{
|
|
137
|
+
from: 0,
|
|
138
|
+
to: pos,
|
|
139
|
+
insert: beautifyCode,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
} else if (type == "checkAll") {
|
|
144
|
+
const tr = state.update({
|
|
145
|
+
// selection: EditorSelection.cursor(pos), // 设置光标
|
|
146
|
+
selection: EditorSelection.range(0, pos),
|
|
147
|
+
scrollIntoView: true,
|
|
148
|
+
});
|
|
149
|
+
view.dispatch(tr);
|
|
150
|
+
} else if (type == "copy") {
|
|
151
|
+
let selectedText = "";
|
|
152
|
+
if (state.selection.ranges.some((range) => !range.empty)) {
|
|
153
|
+
const selection = state.selection.ranges[0];
|
|
154
|
+
selectedText = state.sliceDoc(selection.from, selection.to);
|
|
155
|
+
} else {
|
|
156
|
+
selectedText = state.doc.toString();
|
|
157
|
+
}
|
|
158
|
+
navigator.clipboard.writeText(selectedText);
|
|
159
|
+
ElMessage({
|
|
160
|
+
message: "复制成功!",
|
|
161
|
+
type: "success",
|
|
162
|
+
});
|
|
163
|
+
} else if (type == "clear") {
|
|
164
|
+
view.dispatch({
|
|
165
|
+
changes: [
|
|
166
|
+
{
|
|
167
|
+
from: 0,
|
|
168
|
+
to: pos,
|
|
169
|
+
insert: "",
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
view.focus();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
60
177
|
|
|
61
178
|
onMounted(() => {
|
|
62
179
|
const extensions: Extension[] = [
|
|
@@ -64,7 +181,9 @@ onMounted(() => {
|
|
|
64
181
|
solarizedDark,
|
|
65
182
|
EditorView.lineWrapping,
|
|
66
183
|
EditorView.updateListener.of((v: ViewUpdate) => {
|
|
67
|
-
|
|
184
|
+
if (v.docChanged) {
|
|
185
|
+
emits("update:modelValue", v.state.doc.toString());
|
|
186
|
+
}
|
|
68
187
|
}),
|
|
69
188
|
];
|
|
70
189
|
const language = props.language;
|
|
@@ -107,13 +226,58 @@ onMounted(() => {
|
|
|
107
226
|
<style lang="scss">
|
|
108
227
|
.yh-code-mirror-container {
|
|
109
228
|
width: 100%;
|
|
229
|
+
position: relative;
|
|
110
230
|
.code-slot {
|
|
111
231
|
width: 100%;
|
|
232
|
+
font-family: "Fira Code", "Roboto Mono", Consolas, "Microsoft Yahei";
|
|
112
233
|
line-height: 25px;
|
|
113
|
-
font-size:
|
|
234
|
+
font-size: 16px;
|
|
114
235
|
padding-left: 29.77px;
|
|
115
236
|
color: #ffffff;
|
|
116
237
|
background-color: #173541;
|
|
117
238
|
}
|
|
239
|
+
.cm-editor {
|
|
240
|
+
.cm-line {
|
|
241
|
+
font-size: 16px;
|
|
242
|
+
line-height: 25px;
|
|
243
|
+
font-family: "Fira Code", "Roboto Mono", Consolas, "Microsoft Yahei";
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
.codemirror-editor {
|
|
247
|
+
&::-webkit-scrollbar {
|
|
248
|
+
width: 6px;
|
|
249
|
+
height: 6px;
|
|
250
|
+
background-color: #173541;
|
|
251
|
+
}
|
|
252
|
+
&::-webkit-scrollbar-thumb {
|
|
253
|
+
background-color: #f5f5f5;
|
|
254
|
+
&:hover {
|
|
255
|
+
background-color: #fff;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
.editor-operation-btn {
|
|
260
|
+
position: absolute;
|
|
261
|
+
bottom: 1px;
|
|
262
|
+
right: 1px;
|
|
263
|
+
padding: 0 3px;
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
border-radius: 3px;
|
|
267
|
+
opacity: 0.5;
|
|
268
|
+
background: #409eff;
|
|
269
|
+
transition: all 0.3s ease;
|
|
270
|
+
i {
|
|
271
|
+
font-size: 16px;
|
|
272
|
+
color: #fff;
|
|
273
|
+
margin: 0 5px;
|
|
274
|
+
cursor: pointer;
|
|
275
|
+
line-height: 24px;
|
|
276
|
+
}
|
|
277
|
+
&:hover {
|
|
278
|
+
opacity: 1;
|
|
279
|
+
background: #409eff;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
118
282
|
}
|
|
119
283
|
</style>
|
package/package.json
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "yh-codemirror",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "wraper codemirror with vue3",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"pub": "npm publish --registry https://registry.npmjs.org/ --no-git-checks && npm publish --registry https://packages.aliyun.com/60765e0161a945067837bb5f/npm/npm-registry/ --no-git-checks"
|
|
8
|
-
},
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"@codemirror/autocomplete": "^6.
|
|
11
|
-
"@codemirror/lang-css": "^6.2.1",
|
|
12
|
-
"@codemirror/lang-java": "^6.0.1",
|
|
13
|
-
"@codemirror/lang-javascript": "^6.
|
|
14
|
-
"@codemirror/lang-sql": "^6.
|
|
15
|
-
"@codemirror/lang-html": "^6.4.9",
|
|
16
|
-
"@codemirror/language": "^6.
|
|
17
|
-
"@codemirror/view": "^6.
|
|
18
|
-
"codemirror": "^6.0.1"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"vue": "
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "yh-codemirror",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "wraper codemirror with vue3",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"pub": "npm publish --registry https://registry.npmjs.org/ --no-git-checks && npm publish --registry https://packages.aliyun.com/60765e0161a945067837bb5f/npm/npm-registry/ --no-git-checks"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@codemirror/autocomplete": "^6.16.3",
|
|
11
|
+
"@codemirror/lang-css": "^6.2.1",
|
|
12
|
+
"@codemirror/lang-java": "^6.0.1",
|
|
13
|
+
"@codemirror/lang-javascript": "^6.2.2",
|
|
14
|
+
"@codemirror/lang-sql": "^6.7.0",
|
|
15
|
+
"@codemirror/lang-html": "^6.4.9",
|
|
16
|
+
"@codemirror/language": "^6.10.2",
|
|
17
|
+
"@codemirror/view": "^6.28.2",
|
|
18
|
+
"codemirror": "^6.0.1",
|
|
19
|
+
"js-beautify": "^1.15.1"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"vue-i18n": "9.8.0",
|
|
23
|
+
"vue": "3.2.47",
|
|
24
|
+
"element-plus": "2.3.8"
|
|
25
|
+
},
|
|
26
|
+
"author": "Liubin"
|
|
26
27
|
}
|