@live-change/wysiwyg-frontend 0.2.10 → 0.2.11

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.
@@ -35,7 +35,7 @@
35
35
 
36
36
  const emptyContent = {
37
37
  "type": "doc",
38
- "content": [].concat(new Array(2).fill(
38
+ "content": [
39
39
  {
40
40
  "type": "paragraph",
41
41
  "content": [
@@ -53,8 +53,66 @@
53
53
  "text": "est"
54
54
  }
55
55
  ]
56
+ },
57
+ {
58
+ "type": "component",
59
+ "attrs": {
60
+ "is": "card",
61
+ "attrs": {
62
+ "class": "surface-card px-3 shadow-2 w-full f p-2"
63
+ }
64
+ },
65
+ "content": [
66
+ {
67
+ "type": "paragraph",
68
+ "content": [
69
+ {
70
+ "type": "text",
71
+ "text": "test"
72
+ }
73
+ ]
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "type": "paragraph",
79
+ "content": [
80
+ {
81
+ "type": "text",
82
+ "text": "test"
83
+ },
84
+ {
85
+ "type": "text",
86
+ "marks": [
87
+ {
88
+ "type": "bold"
89
+ }
90
+ ],
91
+ "text": "est"
92
+ }
93
+ ]
94
+ },
95
+ {
96
+ "type": "component",
97
+ "attrs": {
98
+ "is": "card",
99
+ "attrs": {
100
+ "class": "surface-card py-1 px-3 shadow-2 w-full"
101
+ }
102
+ },
103
+ "content": [
104
+ {
105
+ "type": "paragraph",
106
+ "content": [
107
+ {
108
+ "type": "text",
109
+ "text": "test"
110
+ }
111
+ ]
112
+ }
113
+ ]
56
114
  }
57
- ))
115
+ ]
58
116
  }
59
117
 
60
118
  </script>
@@ -1,22 +1,81 @@
1
1
  <template>
2
2
  <node-view-wrapper>
3
- <ComponentEditor>
3
+ <ComponentEditor v-bind="{ ...attrs, class: ['relative', attrs.class] }">
4
4
  <node-view-content class="content" />
5
+ <div class="absolute top-0 right-0 pr-4 max-h-0 align-items-center z-5 edit-buttons ">
6
+ <Button icon="pi pi-eye"
7
+ :class="[
8
+ 'p-button p-button-icon-only p-button-rounded mr-0',
9
+ selectedEditor != 'style' ? 'p-button-success' : 'p-button-secondary'
10
+ ]"
11
+ style="transform: scale(0.8)"
12
+ @click="(event) => toggleEditor('style', event)" />
13
+ <Button icon="pi pi-cog"
14
+ :class="[
15
+ 'p-button p-button-icon-only p-button-rounded mr-0',
16
+ selectedEditor != 'settings' ? 'p-button-warning' : 'p-button-secondary'
17
+ ]"
18
+ style="transform: scale(0.8)"
19
+ @click="(event) => toggleEditor('settings', event)"/>
20
+ <Button icon="pi pi-trash"
21
+ class="p-button p-button-icon-only p-button-rounded p-button-danger"
22
+ style="transform: scale(0.8)"
23
+ @click="() => props.deleteNode()" />
24
+ </div>
25
+ <div class="absolute pointer-events-none border-2 border-dashed z-9"
26
+ :class="selectedEditor == 'style' ? 'border-blue-400' : 'border-yellow-400'"
27
+ style="top: -10px; left: -10px; width: auto; height: auto; right: -10px; bottom: -10px"
28
+ v-if="selectedEditor"></div>
5
29
  </ComponentEditor>
6
30
  </node-view-wrapper>
7
31
  </template>
8
32
 
9
33
  <script setup>
34
+ import Button from "primevue/button"
35
+
10
36
  import { NodeViewContent, nodeViewProps, NodeViewWrapper } from '@tiptap/vue-3'
11
37
  import components from "./components.js";
12
38
 
39
+ import { inject, computed, getCurrentInstance } from "vue"
40
+
13
41
  const props = defineProps(nodeViewProps)
14
42
 
