vue-editify 0.1.43 → 0.1.45

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,12 +23,12 @@ import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, pro
23
23
  import { AlexEditor, AlexElement, AlexElementRangeType, AlexElementsRangeType } from 'alex-editor'
24
24
  import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
25
25
  import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, PluginResultType } from '../core/tool'
26
- import { parseList, orderdListHandle, commonElementHandle, tableHandle, preHandle, specialInblockHandle } from '../core/rule'
26
+ import { parseList, orderdListHandle, commonElementHandle, tableThTdHandle, tableFormatHandle, tableRangeMergedHandle, preHandle, specialInblockHandle } from '../core/rule'
27
27
  import { isTask, elementToParagraph, getMatchElementsByRange, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange } from '../core/function'
28
28
  import Toolbar from '../components/toolbar/toolbar.vue'
29
29
  import Menu from '../components/menu/menu.vue'
30
30
  import Layer from '../components/layer/layer.vue'
31
- import { EditifyProps, EditifyTableColumnResizeParamsType, EditifyToolbarOptionsType } from './props'
31
+ import { EditifyProps, EditifyResizeParamsType, EditifyToolbarOptionsType } from './props'
32
32
  import { trans } from '../locale'
33
33
  import { LanguagesItemType } from '../hljs'
34
34
 
@@ -52,8 +52,8 @@ const isModelChange = ref<boolean>(false)
52
52
  const isInputChinese = ref<boolean>(false)
53
53
  //工具条和菜单栏判定延时器
54
54
  const rangeUpdateTimer = ref<any>(null)
