vue-editify 0.1.27 → 0.1.30
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/lib/core/function.d.ts +265 -0
- package/lib/core/rule.d.ts +32 -0
- package/lib/core/tool.d.ts +50 -1
- package/lib/editify.es.js +140 -66
- package/lib/editify.umd.js +1 -1
- package/lib/hljs/index.d.ts +9 -0
- package/lib/index.d.ts +1 -1
- package/lib/locale/index.d.ts +5 -0
- package/lib/plugins/attachment/index.d.ts +19 -0
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/components/menu/menu.vue +51 -11
- package/src/core/function.ts +265 -42
- package/src/core/rule.ts +49 -7
- package/src/core/tool.ts +51 -9
- package/src/editify/editify.less +2 -1
- package/src/editify/editify.vue +3 -11
- package/src/hljs/index.ts +9 -2
- package/src/index.ts +1 -1
- package/src/locale/index.ts +5 -2
- package/src/plugins/attachment/index.ts +101 -57
- package/vite.config.ts.timestamp-1714200628309-967ea10c27215.mjs +0 -48
package/src/core/tool.ts
CHANGED
@@ -198,8 +198,15 @@ export type MenuConfigType = {
|
|
198
198
|
extends?: MenuExtendType
|
199
199
|
}
|
200
200
|
|
201
|
+
export type PluginMenuConfigType = {
|
202
|
+
extraDisabled?: ((name: string) => boolean) | null
|
203
|
+
sequence: number
|
204
|
+
extend: MenuCustomButtonType
|
205
|
+
}
|
206
|
+
|
201
207
|
export type PluginResultType = {
|
202
|
-
|
208
|
+
name: string
|
209
|
+
menu?: PluginMenuConfigType
|
203
210
|
updateView?: () => void
|
204
211
|
customParseNode?: (element: AlexElement) => AlexElement
|
205
212
|
renderRule?: (el: AlexElement) => void
|
@@ -209,7 +216,9 @@ export type PluginResultType = {
|
|
209
216
|
|
210
217
|
export type PluginType = (editifyInstance: ComponentInternalInstance, color: string | null, editTrans: (key: string) => any) => PluginResultType
|
211
218
|
|
212
|
-
|
219
|
+
/**
|
220
|
+
* 粘贴html时保留的数据
|
221
|
+
*/
|
213
222
|
export const pasteKeepData: ObjectType = {
|
214
223
|
//粘贴html时元素保留的样式(全部元素)
|
215
224
|
marks: {
|
@@ -237,7 +246,12 @@ export const pasteKeepData: ObjectType = {
|
|
237
246
|
}
|
238
247
|
}
|
239
248
|
|
240
|
-
|
249
|
+
/**
|
250
|
+
* 对象平替值方法
|
251
|
+
* @param o1
|
252
|
+
* @param o2
|
253
|
+
* @returns
|
254
|
+
*/
|
241
255
|
export const mergeObject = function (o1: ObjectType, o2: ObjectType) {
|
242
256
|
if (!DapCommon.isObject(o1) && DapCommon.isObject(o2)) {
|
243
257
|
return null
|
@@ -255,7 +269,13 @@ export const mergeObject = function (o1: ObjectType, o2: ObjectType) {
|
|
255
269
|
return o1
|
256
270
|
}
|
257
271
|
|
258
|
-
|
272
|
+
/**
|
273
|
+
* 判断对象是否含有某个属性或者属性值是否一致
|
274
|
+
* @param obj
|
275
|
+
* @param name
|
276
|
+
* @param value
|
277
|
+
* @returns
|
278
|
+
*/
|
259
279
|
export const queryHasValue = function (obj: ObjectType, name: string, value?: string | number) {
|
260
280
|
//如果value不存在则判断是否拥有属性name
|
261
281
|
if (value == null || value == undefined) {
|
@@ -296,7 +316,11 @@ export const queryHasValue = function (obj: ObjectType, name: string, value?: st
|
|
296
316
|
return ownValue == value
|
297
317
|
}
|
298
318
|
|
299
|
-
|
319
|
+
/**
|
320
|
+
* 深拷贝函数
|
321
|
+
* @param data
|
322
|
+
* @returns
|
323
|
+
*/
|
300
324
|
export const cloneData = function (data: any) {
|
301
325
|
if (DapCommon.isObject(data) || Array.isArray(data)) {
|
302
326
|
return JSON.parse(JSON.stringify(data))
|
@@ -304,7 +328,11 @@ export const cloneData = function (data: any) {
|
|
304
328
|
return data
|
305
329
|
}
|
306
330
|
|
307
|
-
|
331
|
+
/**
|
332
|
+
* 根据行元素获取colgroup的col数量
|
333
|
+
* @param row
|
334
|
+
* @returns
|
335
|
+
*/
|
308
336
|
export const getColNumbers = function (row: AlexElement) {
|
309
337
|
const children = row.children || []
|
310
338
|
let num = 0
|
@@ -321,7 +349,11 @@ export const getColNumbers = function (row: AlexElement) {
|
|
321
349
|
return num
|
322
350
|
}
|
323
351
|
|
324
|
-
|
352
|
+
/**
|
353
|
+
* 获取菜单按钮列表数据配置
|
354
|
+
* @param editTrans
|
355
|
+
* @returns
|
356
|
+
*/
|
325
357
|
export const getButtonOptionsConfig = function (editTrans: (key: string) => any): ButtonOptionsConfigType {
|
326
358
|
return {
|
327
359
|
//标题配置
|
@@ -517,7 +549,12 @@ export const getButtonOptionsConfig = function (editTrans: (key: string) => any)
|
|
517
549
|
}
|
518
550
|
}
|
519
551
|
|
520
|
-
|
552
|
+
/**
|
553
|
+
* 工具条全量配置
|
554
|
+
* @param editTrans
|
555
|
+
* @param editLocale
|
556
|
+
* @returns
|
557
|
+
*/
|
521
558
|
export const getToolbarConfig = function (editTrans: (key: string) => any, editLocale: LocaleType): ToolbarConfigType {
|
522
559
|
return {
|
523
560
|
//是否使用工具条
|
@@ -762,7 +799,12 @@ export const getToolbarConfig = function (editTrans: (key: string) => any, editL
|
|
762
799
|
}
|
763
800
|
}
|
764
801
|
|
765
|
-
|
802
|
+
/**
|
803
|
+
* 菜单栏全量配置
|
804
|
+
* @param editTrans
|
805
|
+
* @param editLocale
|
806
|
+
* @returns
|
807
|
+
*/
|
766
808
|
export const getMenuConfig = function (editTrans: (key: string) => any, editLocale: LocaleType): MenuConfigType {
|
767
809
|
return {
|
768
810
|
//是否使用菜单栏
|
package/src/editify/editify.less
CHANGED
@@ -348,7 +348,7 @@
|
|
348
348
|
color: @font-color-link;
|
349
349
|
transition: all 200ms;
|
350
350
|
position: relative;
|
351
|
-
padding: 0
|
351
|
+
padding: 0 10px;
|
352
352
|
font-size: 14px;
|
353
353
|
vertical-align: baseline;
|
354
354
|
|
@@ -378,6 +378,7 @@
|
|
378
378
|
&.editify-placeholder::before {
|
379
379
|
cursor: auto;
|
380
380
|
}
|
381
|
+
|
381
382
|
:deep(a) {
|
382
383
|
cursor: pointer;
|
383
384
|
}
|
package/src/editify/editify.vue
CHANGED
@@ -45,8 +45,6 @@ const emits = defineEmits(['update:modelValue', 'focus', 'blur', 'change', 'keyd
|
|
45
45
|
|
46
46
|
//设置国际化方法
|
47
47
|
const $editTrans = trans(props.locale || 'zh_CN')
|
48
|
-
//对子孙后代组件提供国际化方法
|
49
|
-
provide('$editTrans', $editTrans)
|
50
48
|
|
51
49
|
//是否编辑器内部修改值
|
52
50
|
const isModelChange = ref<boolean>(false)
|
@@ -135,15 +133,7 @@ const pluginResultList = computed<PluginResultType[]>(() => {
|
|
135
133
|
})
|
136
134
|
//最终生效的菜单栏配置
|
137
135
|
const menuConfig = computed<MenuConfigType>(() => {
|
138
|
-
|
139
|
-
//注册插件:自定义菜单栏
|
140
|
-
pluginResultList.value.forEach(pluginResult => {
|
141
|
-
menu = <MenuConfigType>mergeObject(menu, pluginResult.menu || {})
|
142
|
-
})
|
143
|
-
//加入自定义menu配置
|
144
|
-
menu = <MenuConfigType>mergeObject(menu, props.menu || {})
|
145
|
-
//返回最终配置
|
146
|
-
return <MenuConfigType>mergeObject(getMenuConfig($editTrans, props.locale), menu)
|
136
|
+
return <MenuConfigType>mergeObject(getMenuConfig($editTrans, props.locale), props.menu || {})
|
147
137
|
})
|
148
138
|
|
149
139
|
//编辑器内部修改值的方法
|
@@ -841,6 +831,7 @@ onBeforeUnmount(() => {
|
|
841
831
|
editor.value!.destroy()
|
842
832
|
})
|
843
833
|
|
834
|
+
provide('$editTrans', $editTrans)
|
844
835
|
provide('editify', instance)
|
845
836
|
provide('isSourceView', isSourceView)
|
846
837
|
provide('isFullScreen', isFullScreen)
|
@@ -848,6 +839,7 @@ provide('canUseMenu', canUseMenu)
|
|
848
839
|
provide('editor', editor)
|
849
840
|
provide('dataRangeCaches', dataRangeCaches)
|
850
841
|
provide('showBorder', showBorder)
|
842
|
+
provide('pluginResultList', pluginResultList)
|
851
843
|
|
852
844
|
defineExpose({
|
853
845
|
editor,
|
package/src/hljs/index.ts
CHANGED
@@ -74,7 +74,12 @@ export type LanguagesItemType = {
|
|
74
74
|
value?: string
|
75
75
|
}
|
76
76
|
|
77
|
-
|
77
|
+
/**
|
78
|
+
* 获取经过hljs处理的html元素
|
79
|
+
* @param code
|
80
|
+
* @param language
|
81
|
+
* @returns
|
82
|
+
*/
|
78
83
|
export const getHljsHtml = function (code: string, language: string) {
|
79
84
|
if (language) {
|
80
85
|
return hljs.highlight(code, {
|
@@ -84,7 +89,9 @@ export const getHljsHtml = function (code: string, language: string) {
|
|
84
89
|
}
|
85
90
|
return hljs.highlightAuto(code).value
|
86
91
|
}
|
87
|
-
|
92
|
+
/**
|
93
|
+
* 可选择语言列表
|
94
|
+
*/
|
88
95
|
export const languages: LanguagesItemType[] = [
|
89
96
|
{
|
90
97
|
label: 'Plain Text',
|
package/src/index.ts
CHANGED
package/src/locale/index.ts
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
import { en_US } from './en_US'
|
2
2
|
import { zh_CN } from './zh_CN'
|
3
3
|
|
4
|
-
//语言类型
|
5
4
|
export type LocaleType = 'zh_CN' | 'en_US'
|
6
5
|
|
7
|
-
|
6
|
+
/**
|
7
|
+
* 翻译方法
|
8
|
+
* @param locale
|
9
|
+
* @returns
|
10
|
+
*/
|
8
11
|
export const trans = (locale: LocaleType) => {
|
9
12
|
return (key: string) => {
|
10
13
|
return { zh_CN, en_US }[locale][key]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ComponentInternalInstance, h } from 'vue'
|
2
|
-
import { AlexEditor, AlexElement } from 'alex-editor'
|
2
|
+
import { AlexEditor, AlexElement, AlexElementsRangeType } from 'alex-editor'
|
3
3
|
import { ObjectType, PluginType } from '../../core/tool'
|
4
4
|
import Layer from '../../components/layer/layer.vue'
|
5
5
|
import Button from '../../components/button/button.vue'
|
@@ -7,7 +7,7 @@ import Icon from '../../components/icon/icon.vue'
|
|
7
7
|
import InsertAttachment from './insertAttachment/insertAttachment.vue'
|
8
8
|
import { InsertAttachmentUploadErrorType } from './insertAttachment/props'
|
9
9
|
import { event as DapEvent, common as DapCommon } from 'dap-util'
|
10
|
-
import { hasPreInRange } from '../../core/function'
|
10
|
+
import { hasLinkInRange, hasPreInRange, hasQuoteInRange } from '../../core/function'
|
11
11
|
|
12
12
|
export type AttachmentOptionsType = {
|
13
13
|
//排序
|
@@ -34,72 +34,116 @@ export type AttachmentOptionsType = {
|
|
34
34
|
handleError?: (error: InsertAttachmentUploadErrorType, file: File) => void
|
35
35
|
}
|
36
36
|
|
37
|
+
/**
|
38
|
+
* 元素是否附件
|
39
|
+
* @param element
|
40
|
+
* @returns
|
41
|
+
*/
|
42
|
+
export const isAttachment = (element: AlexElement) => {
|
43
|
+
if (element.isEmpty()) {
|
44
|
+
return false
|
45
|
+
}
|
46
|
+
return element.parsedom == 'span' && element.type == 'closed' && element.hasMarks() && element.marks!['data-attachment']
|
47
|
+
}
|
48
|
+
|
49
|
+
/**
|
50
|
+
* 选区是否含有附件
|
51
|
+
* @param editor
|
52
|
+
* @param dataRangeCaches
|
53
|
+
* @returns
|
54
|
+
*/
|
55
|
+
export const hasAttachmentInRange = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType) => {
|
56
|
+
if (!editor.range) {
|
57
|
+
return false
|
58
|
+
}
|
59
|
+
if (editor.range.anchor.isEqual(editor.range.focus)) {
|
60
|
+
return isAttachment(editor.range.anchor.element)
|
61
|
+
}
|
62
|
+
return dataRangeCaches.flatList.some(item => {
|
63
|
+
return isAttachment(item.element)
|
64
|
+
})
|
65
|
+
}
|
66
|
+
|
67
|
+
/**
|
68
|
+
* 附件插件
|
69
|
+
* @param options
|
70
|
+
* @returns
|
71
|
+
*/
|
37
72
|
export const attachment = (options?: AttachmentOptionsType) => {
|
38
73
|
if (!DapCommon.isObject(options)) {
|
39
74
|
options = {}
|
40
75
|
}
|
41
76
|
const plugin: PluginType = (editifyInstance: ComponentInternalInstance, color: string | null, editTrans: (key: string) => any) => {
|
77
|
+
let isDisabled = false
|
78
|
+
//如果光标范围内有链接、代码块和引用则禁用
|
79
|
+
if (editifyInstance.exposed!.editor.value) {
|
80
|
+
isDisabled = hasPreInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasLinkInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasQuoteInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
|
81
|
+
}
|
42
82
|
return {
|
83
|
+
name: 'attachment',
|
43
84
|
//附件菜单项配置
|
44
85
|
menu: {
|
45
|
-
sequence:
|
46
|
-
|
86
|
+
sequence: options!.sequence || 100,
|
87
|
+
extraDisabled: (name: string) => {
|
88
|
+
//如果光标选区内有附件则禁用链接菜单、引用菜单、代码块菜单
|
89
|
+
if (name == 'link' || name == 'quote' || name == 'codeBlock') {
|
90
|
+
return hasAttachmentInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
|
91
|
+
}
|
92
|
+
return false
|
47
93
|
},
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
contenteditable: 'false'
|
77
|
-
}
|
78
|
-
//创建元素
|
79
|
-
const attachmentElement = new AlexElement('closed', 'span', marks, null, null)
|
80
|
-
//获取editor对象
|
81
|
-
const editor = <AlexEditor>editifyInstance.exposed!.editor.value
|
82
|
-
//插入编辑器
|
83
|
-
editor.insertElement(attachmentElement)
|
84
|
-
//创建空文本元素
|
85
|
-
const beforeText = AlexElement.getSpaceElement()
|
86
|
-
const afterText = AlexElement.getSpaceElement()
|
87
|
-
//将空白文本元素插入附件两端
|
88
|
-
editor.addElementAfter(afterText, attachmentElement)
|
89
|
-
editor.addElementBefore(beforeText, attachmentElement)
|
90
|
-
//移动光标到新插入的元素
|
91
|
-
editor.range!.anchor.moveToStart(afterText)
|
92
|
-
editor.range!.focus.moveToStart(afterText)
|
93
|
-
//渲染
|
94
|
-
editor.formatElementStack()
|
95
|
-
editor.domRender()
|
96
|
-
editor.rangeRender()
|
94
|
+
extend: {
|
95
|
+
type: 'select',
|
96
|
+
title: options!.title || editTrans('insertAttachment'),
|
97
|
+
leftBorder: options!.leftBorder,
|
98
|
+
rightBorder: options!.rightBorder,
|
99
|
+
hideScroll: true,
|
100
|
+
disabled: isDisabled,
|
101
|
+
default: () => h(Icon, { value: 'attachment' }),
|
102
|
+
layer: (_name: string, btnInstance: InstanceType<typeof Button>) =>
|
103
|
+
h(InsertAttachment, {
|
104
|
+
color: color,
|
105
|
+
accept: options!.accept,
|
106
|
+
allowedFileType: options!.allowedFileType || [],
|
107
|
+
multiple: !!options!.multiple,
|
108
|
+
maxSize: options!.maxSize,
|
109
|
+
minSize: options!.minSize,
|
110
|
+
customUpload: options!.customUpload,
|
111
|
+
handleError: options!.handleError,
|
112
|
+
onChange: () => {
|
113
|
+
;(<InstanceType<typeof Layer>>btnInstance.$refs.layerRef).setPosition()
|
114
|
+
},
|
115
|
+
onInsert: (name: string, url: string) => {
|
116
|
+
//如果地址存在
|
117
|
+
if (url) {
|
118
|
+
const marks: ObjectType = {
|
119
|
+
'data-attachment': url,
|
120
|
+
'data-attachment-name': name || editTrans('attachmentDefaultName'),
|
121
|
+
contenteditable: 'false'
|
97
122
|
}
|
98
|
-
|
99
|
-
|
123
|
+
//创建元素
|
124
|
+
const attachmentElement = new AlexElement('closed', 'span', marks, null, null)
|
125
|
+
//获取editor对象
|
126
|
+
const editor = <AlexEditor>editifyInstance.exposed!.editor.value
|
127
|
+
//插入编辑器
|
128
|
+
editor.insertElement(attachmentElement)
|
129
|
+
//创建空文本元素
|
130
|
+
const beforeText = AlexElement.getSpaceElement()
|
131
|
+
const afterText = AlexElement.getSpaceElement()
|
132
|
+
//将空白文本元素插入附件两端
|
133
|
+
editor.addElementAfter(afterText, attachmentElement)
|
134
|
+
editor.addElementBefore(beforeText, attachmentElement)
|
135
|
+
//移动光标到新插入的元素
|
136
|
+
editor.range!.anchor.moveToStart(afterText)
|
137
|
+
editor.range!.focus.moveToStart(afterText)
|
138
|
+
//渲染
|
139
|
+
editor.formatElementStack()
|
140
|
+
editor.domRender()
|
141
|
+
editor.rangeRender()
|
100
142
|
}
|
101
|
-
|
102
|
-
|
143
|
+
//关闭浮层
|
144
|
+
btnInstance.show = false
|
145
|
+
}
|
146
|
+
})
|
103
147
|
}
|
104
148
|
},
|
105
149
|
//找到附件元素点击下载
|
@@ -1,48 +0,0 @@
|
|
1
|
-
// vite.config.ts
|
2
|
-
import { defineConfig } from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/vite/dist/node/index.js";
|
3
|
-
import vue from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/@vitejs/plugin-vue/dist/index.mjs";
|
4
|
-
import dts from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/vite-plugin-dts/dist/index.mjs";
|
5
|
-
import path from "path";
|
6
|
-
var __vite_injected_original_dirname = "/Users/lingkai/Desktop/\u524D\u7AEF\u5E93/vue-editify";
|
7
|
-
var vite_config_default = defineConfig({
|
8
|
-
plugins: [vue(), dts()],
|
9
|
-
build: {
|
10
|
-
//打包后的目录名称
|
11
|
-
outDir: "lib",
|
12
|
-
minify: "terser",
|
13
|
-
lib: {
|
14
|
-
entry: path.resolve(__vite_injected_original_dirname, "src/index.ts"),
|
15
|
-
name: "editify",
|
16
|
-
fileName: (format) => `editify.${format}.js`
|
17
|
-
},
|
18
|
-
rollupOptions: {
|
19
|
-
// 确保外部化处理那些你不想打包进库的依赖
|
20
|
-
external: ["vue"],
|
21
|
-
output: {
|
22
|
-
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
|
23
|
-
globals: {
|
24
|
-
vue: "Vue"
|
25
|
-
},
|
26
|
-
exports: "named"
|
27
|
-
}
|
28
|
-
},
|
29
|
-
sourcemap: false
|
30
|
-
//是否构建source map 文件
|
31
|
-
},
|
32
|
-
css: {
|
33
|
-
preprocessorOptions: {
|
34
|
-
less: {
|
35
|
-
// 使用 less 编写样式的 UI 库(如 antd)时建议加入这个设置
|
36
|
-
javascriptEnabled: true,
|
37
|
-
additionalData: `@import "src/css/base.less";`
|
38
|
-
}
|
39
|
-
}
|
40
|
-
},
|
41
|
-
server: {
|
42
|
-
host: "0.0.0.0"
|
43
|
-
}
|
44
|
-
});
|
45
|
-
export {
|
46
|
-
vite_config_default as default
|
47
|
-
};
|
48
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvbGluZ2thaS9EZXNrdG9wL1x1NTI0RFx1N0FFRlx1NUU5My92dWUtZWRpdGlmeVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL2xpbmdrYWkvRGVza3RvcC9cdTUyNERcdTdBRUZcdTVFOTMvdnVlLWVkaXRpZnkvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL1VzZXJzL2xpbmdrYWkvRGVza3RvcC8lRTUlODklOEQlRTclQUIlQUYlRTUlQkElOTMvdnVlLWVkaXRpZnkvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlJ1xuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXG5pbXBvcnQgZHRzIGZyb20gJ3ZpdGUtcGx1Z2luLWR0cydcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG5cdHBsdWdpbnM6IFt2dWUoKSwgZHRzKCldLFxuXHRidWlsZDoge1xuXHRcdC8vXHU2MjUzXHU1MzA1XHU1NDBFXHU3Njg0XHU3NkVFXHU1RjU1XHU1NDBEXHU3OUYwXG5cdFx0b3V0RGlyOiAnbGliJyxcblx0XHRtaW5pZnk6ICd0ZXJzZXInLFxuXHRcdGxpYjoge1xuXHRcdFx0ZW50cnk6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICdzcmMvaW5kZXgudHMnKSxcblx0XHRcdG5hbWU6ICdlZGl0aWZ5Jyxcblx0XHRcdGZpbGVOYW1lOiBmb3JtYXQgPT4gYGVkaXRpZnkuJHtmb3JtYXR9LmpzYFxuXHRcdH0sXG5cdFx0cm9sbHVwT3B0aW9uczoge1xuXHRcdFx0Ly8gXHU3ODZFXHU0RkREXHU1OTE2XHU5MEU4XHU1MzE2XHU1OTA0XHU3NDA2XHU5MEEzXHU0RTlCXHU0RjYwXHU0RTBEXHU2MEYzXHU2MjUzXHU1MzA1XHU4RkRCXHU1RTkzXHU3Njg0XHU0RjlEXHU4RDU2XG5cdFx0XHRleHRlcm5hbDogWyd2dWUnXSxcblx0XHRcdG91dHB1dDoge1xuXHRcdFx0XHQvLyBcdTU3MjggVU1EIFx1Njc4NFx1NUVGQVx1NkEyMVx1NUYwRlx1NEUwQlx1NEUzQVx1OEZEOVx1NEU5Qlx1NTkxNlx1OTBFOFx1NTMxNlx1NzY4NFx1NEY5RFx1OEQ1Nlx1NjNEMFx1NEY5Qlx1NEUwMFx1NEUyQVx1NTE2OFx1NUM0MFx1NTNEOFx1OTFDRlxuXHRcdFx0XHRnbG9iYWxzOiB7XG5cdFx0XHRcdFx0dnVlOiAnVnVlJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRleHBvcnRzOiAnbmFtZWQnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzb3VyY2VtYXA6IGZhbHNlIC8vXHU2NjJGXHU1NDI2XHU2Nzg0XHU1RUZBc291cmNlIG1hcCBcdTY1ODdcdTRFRjZcblx0fSxcblx0Y3NzOiB7XG5cdFx0cHJlcHJvY2Vzc29yT3B0aW9uczoge1xuXHRcdFx0bGVzczoge1xuXHRcdFx0XHQvLyBcdTRGN0ZcdTc1MjggbGVzcyBcdTdGMTZcdTUxOTlcdTY4MzdcdTVGMEZcdTc2ODQgVUkgXHU1RTkzXHVGRjA4XHU1OTgyIGFudGRcdUZGMDlcdTY1RjZcdTVFRkFcdThCQUVcdTUyQTBcdTUxNjVcdThGRDlcdTRFMkFcdThCQkVcdTdGNkVcblx0XHRcdFx0amF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXG5cdFx0XHRcdGFkZGl0aW9uYWxEYXRhOiBgQGltcG9ydCBcInNyYy9jc3MvYmFzZS5sZXNzXCI7YFxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0c2VydmVyOiB7XG5cdFx0aG9zdDogJzAuMC4wLjAnXG5cdH1cbn0pXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTRULFNBQVMsb0JBQW9CO0FBQ3pWLE9BQU8sU0FBUztBQUNoQixPQUFPLFNBQVM7QUFDaEIsT0FBTyxVQUFVO0FBSGpCLElBQU0sbUNBQW1DO0FBS3pDLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzNCLFNBQVMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQUEsRUFDdEIsT0FBTztBQUFBO0FBQUEsSUFFTixRQUFRO0FBQUEsSUFDUixRQUFRO0FBQUEsSUFDUixLQUFLO0FBQUEsTUFDSixPQUFPLEtBQUssUUFBUSxrQ0FBVyxjQUFjO0FBQUEsTUFDN0MsTUFBTTtBQUFBLE1BQ04sVUFBVSxZQUFVLFdBQVcsTUFBTTtBQUFBLElBQ3RDO0FBQUEsSUFDQSxlQUFlO0FBQUE7QUFBQSxNQUVkLFVBQVUsQ0FBQyxLQUFLO0FBQUEsTUFDaEIsUUFBUTtBQUFBO0FBQUEsUUFFUCxTQUFTO0FBQUEsVUFDUixLQUFLO0FBQUEsUUFDTjtBQUFBLFFBQ0EsU0FBUztBQUFBLE1BQ1Y7QUFBQSxJQUNEO0FBQUEsSUFDQSxXQUFXO0FBQUE7QUFBQSxFQUNaO0FBQUEsRUFDQSxLQUFLO0FBQUEsSUFDSixxQkFBcUI7QUFBQSxNQUNwQixNQUFNO0FBQUE7QUFBQSxRQUVMLG1CQUFtQjtBQUFBLFFBQ25CLGdCQUFnQjtBQUFBLE1BQ2pCO0FBQUEsSUFDRDtBQUFBLEVBQ0Q7QUFBQSxFQUNBLFFBQVE7QUFBQSxJQUNQLE1BQU07QUFBQSxFQUNQO0FBQ0QsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
|