15
- const { is, attrs } = props.node.attrs
43
+ const is = computed(() => props.node.attrs.is)
44
+ const attrs = computed(() => props.node.attrs.attrs)
45
+
46
+ const ComponentEditor = components[props.node.attrs.is].editor
47
+
48
+ const uid = getCurrentInstance().uid
49
+
50
+ const nodeControl = computed(() => ({
51
+ uid,
52
+ updateAttributes: props.updateAttributes,
53
+ deleteNode: props.deleteNode,
54
+ is: props.node.attrs.is,
55
+ attrs: props.node.attrs.attrs
56
+ }))
57
+
58
+ const editorControl = inject("componentEditorControl")
59
+
60
+ function toggleEditor(type, event) {
61
+ editorControl.toggleEditor(type, nodeControl, event)
62
+ }
63
+
64
+ const selectedEditor = computed(() =>{
65
+ console.log('EC', editorControl.componentControl.value?.nodeControl?.value.uid, uid)
66
+ return editorControl.componentControl.value?.nodeControl?.value?.uid === uid
67
+ ? editorControl.componentControl.value?.type
68
+ : null
69
+ })
16
70
 
17
- const ComponentEditor = components[is].editor
18
71
  </script>
19
72
 
20
- <style scoped>
73
+ <style lang="scss">
74
+ .edit-buttons {
75
+ display: none;
76
+ }
77
+ .show-edit-buttons .edit-buttons {
78
+ display: flex;
79
+ }
21
80
 
22
81
  </style>
@@ -10,7 +10,7 @@
10
10
  <!-- <div v-for="i in [1,2,3,4,5,6,7,8,9,10]">-->
11
11
  <div v-for="([ name, component ], index) in searchResults" :key="name"
12
12
  class="flex flex-wrap relative cursor-pointer hover:surface-100"
13
- @click="() => emit('selected', name)" >
13
+ @click="() => emit('selected', name, component)" >
14
14
  <div class="w-3 ml-2 mr-2 my-1" style="aspect-ratio: 1/1">
15
15
  <div class="pointer-events-none w-6 absolute p-1"
16
16
  style="aspect-ratio: 1/1; transform: scale(0.5); transform-origin: 0 0;">
@@ -66,6 +66,7 @@
66
66
  "attrs": {
67
67
  "is": name,
68
68
  "attrs": {
69
+ ...component.initialAttrs,
69
70
  ...component.previewAttrs
70
71
  }
71
72
  },
@@ -3,21 +3,42 @@
3
3
  <slot v-if="editor" name="menu" :editor="editor" :saveState="saveState">
4
4
  <EditorMenu :editor="editor" :config="config" :saveState="saveState">
5
5
  <template #before="scope"><slot name="beforeMenu" v-bind="{ ...scope, editor, saveState }" /></template>
6
- <template #after="scope"><slot name="afterMenu" v-bind="{ ...scope, editor, saveState }" /></template>
7
6
  <template #begin="scope"><slot name="menuBegin" v-bind="{ ...scope, editor, saveState }" /></template>
8
- <template #end="scope"><slot name="menuEnd" v-bind="{ ...scope, editor, saveState }" /></template>
7
+ <template #end="scope">
8
+ <slot name="menuEnd" v-bind="{ ...scope, editor, saveState }" />
9
+ <Button v-if="config.nodes.component" label="Edit Buttons"
10
+ :class="[
11
+ 'p-button-sm p-button-primary inline-block mr-1 mb-1', { 'p-button-outlined': !editButtons }
12
+ ]"
13
+ @click="toggleEditButtons" />
14
+ </template>
15
+ <template #after="scope">
16
+ <div v-if="componentControl"
17
+ class="surface-card p-1 shadow-2 border-round">
18
+ <StyleEditor v-if="componentControl.type == 'style'" :nodeControl="componentControl.nodeControl"
19
+ :key="componentControl.uid" />
20
+ <SettingsEditor v-if="componentControl.type == 'settings'" :nodeControl="componentControl.nodeControl"
21
+ :key="componentControl.uid" />
22
+ </div>
23
+ <slot name="afterMenu" v-bind="{ ...scope, editor, saveState }" />
24
+ </template>
9
25
  </EditorMenu>
10
26
  </slot>
11
- <editor-content :editor="editor" class="content" />
27
+ <editor-content :editor="editor" :class="[content, { 'show-edit-buttons': editButtons }]" />
12
28
  </div>
13
29
  </template>
14
30
 