55
- //表格列宽拖拽记录数据
56
- const tableColumnResizeParams = ref<EditifyTableColumnResizeParamsType>({
55
+ //拖拽记录数据
56
+ const resizeParams = ref<EditifyResizeParamsType>({
57
57
  element: null, //被拖拽的td
58
58
  start: 0 //水平方向起点位置
59
59
  })
@@ -287,7 +287,13 @@ const createEditor = () => {
287
287
  commonElementHandle(editor.value!, el)
288
288
  },
289
289
  el => {
290
- tableHandle(editor.value!, el)
290
+ tableThTdHandle(editor.value!, el)
291
+ },
292
+ el => {
293
+ tableFormatHandle(editor.value!, el)
294
+ },
295
+ el => {
296
+ tableRangeMergedHandle(editor.value!, el)
291
297
  },
292
298
  el => {
293
299
  preHandle(editor.value!, el, !!(toolbarConfig.value?.use && toolbarConfig.value?.codeBlock?.languages?.show), <(string | LanguagesItemType)[]>toolbarConfig.value?.codeBlock?.languages?.options)
@@ -338,96 +344,151 @@ const setVideoHeight = () => {
338
344
  video.style.height = video.offsetWidth / props.videoRatio + 'px'
339
345
  })
340
346
  }
341
- //鼠标在页面按下:处理表格拖拽改变列宽和菜单栏是否使用判断
347
+ //鼠标在页面按下:处理表格拖拽改变列宽、拖拽改变图片视频宽度和菜单栏是否使用判断
342
348
  const documentMouseDown = (e: Event) => {
343
349
  if (props.disabled) {
344
350
  return
345
351
  }
352
+ const elm = e.target as HTMLElement
353
+ const event = e as MouseEvent
346
354
  //鼠标在编辑器内按下
347
- if (DapElement.isContains(contentRef.value!, <HTMLElement>e.target)) {
348
- const elm = <HTMLElement>e.target
355
+ if (DapElement.isContains(contentRef.value!, elm)) {
349
356
  const key = DapData.get(elm, 'data-alex-editor-key')
350
357
  if (key) {
351
358
  const element = editor.value!.getElementByKey(key)
352
- if (element && element.parsedom == 'td') {
353
- const length = element.parent!.children!.length
354
- //最后一个td不设置
355
- if (element.parent!.children![length - 1].isEqual(element)) {
356
- return
359
+ if (element) {
360
+ //如果是td则表示拖拽改变列宽
361
+ if (element.parsedom == 'td') {
362
+ const length = element.parent!.children!.length
363
+ //最后一个td不设置
364
+ if (element.parent!.children![length - 1].isEqual(element)) {
365
+ return
366
+ }
367
+ const rect = DapElement.getElementBounding(elm)
368
+ //在可拖拽范围内
369
+ if (event.pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && event.pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
370
+ resizeParams.value.element = element
371
+ resizeParams.value.start = event.pageX
372
+ }
357
373
  }
358
- const rect = DapElement.getElementBounding(elm)
359
- //在可拖拽范围内
360
- if ((<MouseEvent>e).pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && (<MouseEvent>e).pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
361
- tableColumnResizeParams.value.element = element
362
- tableColumnResizeParams.value.start = (<MouseEvent>e).pageX
374
+ //如果是img或者video则表示拖拽改变图片视频宽度
375
+ else if (['img', 'video'].includes(element.parsedom!)) {
376
+ const rect = DapElement.getElementBounding(elm)
377
+ //在可拖拽范围内
378
+ if ((event.pageX >= Math.abs(rect.left + elm.offsetWidth - 10) && event.pageX <= Math.abs(rect.left + elm.offsetWidth)) || (event.pageX >= Math.abs(rect.left) && event.pageX <= Math.abs(rect.left + 10))) {
379
+ resizeParams.value.element = element
380
+ resizeParams.value.start = event.pageX
381
+ }
363
382
  }
364
383
  }
365
384
  }
366
385
  }
367
386
  //如果点击了除编辑器外的地方,菜单栏不可使用
368
- if (!DapElement.isContains(elRef.value!, <HTMLElement>e.target) && !isSourceView.value) {
387
+ if (!DapElement.isContains(elRef.value!, elm) && !isSourceView.value) {
369
388
  canUseMenu.value = false
370
389
  }
371
390
  }
372
- //鼠标在页面移动:处理表格拖拽改变列宽
391
+ //鼠标在页面移动:处理表格拖拽改变列宽、拖拽改变图片视频宽度
373
392
  const documentMouseMove = (e: Event) => {
374
393
  if (props.disabled) {
375
394
  return
376
395
  }
377
- if (!tableColumnResizeParams.value.element) {
396
+ if (!resizeParams.value.element) {
378
397
  return
379
398
  }
380
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
381
- if (tables.length != 1) {
382
- return
399
+ const event = e as MouseEvent
400
+ //表格列宽拖拽
401
+ if (resizeParams.value.element.parsedom == 'td') {
402
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
403
+ if (tables.length != 1) {
404
+ return
405
+ }
406
+ const colgroup = tables[0].children!.find(item => {
407
+ return item.parsedom == 'colgroup'
408
+ })!
409
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
410
+ return el.isEqual(resizeParams.value.element!)
411
+ })
412
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}`
413
+ colgroup.children![index].marks!['width'] = width
414
+ colgroup.children![index].elm!.setAttribute('width', width)
415
+ resizeParams.value.start = event.pageX
416
+ }
417
+ //图片视频拖拽改变宽度
418
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
419
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}px`
420
+ if (resizeParams.value.element.hasStyles()) {
421
+ resizeParams.value.element.styles!['width'] = width
422
+ } else {
423
+ resizeParams.value.element.styles = {
424
+ width: width
425
+ }
426
+ }
427
+ resizeParams.value.element.elm!.style.width = width
428
+ if (resizeParams.value.element.parsedom == 'video') {
429
+ setVideoHeight()
430
+ }
431
+ resizeParams.value.start = event.pageX
383
432
  }
384
- const colgroup = tables[0].children!.find(item => {
385
- return item.parsedom == 'colgroup'
386
- })!
387
- const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
388
- return el.isEqual(tableColumnResizeParams.value.element!)
389
- })
390
- const width = `${tableColumnResizeParams.value.element.elm!.offsetWidth + (<MouseEvent>e).pageX - tableColumnResizeParams.value.start}`
391
- colgroup.children![index].marks!['width'] = width
392
- colgroup.children![index].elm!.setAttribute('width', width)
393
- tableColumnResizeParams.value.start = (<MouseEvent>e).pageX
394
433
  }
395
- //鼠标在页面松开:处理表格拖拽改变列宽
434
+ //鼠标在页面松开:处理表格拖拽改变列宽、拖拽改变图片视频宽度
396
435
  const documentMouseUp = () => {
397
436
  if (props.disabled) {
398
437
  return
399
438
  }
400
- if (!tableColumnResizeParams.value.element) {
439
+ if (!resizeParams.value.element) {
401
440
  return
402
441
  }
403
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
404
- if (tables.length != 1) {
405
- return
442
+ //表格列宽拖拽
443
+ if (resizeParams.value.element.parsedom == 'td') {
444
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
445
+ if (tables.length != 1) {
446
+ return
447
+ }
448
+ const colgroup = tables[0].children!.find(item => {
449
+ return item.parsedom == 'colgroup'
450
+ })!
451
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
452
+ return el.isEqual(resizeParams.value.element!)
453
+ })
454
+ const width = parseFloat(colgroup.children![index].marks!['width'])
455
+ if (!isNaN(width)) {
456
+ colgroup.children![index].marks!['width'] = `${Number(((width / resizeParams.value.element.parent!.elm!.offsetWidth) * 100).toFixed(2))}%`
457
+ editor.value!.formatElementStack()
458
+ editor.value!.domRender()
459
+ editor.value!.rangeRender()
460
+ }
461
+ resizeParams.value.element = null
462
+ resizeParams.value.start = 0
406
463
  }
407
- const colgroup = tables[0].children!.find(item => {
408
- return item.parsedom == 'colgroup'
409
- })!
410
- const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
411
- return el.isEqual(tableColumnResizeParams.value.element!)
412
- })
413
- const width = Number(colgroup.children![index].marks!['width'])
414
- if (!isNaN(width)) {
415
- colgroup.children![index].marks!['width'] = `${Number(((width / tableColumnResizeParams.value.element.parent!.elm!.offsetWidth) * 100).toFixed(2))}%`
416
- editor.value!.formatElementStack()
417
- editor.value!.domRender()
418
- editor.value!.rangeRender()
464
+ //图片视频拖拽改变宽度
465
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
466
+ const width = parseFloat(resizeParams.value.element.styles!['width'])
467
+ if (!isNaN(width)) {
468
+ if (resizeParams.value.element.hasStyles()) {
469
+ resizeParams.value.element.styles!['width'] = `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
470
+ } else {
471
+ resizeParams.value.element.styles = {
472
+ width: `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
473
+ }
474
+ }
475
+ editor.value!.formatElementStack()
476
+ editor.value!.domRender()
477
+ editor.value!.rangeRender()
478
+ }
479
+ resizeParams.value.element = null
480
+ resizeParams.value.start = 0
419
481
  }
420
- tableColumnResizeParams.value.element = null
421
- tableColumnResizeParams.value.start = 0
422
482
  }
423
483
  //鼠标点击页面:处理任务列表复选框勾选
424
484
  const documentClick = (e: Event) => {
425
485
  if (props.disabled) {
426
486
  return
427
487
  }
488
+ const elm = e.target as HTMLElement
489
+ const event = e as MouseEvent
428
490
  //鼠标在编辑器内点击
429
- if (DapElement.isContains(contentRef.value!, <HTMLElement>e.target)) {
430
- const elm = <HTMLElement>e.target
491
+ if (DapElement.isContains(contentRef.value!, elm)) {
431
492
  const key = DapData.get(elm, 'data-alex-editor-key')
432
493
  if (key) {
433
494
  const element = editor.value!.getElementByKey(key)!
@@ -435,7 +496,7 @@ const documentClick = (e: Event) => {
435
496
  if (isTask(element)) {
436
497
  const rect = DapElement.getElementBounding(elm)
437
498
  //在复选框范围内
438
- if ((<MouseEvent>e).pageX >= Math.abs(rect.left) && (<MouseEvent>e).pageX <= Math.abs(rect.left + 16) && (<MouseEvent>e).pageY >= Math.abs(rect.top + elm.offsetHeight / 2 - 8) && (<MouseEvent>e).pageY <= Math.abs(rect.top + elm.offsetHeight / 2 + 8)) {
499
+ if (event.pageX >= Math.abs(rect.left) && event.pageX <= Math.abs(rect.left + 16) && event.pageY >= Math.abs(rect.top + elm.offsetHeight / 2 - 8) && event.pageY <= Math.abs(rect.top + elm.offsetHeight / 2 + 8)) {
439
500
  //取消勾选
440
501
  if (element.marks!['data-editify-task'] == 'checked') {
441
502
  element.marks!['data-editify-task'] = 'uncheck'
@@ -477,6 +538,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
477
538
  if (el.marks!['disabled']) {
478
539
  marks['disabled'] = el.marks!['disabled']
479
540
  }
541
+ //图片的alt属性保留
542
+ if (el.parsedom == 'img' && el.marks!['alt']) {
543
+ marks['alt'] = el.marks!['alt']
544
+ }
480
545
  //图片和视频的src属性保留
481
546
  if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
482
547
  marks['src'] = el.marks!['src']
@@ -521,9 +586,29 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
521
586
  if (el.parsedom == 'div' && el.marks!['data-editify-task']) {
522
587
  marks['data-editify-task'] = el.marks!['data-editify-task']
523
588
  }
589
+ //表格列宽属性保留
590
+ if (el.parsedom == 'col' && el.marks!['width']) {
591
+ marks['width'] = el.marks!['width']
592
+ }
593
+ //表格单元格colspan属性保留
594
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['colspan']) {
595
+ marks['colspan'] = el.marks!['colspan']
596
+ }
597
+ //表格单元格rowspan属性保留
598
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['rowspan']) {
599
+ marks['rowspan'] = el.marks!['rowspan']
600
+ }
601
+ //表格单元格被合并属性保留
602
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['data-editify-merged']) {
603
+ marks['data-editify-merged'] = el.marks!['data-editify-merged']
604
+ }
524
605
  }
525
606
  //处理需要保留的样式
526
607
  if (el.hasStyles()) {
608
+ //图片和视频保留width样式
609
+ if (['img', 'video'].includes(el.parsedom!) && el.styles!['width']) {
610
+ styles['width'] = el.styles!['width']
611
+ }
527
612
  //块元素保留text-indent样式
528
613
  if ((el.isBlock() || el.isInblock()) && el.styles!['text-indent']) {
529
614
  styles['text-indent'] = el.styles!['text-indent']
@@ -631,10 +716,10 @@ const handleEditorClick = (e: Event) => {
631
716
  if (props.disabled || isSourceView.value) {
632
717
  return
633
718
  }
634
- const node = <HTMLElement>e.target
719
+ const elm = e.target as HTMLElement
635
720
  //点击的是图片或者视频
636
- if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
637
- const key = Number(node.getAttribute('data-editify-element'))
721
+ if (elm.nodeName.toLocaleLowerCase() == 'img' || elm.nodeName.toLocaleLowerCase() == 'video') {
722
+ const key = Number(elm.getAttribute('data-editify-element'))
638
723
  if (DapNumber.isNumber(key)) {
639
724
  const element = editor.value!.getElementByKey(key)!
640
725
  if (!editor.value!.range) {
@@ -4,7 +4,7 @@ import { PluginType, MenuConfigType, ObjectType, ToolbarConfigType } from '../co
4
4
  import { AlexElement } from 'alex-editor'
5
5
  import { LocaleType } from '../locale'
6
6
 
7
- export type EditifyTableColumnResizeParamsType = {
7
+ export type EditifyResizeParamsType = {
8
8
  element: AlexElement | null
9
9
  start: number
10
10
  }
@@ -1,3 +1,19 @@
1
+ .editify-icon-merge-cells-up:before {
2
+ content: '\e73e';
3
+ }
4
+
5
+ .editify-icon-merge-cells-left:before {
6
+ content: '\e741';
7
+ }
8
+
9
+ .editify-icon-merge-cells-right:before {
10
+ content: '\e73f';
11
+ }
12
+
13
+ .editify-icon-merge-cells-down:before {
14
+ content: '\e740';
15
+ }
16
+
1
17
  .editify-icon-mathformula:before {
2
18
  content: '\e616';
3
19
  }
Binary file
Binary file
package/src/index.ts CHANGED
@@ -9,17 +9,17 @@ export type { ButtonTypeType, ButtonOptionsItemType, ButtonSelectConfigType, But
9
9
  export type { InsertImageUploadErrorType } from './components/insertImage/props'
10
10
  export type { InsertVideoUploadErrorType } from './components/insertVideo/props'
11
11
  export type { MenuButtonType, MenuSelectButtonType, MenuDisplayButtonType, MenuImageButtonType, MenuVideoButtonType, MenuTableButtonType, MenuCustomButtonType, CodeBlockToolbarType, TextToolbarType, ToolbarConfigType, MenuSequenceType, MenuModeType, MenuExtendType, MenuConfigType, PluginType, PluginResultType } from './core/tool'
12
- export type { ElementMatchConfig } from './core/function'
12
+ export type { ElementMatchConfigType } from './core/function'
13
13
 
14
14
  //导出编辑器操作方法
15
- export { elementIsMatch, getMatchElementByElement, getMatchElementsByRange, elementIsInList, elementIsInTask, isList, isTask, hasPreInRange, isRangeInPre, hasQuoteInRange, isRangeInQuote, hasListInRange, isRangeInList, hasTaskInRange, isRangeInTask, hasLinkInRange, hasTableInRange, hasImageInRange, hasVideoInRange, queryTextStyle, queryTextMark, getRangeText, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock } from './core/function'
15
+ export { elementIsMatch, getMatchElementByElement, getMatchElementsByRange, elementIsInList, elementIsInTask, isList, isTask, hasPreInRange, isRangeInPre, hasQuoteInRange, isRangeInQuote, hasListInRange, isRangeInList, hasTaskInRange, isRangeInTask, hasLinkInRange, hasTableInRange, hasImageInRange, hasVideoInRange, queryTextStyle, queryTextMark, getRangeText, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock, insertSeparator } from './core/function'
16
16
 
17
17
  //安装函数
18
18
  const install: FunctionPlugin = (app: App) => {
19
19
  app.component(Editify.name!, Editify)
20
20
  }
21
21
  //版本号
22
- const version = '0.1.43'
22
+ const version = '0.1.45'
23
23
 
24
24
  //导出AlexElement元素
25
25
  export { AlexElement } from 'alex-editor'
@@ -9,6 +9,10 @@ export const en_US: ObjectType = {
9
9
  insertColumnRight: 'Insert column backward',
10
10
  deleteRow: 'Delete rows',
11
11
  deleteColumn: 'Delete column',
12
+ mergeCellsLeft: 'Merge cells to the left',
13
+ mergeCellsRight: 'Merge cells to the right',
14
+ mergeCellsUp: 'Merge cells up',
15
+ mergeCellsDown: 'Merge cells down',
12
16
  deleteTable: 'Delete table',
13
17
  selectLanguages: 'Select language',
14
18
  autoRecognize: 'Auto',
@@ -9,6 +9,10 @@ export const zh_CN: ObjectType = {
9
9
  insertColumnRight: '向后插入列',
10
10
  deleteRow: '删除行',
11
11
  deleteColumn: '删除列',
12
+ mergeCellsLeft: '向左合并单元格',
13
+ mergeCellsRight: '向右合并单元格',
14
+ mergeCellsUp: '向上合并单元格',
15
+ mergeCellsDown: '向下合并单元格',
12
16
  deleteTable: '删除表格',
13
17
  selectLanguages: '选择语言',
14
18
  autoRecognize: '自动识别',
@@ -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