15
31
  <script setup>
32
+ import Button from "primevue/button"
33
+
34
+ import StyleEditor from "./StyleEditor.vue";
35
+ import SettingsEditor from "./SettingsEditor.vue";
16
36
 
17
37
  import { useEditor, EditorContent } from '@tiptap/vue-3'
18
38
  import { History } from '@tiptap/extension-history'
19
39
  import {
20
- ref, computed, watch, provide, defineEmits, defineProps, getCurrentInstance, onUnmounted, inject, onMounted
40
+ ref, computed, watch, provide, defineEmits, defineProps, getCurrentInstance, onUnmounted, inject, onMounted,
41
+ shallowRef
21
42
  } from 'vue'
22
43
  import { toRefs, useDebounceFn } from '@vueuse/core'
23
44
  import EditorMenu from "./EditorMenu.vue"
@@ -139,6 +160,14 @@
139
160
  ? serializeSchema(editor.view.state.schema.spec)
140
161
  : getSchemaSpecFromConfig(props.config)
141
162
 
163
+ const editButtons = ref(true)
164
+ function toggleEditButtons() {
165
+ editButtons.value = !editButtons.value
166
+ if(!editButtons.value) {
167
+ componentControl.value = null
168
+ }
169
+ }
170
+
142
171
  if(typeof window != 'undefined') window.schemaSpecJson = JSON.stringify(schemaSpec, null, " ")
143
172
 
144
173
  async function save() {
@@ -163,6 +192,20 @@
163
192
  }
164
193
  }
165
194
 
195
+ const componentControl = shallowRef()
196
+ provide('componentEditorControl', {
197
+ componentControl,
198
+ toggleEditor(type, nodeControl, event) {
199
+ const uid = nodeControl.value.uid
200
+ if(componentControl.value && componentControl.value.uid == uid && componentControl.value.type == type) {
201
+ componentControl.value = null
202
+ } else {
203
+ console.log("SET COMPONENT CONTROL", nodeControl.value)
204
+ componentControl.value = { type, nodeControl, uid }
205
+ }
206
+ }
207
+ })
208
+
166
209
  </script>
167
210
 
168
211
  <style scoped>
@@ -76,8 +76,8 @@
76
76
  </FileInput>
77
77
  <!-- </div>-->
78
78
 
79
- <Button v-if="config.nodes.component" label="Insert Component"
80
- class="p-button-sm p-button-primary inline-block mr-1 mb-1"
79
+ <Button v-if="config.nodes.component" label="Component"
80
+ class="p-button-sm p-button-primary p-button-outlined inline-block mr-1 mb-1"
81
81
  @click="openComponentMenu" />
82
82
 
83
83
  <span v-if="saveState"
@@ -100,7 +100,7 @@
100
100
  </div>
101
101
  <slot name="after" />
102
102
  <OverlayPanel ref="insertComponentOverlay" style="width: 450px" :breakpoints="{'960px': '75vw'}">
103
- <ComponentsMenu :config="config" @selected="c => handleComponentSelected(c)" />
103
+ <ComponentsMenu :config="config" @selected="(n,c) => handleComponentSelected(n,c)" />
104
104
  </OverlayPanel>
105
105
  <!-- <div class="surface-card p-1 shadow-2" style="width: 450px">
106
106
  <h3>components:</h3>
@@ -159,12 +159,13 @@
159
159
  function openComponentMenu(event) {
160
160
  insertComponentOverlay.value.show(event)
161
161
  }
162
- function handleComponentSelected(component) {
162
+ function handleComponentSelected(name, component) {
163
163
  insertComponentOverlay.value.hide()
164
164
  editor.value.chain().focus().insertContent({
165
165
  type: 'component',
166
166
  attrs: {
167
- is: component,
167
+ is: name,
168
+ attrs: component.initialAttrs
168
169
  },
169
170
  content: [
170
171
  { type: 'paragraph', content: [
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <div class="flex flex-row flex-wrap ">
3
+ <div v-for="type in paddingTypes"
4
+ class="flex flex-row align-items-center justify-content-start my-1"
5
+ style="width: 5.6em">
6
+ <label :for="'padding-'+type" class="mb-0 mr-1">{{ type }}</label>
7
+ <InputNumber v-if="props.modelValue[type] !== undefined"
8
+ :inputId="'padding-'+type"
9
+ class="p-inputtext-sm"
10
+ inputStyle="max-width: 1.7em;"
11
+ :modelValue="props.modelValue[type]"
12
+ @update:modelValue="value => updatePadding(type, value)"
13
+ mode="decimal"
14
+ showButtons :min="-1" :max="8" />
15
+ <Button v-else class="p-button p-button-icon-only p-button-rounded mr-0" icon="pi pi-plus"
16
+ @click="ev => updatePadding(type, 1)" />
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script setup>
22
+ import InputNumber from "primevue/inputnumber"
23
+ import Button from "primevue/button"
24
+
25
+ const props = defineProps({
26
+ modelValue: {
27
+ type: Object,
28
+ default: () => ({})
29
+ }
30
+ })
31
+ const emit = defineEmits(['update:modelValue'])
32
+
33
+ const paddingTypes = ['all', 'x', 'y', 'l', 'r', 't', 'b']
34
+
35
+ function updatePadding(type, value) {
36
+ console.log("UPDATE PADDING", type, value)
37
+ const newValue = { ...props.modelValue }
38
+ if(value < 0) {
39
+ delete newValue[type]
40
+ } else {
41
+ newValue[type] = value
42
+ }
43
+ emit('update:modelValue', newValue)
44
+ }
45
+ </script>
46
+
47
+ <style scoped>
48
+
49
+ </style>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <h2>Settings editor</h2>
3
+ </template>
4
+
5
+ <script setup>
6
+ </script>
7
+
8
+ <style scoped>
9
+
10
+ </style>
@@ -0,0 +1,179 @@
1
+ <template>
2
+ <!-- <pre>{{ JSON.stringify(classInfo, null, " ") }}</pre>-->
3
+ <div class="flex flex-column flex-wrap w-full">
4
+ <div v-if="editingPadding">
5
+ <div class="flex flex-row align-items-center mb-2">
6
+ <label class="mr-3" style="width: 4em">Padding:</label>
7
+ <PaddingEditor :modelValue="classInfo.padding"
8
+ @update:modelValue="p => handleClassInfoUpdate({ padding: p })" />
9
+ </div>
10
+ <div class="flex flex-row align-items-center">
11
+ <label class="mr-3" style="width: 4em">Margin:</label>
12
+ <PaddingEditor :modelValue="classInfo.margin"
13
+ @update:modelValue="p => handleClassInfoUpdate({ margin: p })" />
14
+ </div>
15
+ </div>
16
+ <div class="flex flex-column md:flex-row">
17
+ <div class="flex-1 mr-2 flex flex-column">
18
+ <div class="flex flex-row align-items-center flex-shrink-0">
19
+ <label class="my-2 flex-grow-1">Classes:</label>
20
+ <div class="flex flex-row align-items-center mr-4">
21
+ <i class="pi pi-arrows-alt" style="font-size: 1.2rem"></i>
22
+ <InputSwitch v-model="editingPadding" class="ml-2" />
23
+ </div>
24
+ </div>
25
+ <AutoComplete :modelValue="classInfo.list"
26
+ @update:modelValue="l => handleClassInfoUpdate({ list: l })"
27
+ :separator="/ /" :multiple="true" :suggestions="classSuggestions"
28
+ @complete="ev => searchClasses(ev)"
29
+ class="autocomplete-w-full flex-grow-1" />
30
+ </div>
31
+ <div class="flex-1 flex flex-column">
32
+ <div class="flex flex-row flex-shrink-0">
33
+ <label class="my-2 flex-grow-1">Style:</label>
34
+ </div>
35
+ <prism-editor v-if="isMounted"
36
+ class="style-editor p-inputtext flex-grow-1" :highlight="highlightCss"
37
+ :style="{ height: (nodeStyleLines * 1.35 + 1.1) + 'em' }"
38
+ :modelValue="nodeStyle" @update:modelValue="handleStyleUpdate"
39
+ :readonly="false" :line-numbers="nodeStyleLines > 1" />
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script setup>
46
+ import AutoComplete from "primevue/autocomplete"
47
+ import InputSwitch from 'primevue/inputswitch';
48
+
49
+ import PaddingEditor from "./PaddingEditor.vue"
50
+
51
+ import 'vue-prism-editor/dist/prismeditor.min.css'
52
+ import 'prismjs/themes/prism-coy.css'
53
+ import * as Prism from 'prismjs/components/prism-core'
54
+ import 'prismjs/components/prism-css'
55
+
56
+ import { PrismEditor } from 'vue-prism-editor'
57
+
58
+ import {ref, computed, watch, provide, defineEmits, defineProps, onMounted} from 'vue'
59
+ import { toRefs } from '@vueuse/core'
60
+
61
+ const isMounted = ref(false)
62
+ onMounted(() => isMounted.value = true)
63
+
64
+ const props = defineProps({
65
+ nodeControl: {
66
+ type: Object,
67
+ required: true
68
+ }
69
+ })
70
+
71
+ const { nodeControl } = toRefs(props)
72
+
73
+ const editingPadding = ref(false)
74
+
75
+ function extract(info, regex, setter) {
76
+ const rest = []
77
+ const list = info.list
78
+ for(let i = 0; i < list.length; i++) {
79
+ const match = list[i].match(regex)
80
+ if(match) setter(...match.slice(1))
81
+ else rest.push(list[i])
82
+ }
83
+ info.list = rest
84
+ }
85
+
86
+ function extractClasses(info) {
87
+ info.padding = { }
88
+ if(editingPadding.value) {
89
+ extract(info, /^p([xyltrb])?-(\d+)$/, (dir, size) => {
90
+ if (dir) info.padding[dir] = size
91
+ else info.padding.all = size
92
+ })
93
+ info.margin = {}
94
+ extract(info, /^m([xyltrb])?-(\d+)$/, (dir, size) => {
95
+ if (dir) info.margin[dir] = size
96
+ else info.margin.all = size
97
+ })
98
+ }
99
+ }
100
+ function recombinePadding(list, padding, prefix = 'p') {
101
+ if(padding.all !== undefined) list.push(`${prefix}-${padding.all}`)
102
+ if(padding.x !== undefined) list.push(`${prefix}x-${padding.x}`)
103
+ if(padding.y !== undefined) list.push(`${prefix}y-${padding.y}`)
104
+ if(padding.t !== undefined) list.push(`${prefix}t-${padding.t}`)
105
+ if(padding.r !== undefined) list.push(`${prefix}r-${padding.r}`)
106
+ if(padding.b !== undefined) list.push(`${prefix}b-${padding.b}`)
107
+ if(padding.l !== undefined) list.push(`${prefix}l-${padding.l}`)
108
+ }
109
+ function recombineClasses(info) {
110
+ const { padding, margin, list } = info
111
+ if(editingPadding.value) {
112
+ recombinePadding(list, padding, 'p')
113
+ recombinePadding(list, margin, 'm')
114
+ }
115
+ }
116
+
117
+ const insertableClasses = ['flex', 'flex-grow-1']
118
+ const nodeClass = computed(() => {
119
+ console.log("nodeControl", nodeControl.value)
120
+ return nodeControl.value.attrs.class
121
+ })
122
+ const classInfo = computed(() => {
123
+ const list = nodeClass.value ? nodeClass.value.split(' ') : []
124
+ const info = { list }
125
+ extractClasses(info)
126
+ return info
127
+ })
128
+ const classSuggestions = ref()
129
+ function searchClasses(event) {
130
+ const query = event.query.toLowerCase()
131
+ console.log("SEARCH CLASSES", query)
132
+ classSuggestions.value = [
133
+ ...(insertableClasses.find(c => c == event.query) ? [] : [event.query]),
134
+ ...(insertableClasses.filter((c) => {
135
+ return c.toLowerCase().startsWith(query)
136
+ }))
137
+ ]
138
+ }
139
+ function handleClassInfoUpdate(change) {
140
+ let info = JSON.parse(JSON.stringify(classInfo.value))
141
+ info = { ...info, ...change }
142
+ recombineClasses(info)
143
+ console.log("INFO", info)
144
+ nodeControl.value.updateAttributes({ attrs: {
145
+ ...nodeControl.value.attrs,
146
+ class: info.list.join(' ')
147
+ }})
148
+ }
149
+
150
+ const nodeStyle = computed(() => {
151
+ return nodeControl.value.attrs.style
152
+ })
153
+ const nodeStyleLines = computed(() => (nodeStyle.value || '').split('\n').length)
154
+ function highlightCss(code) {
155
+ return Prism.highlight(code, Prism.languages.css, "css")
156
+ }
157
+ function handleStyleUpdate(style) {
158
+ console.log("NC", nodeControl.value)
159
+ nodeControl.value.updateAttributes({ attrs: {
160
+ ...nodeControl.value.attrs,
161
+ style
162
+ }})
163
+ }
164
+
165
+ </script>
166
+
167
+ <style lang="scss">
168
+ .autocomplete-w-full > ul {
169
+ width: 100%;
170
+ }
171
+ .prism-editor__textarea {
172
+ outline: 0 none;
173
+ outline-offset: 0;
174
+ }
175
+ .style-editor:focus-within {
176
+ box-shadow: 0 0 0 0.2rem #b7e0b8;
177
+ border-color: #4CAF50;
178
+ }
179
+ </style>
@@ -5,11 +5,13 @@ const components = {
5
5
  description: 'PrimeVUE card',
6
6
  previewContent: true,
7
7
  attrs: [],
8
- render: ({ content, attrs }, r) => h('div', { 'class': 'surface-card py-1 px-3 shadow-2 w-full' }, r(content)),
9
- editor: (props, { slots }) => h('div', { 'class': 'surface-card py-1 px-3 shadow-2 w-full' }, slots.default()),
8
+ initialAttrs: {
9
+ class: 'surface-card py-1 px-3 shadow-2'
10
+ },
11
+ render: ({ content, attrs }, r) => h('div', { ...attrs.attrs }, r(content)),
12
+ editor: (attrs, { slots }) => h('div', { ...attrs }, slots.default()),
10
13
  async: true
11
14
  }
12
15
  }
13
16
 
14
-
15
17
  export default components
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/wysiwyg-frontend",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "scripts": {
5
5
  "memDev": "lcli memDev --enableSessions --initScript ./init.js --dbAccess",
6
6
  "localDevInit": "rm tmp.db; lcli localDev --enableSessions --initScript ./init.js",
@@ -26,11 +26,11 @@
26
26
  "@live-change/dao-vue3": "0.5.8",
27
27
  "@live-change/dao-websocket": "0.5.8",
28
28
  "@live-change/framework": "0.7.5",
29
- "@live-change/password-authentication-service": "0.3.3",
30
- "@live-change/prosemirror-service": "0.3.3",
31
- "@live-change/secret-code-service": "0.3.3",
32
- "@live-change/secret-link-service": "0.3.3",
33
- "@live-change/session-service": "0.3.3",
29
+ "@live-change/password-authentication-service": "0.3.4",
30
+ "@live-change/prosemirror-service": "0.3.4",
31
+ "@live-change/secret-code-service": "0.3.4",
32
+ "@live-change/secret-link-service": "0.3.4",
33
+ "@live-change/session-service": "0.3.4",
34
34
  "@live-change/vue3-components": "0.2.16",
35
35
  "@live-change/vue3-ssr": "0.2.16",
36
36
  "@tiptap/extension-blockquote": "^2.0.0-beta.29",
@@ -62,13 +62,14 @@
62
62
  "primeflex": "^3.2.1",
63
63
  "primeicons": "^6.0.1",
64
64
  "primevue": "^3.18.1",
65
+ "prismjs": "^1.28.0",
65
66
  "prosemirror-collab": "^1.3.0",
66
67
  "rollup-plugin-node-builtins": "^2.1.2",
67
68
  "rollup-plugin-visualizer": "5.6.0",
68
- "serialize-javascript": "^6.0.0",
69
69
  "serve-static": "^1.15.0",
70
70
  "v-shared-element": "3.1.0",
71
71
  "vue-meta": "^3.0.0-alpha.9",
72
+ "vue-prism-editor": "2.0.0-alpha.2",
72
73
  "vue-router": "^4.1.3",
73
74
  "vue3-scroll-border": "0.1.2"
74
75
  },
@@ -85,5 +86,5 @@
85
86
  "author": "",
86
87
  "license": "ISC",
87
88
  "description": "",
88
- "gitHead": "7d4c56cc610d692df963c3916411ceb46663b344"
89
+ "gitHead": "7b0e7fc149a3d419aa125b45314cf4eac2fc9410"
89
90
  }