@node-projects/web-component-designer 0.0.80 → 0.0.81

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.
Files changed (29) hide show
  1. package/dist/elements/helper/PathDataPolyfill.d.ts +11 -10
  2. package/dist/elements/helper/PathDataPolyfill.js +35 -0
  3. package/dist/elements/services/DefaultServiceBootstrap.js +5 -1
  4. package/dist/elements/services/htmlWriterService/AbstractHtmlWriterService.d.ts +10 -0
  5. package/dist/elements/services/htmlWriterService/AbstractHtmlWriterService.js +62 -0
  6. package/dist/elements/services/htmlWriterService/FormatingHtmlWriterService.d.ts +5 -5
  7. package/dist/elements/services/htmlWriterService/FormatingHtmlWriterService.js +4 -4
  8. package/dist/elements/services/htmlWriterService/HtmlWriterService copy.d.ts +12 -0
  9. package/dist/elements/services/htmlWriterService/HtmlWriterService copy.js +118 -0
  10. package/dist/elements/services/htmlWriterService/HtmlWriterService.d.ts +6 -6
  11. package/dist/elements/services/htmlWriterService/HtmlWriterService.js +6 -33
  12. package/dist/elements/services/htmlWriterService/IHtmlWriterOptions.d.ts +2 -0
  13. package/dist/elements/services/htmlWriterService/IHtmlWriterOptions.js +5 -3
  14. package/dist/elements/services/manifestParsers/WebcomponentManifestParserService.js +3 -1
  15. package/dist/elements/widgets/codeView/code-view-code-mirror.js +1 -1
  16. package/dist/elements/widgets/designerView/DomConverter.d.ts +3 -3
  17. package/dist/elements/widgets/designerView/DomConverter.js +7 -4
  18. package/dist/elements/widgets/designerView/extensions/PathExtension.d.ts +0 -3
  19. package/dist/elements/widgets/designerView/extensions/PathExtension.js +79 -45
  20. package/dist/elements/widgets/designerView/extensions/contextMenu/CopyPasteContextMenu.js +0 -1
  21. package/dist/elements/widgets/designerView/extensions/contextMenu/PathContextMenu.d.ts +8 -0
  22. package/dist/elements/widgets/designerView/extensions/contextMenu/PathContextMenu.js +31 -0
  23. package/dist/elements/widgets/designerView/extensions/contextMenu/RectContextMenu.d.ts +8 -0
  24. package/dist/elements/widgets/designerView/extensions/contextMenu/RectContextMenu.js +34 -0
  25. package/dist/elements/widgets/designerView/tools/DrawPathTool.js +5 -1
  26. package/dist/elements/widgets/treeView/treeViewExtended.js +1 -0
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.js +1 -0
  29. package/package.json +4 -4
@@ -1,42 +1,42 @@
1
1
  import { IPoint } from "../../interfaces/IPoint.js";
2
2
  export {};
3
- declare type PathDataM = {
3
+ export declare type PathDataM = {
4
4
  type: 'M' | 'm';
5
5
  values: [x: number, y: number];
6
6
  };
7
- declare type PathDataL = {
7
+ export declare type PathDataL = {
8
8
  type: 'L' | 'l';
9
9
  values: [x: number, y: number];
10
10
  };
11
- declare type PathDataT = {
11
+ export declare type PathDataT = {
12
12
  type: 'T' | 't';
13
13
  values: [x: number, y: number];
14
14
  };
15
- declare type PathDataH = {
15
+ export declare type PathDataH = {
16
16
  type: 'H' | 'h';
17
17
  values: [x: number];
18
18
  };
19
- declare type PathDataV = {
19
+ export declare type PathDataV = {
20
20
  type: 'V' | 'v';
21
21
  values: [y: number];
22
22
  };
23
- declare type PathDataZ = {
23
+ export declare type PathDataZ = {
24
24
  type: 'Z' | 'z';
25
25
  values?: [];
26
26
  };
27
- declare type PathDataC = {
27
+ export declare type PathDataC = {
28
28
  type: 'C' | 'c';
29
29
  values: [x1: number, y1: number, x2: number, y2: number, x: number, y: number];
30
30
  };
31
- declare type PathDataS = {
31
+ export declare type PathDataS = {
32
32
  type: 'S' | 's';
33
33
  values: [x2: number, y2: number, x: number, y: number];
34
34
  };
35
- declare type PathDataQ = {
35
+ export declare type PathDataQ = {
36
36
  type: 'Q' | 'q';
37
37
  values: [x1: number, y1: number, x: number, y: number];
38
38
  };
39
- declare type PathDataA = {
39
+ export declare type PathDataA = {
40
40
  type: 'A' | 'a';
41
41
  values: [rx: number, ry: number, ang: number, flag1: 0 | 1, flag2: 0 | 1, x: number, y: number];
42
42
  };
@@ -47,6 +47,7 @@ export declare function straightenLine(p1: IPoint, p2: IPoint): IPoint;
47
47
  export declare function calculateNormLegth(p1: IPoint, p2: IPoint): number;
48
48
  export declare function calculateAlpha(p1: IPoint, p2: IPoint): number;
49
49
  export declare function moveSVGPath(path: SVGPathElement, xFactor: number, yFactor: number): string;
50
+ export declare function createPathD(path: PathData[]): string;
50
51
  declare global {
51
52
  interface SVGGraphicsElement {
52
53
  getPathData(options?: {
@@ -941,3 +941,38 @@ export function moveSVGPath(path, xFactor, yFactor) {
941
941
  }
942
942
  return newPathData;
943
943
  }
944
+ export function createPathD(path) {
945
+ let pathD = "";
946
+ for (let p of path) {
947
+ switch (p.type) {
948
+ case 'M':
949
+ pathD += p.type + p.values[0] + " " + p.values[1];
950
+ break;
951
+ case 'L':
952
+ pathD += p.type + p.values[0] + " " + p.values[1];
953
+ break;
954
+ case 'H':
955
+ break;
956
+ case 'V':
957
+ break;
958
+ case 'Z':
959
+ pathD += p.type;
960
+ break;
961
+ case 'C':
962
+ case 'c':
963
+ pathD += p.type + p.values[0] + " " + p.values[1] + " " + p.values[2] + " " + p.values[3] + " " + p.values[4] + " " + p.values[5];
964
+ break;
965
+ case 'S':
966
+ break;
967
+ case 'Q':
968
+ case 'q':
969
+ pathD += p.type + p.values[0] + " " + p.values[1] + " " + p.values[2] + " " + p.values[3];
970
+ break;
971
+ case 'T':
972
+ break;
973
+ case 'A':
974
+ break;
975
+ }
976
+ }
977
+ return pathD;
978
+ }
@@ -52,6 +52,8 @@ import { DrawRectTool } from '../widgets/designerView/tools/DrawRectTool.js';
52
52
  import { DrawEllipsisTool } from '../widgets/designerView/tools/DrawEllipsisTool.js';
53
53
  import { DrawLineTool } from '../widgets/designerView/tools/DrawLineTool.js';
54
54
  import { HtmlWriterService } from './htmlWriterService/HtmlWriterService.js';
55
+ import { RectContextMenu } from '../widgets/designerView/extensions/contextMenu/RectContextMenu.js';
56
+ import { PathContextMenu } from '../widgets/designerView/extensions/contextMenu/PathContextMenu.js';
55
57
  export function createDefaultServiceContainer() {
56
58
  let serviceContainer = new ServiceContainer();
57
59
  serviceContainer.register("propertyService", new PolymerPropertiesService());
@@ -125,7 +127,9 @@ export function createDefaultServiceContainer() {
125
127
  new CopyPasteContextMenu(),
126
128
  new ZMoveContextMenu(),
127
129
  new MultipleItemsSelectedContextMenu(),
128
- new ItemsBelowContextMenu()
130
+ new PathContextMenu(),
131
+ new RectContextMenu(),
132
+ new ItemsBelowContextMenu(),
129
133
  ];
130
134
  return serviceContainer;
131
135
  }
@@ -0,0 +1,10 @@
1
+ import { IDesignItem } from '../../item/IDesignItem.js';
2
+ import { IHtmlWriterService } from './IHtmlWriterService.js';
3
+ import { IHtmlWriterOptions } from './IHtmlWriterOptions.js';
4
+ import { IndentedTextWriter } from '../../helper/IndentedTextWriter.js';
5
+ import { IStringPosition } from './IStringPosition.js';
6
+ export declare abstract class AbstractHtmlWriterService implements IHtmlWriterService {
7
+ abstract write(indentedTextWriter: IndentedTextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): any;
8
+ writeAttributes(indentedTextWriter: IndentedTextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
9
+ writeStyles(indentedTextWriter: IndentedTextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
10
+ }
@@ -0,0 +1,62 @@
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter.js';
2
+ import { CssCombiner } from '../../helper/CssCombiner.js';
3
+ import { PropertiesHelper } from '../propertiesService/services/PropertiesHelper.js';
4
+ export class AbstractHtmlWriterService {
5
+ writeAttributes(indentedTextWriter, designItem, options) {
6
+ if (designItem.hasAttributes) {
7
+ for (const a of designItem.attributes) {
8
+ indentedTextWriter.write(' ');
9
+ if (typeof a[1] === 'string') {
10
+ if (a[1] === "")
11
+ indentedTextWriter.write(a[0]);
12
+ else {
13
+ if (options.parseJsonInAttributes &&
14
+ ((a[1].startsWith('{') && !a[1].startsWith('{{') && a[1].endsWith('}')) ||
15
+ (a[1].startsWith('[') && !a[1].startsWith('[[') && a[1].endsWith(']')))) {
16
+ try {
17
+ let j = JSON.parse(a[1]);
18
+ let txt;
19
+ if (options.jsonWriteMode == 'beauty')
20
+ txt = JSON.stringify(j, null, 2);
21
+ else
22
+ txt = JSON.stringify(j);
23
+ indentedTextWriter.write(a[0] + '=\'' + DomConverter.normalizeAttributeValue(txt, true) + '\'');
24
+ continue;
25
+ }
26
+ catch { }
27
+ }
28
+ const content = DomConverter.normalizeAttributeValue(a[1]);
29
+ if (content.indexOf('&quot;')) {
30
+ const contentSingle = DomConverter.normalizeAttributeValue(a[1], true);
31
+ if (contentSingle.length < content.length)
32
+ indentedTextWriter.write(a[0] + '=\'' + contentSingle + '\'');
33
+ else
34
+ indentedTextWriter.write(a[0] + '="' + content + '"');
35
+ }
36
+ else
37
+ indentedTextWriter.write(a[0] + '="' + content + '"');
38
+ }
39
+ }
40
+ else if (!a[1])
41
+ indentedTextWriter.write(a[0]);
42
+ else {
43
+ //TODO: writing of bindings, really ???
44
+ }
45
+ }
46
+ }
47
+ }
48
+ writeStyles(indentedTextWriter, designItem, options) {
49
+ if (designItem.hasStyles) {
50
+ indentedTextWriter.write(' style="');
51
+ let styles = designItem.styles;
52
+ if (options.compressCssToShorthandProperties)
53
+ styles = CssCombiner.combine(styles);
54
+ for (const s of styles) {
55
+ if (s[0]) {
56
+ indentedTextWriter.write(PropertiesHelper.camelToDashCase(s[0]) + ':' + DomConverter.normalizeAttributeValue(s[1]) + ';');
57
+ }
58
+ }
59
+ indentedTextWriter.write('"');
60
+ }
61
+ }
62
+ }
@@ -1,8 +1,8 @@
1
- import { IDesignItem } from '../../item/IDesignItem';
2
- import { IHtmlWriterService } from './IHtmlWriterService';
3
- import { IHtmlWriterOptions } from './IHtmlWriterOptions';
4
- import { IndentedTextWriter } from '../../helper/IndentedTextWriter';
5
- import { IStringPosition } from './IStringPosition';
1
+ import { IDesignItem } from '../../item/IDesignItem.js';
2
+ import { IHtmlWriterService } from './IHtmlWriterService.js';
3
+ import { IHtmlWriterOptions } from './IHtmlWriterOptions.js';
4
+ import { IndentedTextWriter } from '../../helper/IndentedTextWriter.js';
5
+ import { IStringPosition } from './IStringPosition.js';
6
6
  declare enum ElementContainerType {
7
7
  block = 0,
8
8
  complex = 1
@@ -1,7 +1,7 @@
1
- import { DomConverter } from '../../widgets/designerView/DomConverter';
2
- import { CssCombiner } from '../../helper/CssCombiner';
3
- import { NodeType } from '../../item/NodeType';
4
- import { PropertiesHelper } from '../propertiesService/services/PropertiesHelper';
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter.js';
2
+ import { CssCombiner } from '../../helper/CssCombiner.js';
3
+ import { NodeType } from '../../item/NodeType.js';
4
+ import { PropertiesHelper } from '../propertiesService/services/PropertiesHelper.js';
5
5
  import { ElementDisplayType, getElementDisplaytype } from '../../helper/ElementHelper.js';
6
6
  var ElementContainerType;
7
7
  (function (ElementContainerType) {
@@ -0,0 +1,12 @@
1
+ import { IDesignItem } from '../../item/IDesignItem';
2
+ import { IHtmlWriterService } from './IHtmlWriterService';
3
+ import { IHtmlWriterOptions } from './IHtmlWriterOptions';
4
+ import { IndentedTextWriter } from '../../helper/IndentedTextWriter';
5
+ import { IStringPosition } from './IStringPosition';
6
+ export declare class HtmlWriterService implements IHtmlWriterService {
7
+ private _conditionalyWriteIndent;
8
+ private _conditionalyWriteNewline;
9
+ write(indentedTextWriter: IndentedTextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): void;
10
+ private internalWrite;
11
+ private writeTextNode;
12
+ }
@@ -0,0 +1,118 @@
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter';
2
+ import { CssCombiner } from '../../helper/CssCombiner';
3
+ import { NodeType } from '../../item/NodeType';
4
+ import { PropertiesHelper } from '../propertiesService/services/PropertiesHelper';
5
+ import { isEmptyTextNode, isInline } from '../../helper/ElementHelper.js';
6
+ export class HtmlWriterService {
7
+ _conditionalyWriteIndent(indentedTextWriter, designItem) {
8
+ if ((designItem.element instanceof HTMLElement && !isInline(designItem.element)) ||
9
+ (designItem.element.previousElementSibling instanceof HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
10
+ (designItem.element.previousElementSibling == null && !isInline(designItem.element.parentElement) && (designItem.element.previousSibling == null || isEmptyTextNode(designItem.element.previousSibling))))
11
+ indentedTextWriter.writeIndent();
12
+ }
13
+ _conditionalyWriteNewline(indentedTextWriter, designItem) {
14
+ if ((designItem.element instanceof HTMLElement && !isInline(designItem.element)) ||
15
+ (designItem.element.nextElementSibling instanceof HTMLElement && !isInline(designItem.element.nextElementSibling)))
16
+ indentedTextWriter.writeNewline();
17
+ }
18
+ write(indentedTextWriter, designItems, rootContainerKeepInline, options, designItemsAssignmentList) {
19
+ for (const d of designItems) {
20
+ this.internalWrite(indentedTextWriter, d, options, designItemsAssignmentList);
21
+ }
22
+ }
23
+ internalWrite(indentedTextWriter, designItem, options, designItemsAssignmentList) {
24
+ let start = indentedTextWriter.position;
25
+ if (designItem.nodeType == NodeType.TextNode) {
26
+ if (isEmptyTextNode(designItem.element) &&
27
+ ((designItem.element.previousSibling instanceof HTMLElement && !isInline(designItem.element.previousSibling)) ||
28
+ (designItem.element.nextSibling instanceof HTMLElement && !isInline(designItem.element.nextSibling)))) {
29
+ }
30
+ else
31
+ this.writeTextNode(indentedTextWriter, designItem, true);
32
+ }
33
+ else if (designItem.nodeType == NodeType.Comment) {
34
+ this._conditionalyWriteIndent(indentedTextWriter, designItem);
35
+ indentedTextWriter.write('<!--' + designItem.content + '-->');
36
+ this._conditionalyWriteNewline(indentedTextWriter, designItem);
37
+ }
38
+ else {
39
+ this._conditionalyWriteIndent(indentedTextWriter, designItem);
40
+ indentedTextWriter.write('<' + designItem.name);
41
+ if (designItem.hasAttributes) {
42
+ for (const a of designItem.attributes) {
43
+ indentedTextWriter.write(' ');
44
+ if (typeof a[1] === 'string') {
45
+ if (a[1] === "")
46
+ indentedTextWriter.write(a[0]);
47
+ else
48
+ indentedTextWriter.write(a[0] + '="' + DomConverter.normalizeAttributeValue(a[1]) + '"');
49
+ }
50
+ else if (!a[1])
51
+ indentedTextWriter.write(a[0]);
52
+ else {
53
+ //TODO: writing of bindings
54
+ }
55
+ }
56
+ }
57
+ if (designItem.hasStyles) {
58
+ indentedTextWriter.write(' style="');
59
+ let styles = designItem.styles;
60
+ if (options.compressCssToShorthandProperties)
61
+ styles = CssCombiner.combine(styles);
62
+ for (const s of styles) {
63
+ if (s[0]) {
64
+ indentedTextWriter.write(PropertiesHelper.camelToDashCase(s[0]) + ':' + DomConverter.normalizeAttributeValue(s[1]) + ';');
65
+ }
66
+ }
67
+ indentedTextWriter.write('"');
68
+ }
69
+ indentedTextWriter.write('>');
70
+ let contentSingleTextNode = false;
71
+ if (designItem.hasChildren) {
72
+ const children = designItem.children();
73
+ contentSingleTextNode = designItem.childCount === 1 && designItem.firstChild.nodeType === NodeType.TextNode;
74
+ if (contentSingleTextNode) {
75
+ this.writeTextNode(indentedTextWriter, designItem, false);
76
+ }
77
+ else {
78
+ if (designItem.element instanceof HTMLElement && !isInline(designItem.element)) {
79
+ indentedTextWriter.writeNewline();
80
+ indentedTextWriter.levelRaise();
81
+ }
82
+ for (const c of children) {
83
+ this.internalWrite(indentedTextWriter, c, options, designItemsAssignmentList);
84
+ let childSingleTextNode = c.childCount === 1 && c.firstChild.nodeType === NodeType.TextNode;
85
+ if (childSingleTextNode)
86
+ indentedTextWriter.writeNewline();
87
+ }
88
+ if (designItem.element instanceof HTMLElement && !isInline(designItem.element)) {
89
+ indentedTextWriter.levelShrink();
90
+ if (!indentedTextWriter.isLastCharNewline())
91
+ indentedTextWriter.writeNewline();
92
+ indentedTextWriter.writeIndent();
93
+ }
94
+ }
95
+ }
96
+ else if (designItem.hasContent) {
97
+ indentedTextWriter.write(DomConverter.normalizeContentValue(designItem.content));
98
+ }
99
+ if (!DomConverter.IsSelfClosingElement(designItem.name))
100
+ indentedTextWriter.write('</' + designItem.name + '>');
101
+ if (!contentSingleTextNode)
102
+ this._conditionalyWriteNewline(indentedTextWriter, designItem);
103
+ }
104
+ if (designItemsAssignmentList) {
105
+ designItemsAssignmentList.set(designItem, { start: start, length: indentedTextWriter.position - start - 1 });
106
+ }
107
+ }
108
+ writeTextNode(indentedTextWriter, designItem, indentAndNewline) {
109
+ let content = DomConverter.normalizeContentValue(designItem.content).trim();
110
+ if (content) {
111
+ if (indentAndNewline)
112
+ this._conditionalyWriteIndent(indentedTextWriter, designItem);
113
+ indentedTextWriter.write(content);
114
+ if (indentAndNewline)
115
+ this._conditionalyWriteNewline(indentedTextWriter, designItem);
116
+ }
117
+ }
118
+ }
@@ -1,9 +1,9 @@
1
- import { IDesignItem } from '../../item/IDesignItem';
2
- import { IHtmlWriterService } from './IHtmlWriterService';
3
- import { IHtmlWriterOptions } from './IHtmlWriterOptions';
4
- import { IndentedTextWriter } from '../../helper/IndentedTextWriter';
5
- import { IStringPosition } from './IStringPosition';
6
- export declare class HtmlWriterService implements IHtmlWriterService {
1
+ import { IDesignItem } from '../../item/IDesignItem.js';
2
+ import { IHtmlWriterOptions } from './IHtmlWriterOptions.js';
3
+ import { IndentedTextWriter } from '../../helper/IndentedTextWriter.js';
4
+ import { IStringPosition } from './IStringPosition.js';
5
+ import { AbstractHtmlWriterService } from './AbstractHtmlWriterService.js';
6
+ export declare class HtmlWriterService extends AbstractHtmlWriterService {
7
7
  private _conditionalyWriteIndent;
8
8
  private _conditionalyWriteNewline;
9
9
  write(indentedTextWriter: IndentedTextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): void;
@@ -1,9 +1,8 @@
1
- import { DomConverter } from '../../widgets/designerView/DomConverter';
2
- import { CssCombiner } from '../../helper/CssCombiner';
3
- import { NodeType } from '../../item/NodeType';
4
- import { PropertiesHelper } from '../propertiesService/services/PropertiesHelper';
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter.js';
2
+ import { NodeType } from '../../item/NodeType.js';
5
3
  import { isEmptyTextNode, isInline } from '../../helper/ElementHelper.js';
6
- export class HtmlWriterService {
4
+ import { AbstractHtmlWriterService } from './AbstractHtmlWriterService.js';
5
+ export class HtmlWriterService extends AbstractHtmlWriterService {
7
6
  _conditionalyWriteIndent(indentedTextWriter, designItem) {
8
7
  if ((designItem.element instanceof HTMLElement && !isInline(designItem.element)) ||
9
8
  (designItem.element.previousElementSibling instanceof HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
@@ -38,34 +37,8 @@ export class HtmlWriterService {
38
37
  else {
39
38
  this._conditionalyWriteIndent(indentedTextWriter, designItem);
40
39
  indentedTextWriter.write('<' + designItem.name);
41
- if (designItem.hasAttributes) {
42
- for (const a of designItem.attributes) {
43
- indentedTextWriter.write(' ');
44
- if (typeof a[1] === 'string') {
45
- if (a[1] === "")
46
- indentedTextWriter.write(a[0]);
47
- else
48
- indentedTextWriter.write(a[0] + '="' + DomConverter.normalizeAttributeValue(a[1]) + '"');
49
- }
50
- else if (!a[1])
51
- indentedTextWriter.write(a[0]);
52
- else {
53
- //TODO: writing of bindings
54
- }
55
- }
56
- }
57
- if (designItem.hasStyles) {
58
- indentedTextWriter.write(' style="');
59
- let styles = designItem.styles;
60
- if (options.compressCssToShorthandProperties)
61
- styles = CssCombiner.combine(styles);
62
- for (const s of styles) {
63
- if (s[0]) {
64
- indentedTextWriter.write(PropertiesHelper.camelToDashCase(s[0]) + ':' + DomConverter.normalizeAttributeValue(s[1]) + ';');
65
- }
66
- }
67
- indentedTextWriter.write('"');
68
- }
40
+ this.writeAttributes(indentedTextWriter, designItem, options);
41
+ this.writeStyles(indentedTextWriter, designItem, options);
69
42
  indentedTextWriter.write('>');
70
43
  let contentSingleTextNode = false;
71
44
  if (designItem.hasChildren) {
@@ -2,4 +2,6 @@ export declare class IHtmlWriterOptions {
2
2
  beautifyOutput: boolean;
3
3
  compressCssToShorthandProperties: boolean;
4
4
  writeDesignerProperties: boolean;
5
+ parseJsonInAttributes: boolean;
6
+ jsonWriteMode: 'min' | 'beauty';
5
7
  }
@@ -1,5 +1,7 @@
1
1
  export class IHtmlWriterOptions {
2
- beautifyOutput;
3
- compressCssToShorthandProperties;
4
- writeDesignerProperties;
2
+ beautifyOutput = true;
3
+ compressCssToShorthandProperties = true;
4
+ writeDesignerProperties = true;
5
+ parseJsonInAttributes = true;
6
+ jsonWriteMode = 'min';
5
7
  }
@@ -78,7 +78,9 @@ export class WebcomponentManifestParserService extends UnkownElementPropertiesSe
78
78
  return new Promise((resolve, reject) => { this._resolveStored.push(resolve); this._rejectStored.push(reject); });
79
79
  }
80
80
  isHandledElement(designItem) {
81
- return this._elementList.find(x => x.tag == designItem.name) != null;
81
+ if (this._elementList)
82
+ return this._elementList.find(x => x.tag == designItem.name) != null;
83
+ return false;
82
84
  }
83
85
  getProperties(designItem) {
84
86
  return this._propertiesList[designItem.name];
@@ -20,7 +20,7 @@ export class CodeViewCodeMirror extends BaseCustomWebComponentLazyAppend {
20
20
  constructor() {
21
21
  super();
22
22
  //@ts-ignore
23
- import("codemirror/lib/codemirror.css", { assert: { type: 'css' } }).then(x => this.shadowRoot.adoptedStyleSheets = [x.default, this.constructor.style]);
23
+ import("./codemirror/lib/codemirror.css", { assert: { type: 'css' } }).then(x => this.shadowRoot.adoptedStyleSheets = [x.default, this.constructor.style]);
24
24
  this.style.display = 'block';
25
25
  this._editor = this._getDomElement('textarea');
26
26
  }
@@ -1,7 +1,7 @@
1
- import { IDesignItem } from "../../item/IDesignItem";
2
- import { IStringPosition } from "../../services/htmlWriterService/IStringPosition";
1
+ import { IDesignItem } from "../../item/IDesignItem.js";
2
+ import { IStringPosition } from "../../services/htmlWriterService/IStringPosition.js";
3
3
  export declare class DomConverter {
4
- static normalizeAttributeValue(value: string | number): string;
4
+ static normalizeAttributeValue(value: string | number, useSingleQuotes?: boolean): string;
5
5
  static normalizeContentValue(value: string): string;
6
6
  static IsSelfClosingElement(tag: string): boolean;
7
7
  static ConvertToString(designItems: IDesignItem[], designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): string;
@@ -1,10 +1,13 @@
1
- import { IndentedTextWriter } from "../../helper/IndentedTextWriter";
1
+ import { IndentedTextWriter } from "../../helper/IndentedTextWriter.js";
2
2
  export class DomConverter {
3
- static normalizeAttributeValue(value) {
3
+ static normalizeAttributeValue(value, useSingleQuotes = false) {
4
4
  if (typeof value === 'number')
5
5
  value = value.toString();
6
- if (value)
6
+ if (value) {
7
+ if (useSingleQuotes)
8
+ return value.replaceAll('\'', '&#39;');
7
9
  return value.replaceAll('"', '&quot;');
10
+ }
8
11
  return value;
9
12
  }
10
13
  static normalizeContentValue(value) {
@@ -31,7 +34,7 @@ export class DomConverter {
31
34
  }
32
35
  static ConvertToString(designItems, designItemsAssignmentList) {
33
36
  let itw = new IndentedTextWriter();
34
- let options = { beautifyOutput: true, writeDesignerProperties: true, compressCssToShorthandProperties: true };
37
+ let options = { beautifyOutput: true, writeDesignerProperties: true, compressCssToShorthandProperties: true, parseJsonInAttributes: true, jsonWriteMode: 'beauty' };
35
38
  designItems[0].serviceContainer.htmlWriterService.write(itw, designItems, true, options, designItemsAssignmentList);
36
39
  return itw.getString();
37
40
  }
@@ -2,7 +2,6 @@ import { IDesignItem } from "../../../item/IDesignItem";
2
2
  import { IDesignerCanvas } from "../IDesignerCanvas";
3
3
  import { AbstractExtension } from "./AbstractExtension";
4
4
  import "../../../helper/PathDataPolyfill";
5
- import { IPoint } from "../../../../interfaces/IPoint";
6
5
  import { IExtensionManager } from "./IExtensionManger";
7
6
  import { PathData } from "../../../helper/PathDataPolyfill";
8
7
  export declare class PathExtension extends AbstractExtension {
@@ -15,10 +14,8 @@ export declare class PathExtension extends AbstractExtension {
15
14
  constructor(extensionManager: IExtensionManager, designerView: IDesignerCanvas, extendedItem: IDesignItem);
16
15
  extend(): void;
17
16
  pointerEvent(event: PointerEvent, circle: SVGCircleElement, p: PathData, index: number): void;
18
- _drawPath(path: PathData[], index: number): string;
19
17
  _drawPathCircle(x: number, y: number, p: PathData, index: number): void;
20
18
  _drawPathLine(x1: number, y1: number, x2: number, y2: number): void;
21
- _drawHelpLine(pStart: IPoint, pEnd: IPoint): void;
22
19
  refresh(): void;
23
20
  dispose(): void;
24
21
  }
@@ -1,6 +1,8 @@
1
1
  import { AbstractExtension } from "./AbstractExtension";
2
2
  import "../../../helper/PathDataPolyfill";
3
3
  import { EventNames } from "../../../../enums/EventNames";
4
+ import { createPathD } from "../../../helper/PathDataPolyfill";
5
+ import { ContextMenuHelper } from "../../../helper/contextMenu/ContextMenuHelper";
4
6
  export class PathExtension extends AbstractExtension {
5
7
  //private _itemRect: DOMRect;
6
8
  //private _svgRect: DOMRect;
@@ -17,7 +19,7 @@ export class PathExtension extends AbstractExtension {
17
19
  //this._itemRect = this.extendedItem.element.getBoundingClientRect();
18
20
  //this._svgRect = (<SVGGeometryElement>this.extendedItem.element).ownerSVGElement.getBoundingClientRect();
19
21
  this._parentRect = this.extendedItem.element.parentElement.getBoundingClientRect();
20
- this._pathdata = this.extendedItem.node.getPathData({ normalize: true });
22
+ this._pathdata = this.extendedItem.node.getPathData({ normalize: false });
21
23
  for (let p of this._pathdata) {
22
24
  switch (p.type) {
23
25
  case 'M':
@@ -26,6 +28,7 @@ export class PathExtension extends AbstractExtension {
26
28
  break;
27
29
  case 'L':
28
30
  this._drawPathCircle(p.values[0], p.values[1], p, 0);
31
+ this._lastPos = { x: p.values[0], y: p.values[1] };
29
32
  break;
30
33
  case 'H':
31
34
  break;
@@ -56,6 +59,8 @@ export class PathExtension extends AbstractExtension {
56
59
  case 'Q':
57
60
  this._drawPathCircle(p.values[0], p.values[1], p, 0);
58
61
  this._drawPathCircle(p.values[2], p.values[3], p, 2);
62
+ this._drawPathLine(this._lastPos.x, this._lastPos.y, p.values[0], p.values[1]);
63
+ this._drawPathLine(p.values[0], p.values[1], p.values[2], p.values[3]);
59
64
  break;
60
65
  case 'T':
61
66
  this._drawPathCircle(p.values[0], p.values[1], p, 0);
@@ -103,7 +108,7 @@ export class PathExtension extends AbstractExtension {
103
108
  circle.setAttribute("cx", (this._circlePos.x + dx).toString());
104
109
  circle.setAttribute("cy", (this._circlePos.y + dy).toString());
105
110
  }
106
- this.extendedItem.element.setAttribute("d", this._drawPath(this._pathdata, index));
111
+ this.extendedItem.element.setAttribute("d", createPathD(this._pathdata));
107
112
  }
108
113
  break;
109
114
  case EventNames.PointerUp:
@@ -111,61 +116,90 @@ export class PathExtension extends AbstractExtension {
111
116
  this._startPos = null;
112
117
  this._circlePos = null;
113
118
  this._lastPos = null;
114
- this.extendedItem.setAttribute('d', this._drawPath(this._pathdata, index));
119
+ this.extendedItem.setAttribute('d', createPathD(this._pathdata));
115
120
  break;
116
121
  }
117
122
  }
118
- _drawPath(path, index) {
119
- let pathD = "";
120
- for (let p of path) {
121
- switch (p.type) {
122
- case 'M':
123
- pathD += p.type + p.values[0] + " " + p.values[1];
124
- break;
125
- case 'L':
126
- pathD += p.type + p.values[0] + " " + p.values[1];
127
- break;
128
- case 'H':
129
- break;
130
- case 'V':
131
- break;
132
- case 'Z':
133
- break;
134
- case 'C':
135
- case 'c':
136
- pathD += p.type + p.values[0] + " " + p.values[1] + " " + p.values[2] + " " + p.values[3] + " " + p.values[4] + " " + p.values[5];
137
- break;
138
- case 'S':
139
- break;
140
- case 'Q':
141
- break;
142
- case 'T':
143
- break;
144
- case 'A':
145
- break;
123
+ _drawPathCircle(x, y, p, index) {
124
+ const items = [];
125
+ const pidx = this._pathdata.indexOf(p);
126
+ items.push({
127
+ title: 'delete point', action: () => {
128
+ this._pathdata.splice(pidx, 1);
129
+ if (pidx == 0)
130
+ this._pathdata[0].type = 'M';
131
+ this.extendedItem.setAttribute('d', createPathD(this._pathdata));
132
+ }
133
+ });
134
+ items.push({
135
+ title: 'insert point after', action: () => {
136
+ const l = { type: 'L', values: [p.values[0], p.values[1]] };
137
+ this._pathdata.splice(pidx + 1, 0, l);
138
+ this.extendedItem.setAttribute('d', createPathD(this._pathdata));
146
139
  }
140
+ });
141
+ if (pidx != 0) {
142
+ items.push({
143
+ title: 'convert to quadratic bézier', action: () => {
144
+ const p1x = this._pathdata[pidx - 1].values[0];
145
+ const p1y = this._pathdata[pidx - 1].values[1];
146
+ const p2x = this._pathdata[pidx].values[0];
147
+ const p2y = this._pathdata[pidx].values[1];
148
+ const mpx = (p2x + p1x) * 0.5;
149
+ const mpy = (p2y + p1y) * 0.5;
150
+ const theta = Math.atan2(p2y - p1y, p2x - p1x) - Math.PI / 2;
151
+ const offset = 50;
152
+ const c1x = mpx + offset * Math.cos(theta);
153
+ const c1y = mpy + offset * Math.sin(theta);
154
+ this._pathdata[pidx].type = 'Q';
155
+ this._pathdata[pidx].values[0] = c1x;
156
+ this._pathdata[pidx].values[1] = c1y;
157
+ this._pathdata[pidx].values[2] = p2x;
158
+ this._pathdata[pidx].values[3] = p2y;
159
+ this.extendedItem.setAttribute('d', createPathD(this._pathdata));
160
+ }
161
+ });
147
162
  }
148
- return pathD;
149
- console.log(pathD);
150
- }
151
- _drawPathCircle(x, y, p, index) {
152
- let circle = this._drawCircle(this._parentRect.x - this.designerCanvas.containerBoundingRect.x + x, this._parentRect.y - this.designerCanvas.containerBoundingRect.y + y, 3, 'svg-path');
163
+ if (pidx != 0) {
164
+ items.push({
165
+ title: 'convert to cubic bézier', action: () => {
166
+ const p1x = this._pathdata[pidx - 1].values[0];
167
+ const p1y = this._pathdata[pidx - 1].values[1];
168
+ const p2x = this._pathdata[pidx].values[0];
169
+ const p2y = this._pathdata[pidx].values[1];
170
+ const mpx = (p2x + p1x) * 0.5;
171
+ const mpy = (p2y + p1y) * 0.5;
172
+ const theta = Math.atan2(p2y - p1y, p2x - p1x) - Math.PI / 2;
173
+ const offset = 50;
174
+ let c1x = mpx + offset * Math.cos(theta);
175
+ let c1y = mpy + offset * Math.sin(theta);
176
+ c1x = p.values[0] + 2 * (p1x - p.values[0]) / 3;
177
+ c1y = p.values[1] + 2 * (p1y - p.values[1]) / 3;
178
+ const c2x = x + 2 * (p1x - x) / 3;
179
+ const c2y = y + 2 * (p1y - y) / 3;
180
+ this._pathdata[pidx].type = 'C';
181
+ this._pathdata[pidx].values[0] = c1x;
182
+ this._pathdata[pidx].values[1] = c1y;
183
+ this._pathdata[pidx].values[2] = c2x;
184
+ this._pathdata[pidx].values[3] = c2y;
185
+ this._pathdata[pidx].values[4] = p2x;
186
+ this._pathdata[pidx].values[5] = p2y;
187
+ this.extendedItem.setAttribute('d', createPathD(this._pathdata));
188
+ }
189
+ });
190
+ }
191
+ let circle = this._drawCircle(this._parentRect.x - this.designerCanvas.containerBoundingRect.x + x, this._parentRect.y - this.designerCanvas.containerBoundingRect.y + y, 5, 'svg-path');
153
192
  circle.addEventListener(EventNames.PointerDown, event => this.pointerEvent(event, circle, p, index));
154
193
  circle.addEventListener(EventNames.PointerMove, event => this.pointerEvent(event, circle, p, index));
155
194
  circle.addEventListener(EventNames.PointerUp, event => this.pointerEvent(event, circle, p, index));
195
+ circle.addEventListener(EventNames.ContextMenu, event => {
196
+ event.preventDefault();
197
+ ContextMenuHelper.showContextMenu(null, event, null, items);
198
+ });
156
199
  }
157
200
  _drawPathLine(x1, y1, x2, y2) {
158
201
  this._drawLine(this._parentRect.x - this.designerCanvas.containerBoundingRect.x + x1, this._parentRect.y - this.designerCanvas.containerBoundingRect.y + y1, this._parentRect.x - this.designerCanvas.containerBoundingRect.x + x2, this._parentRect.y - this.designerCanvas.containerBoundingRect.y + y2, 'svg-path-line');
159
202
  }
160
- _drawHelpLine(pStart, pEnd) {
161
- let line;
162
- line.setAttribute("stroke", "yellow");
163
- line.setAttribute("stroke-width", "2");
164
- line.setAttribute("x1", pStart.x.toString());
165
- line.setAttribute("y1", pStart.y.toString());
166
- line.setAttribute("x2", pEnd.x.toString());
167
- line.setAttribute("y2", pEnd.y.toString());
168
- }
169
203
  refresh() {
170
204
  this._removeAllOverlays();
171
205
  this.extend();
@@ -8,7 +8,6 @@ export class CopyPasteContextMenu {
8
8
  { title: 'copy', action: () => { designerView.executeCommand({ type: CommandType.copy }); } },
9
9
  { title: 'cut', action: () => { designerView.executeCommand({ type: CommandType.cut }); } },
10
10
  { title: 'paste', action: () => { designerView.executeCommand({ type: CommandType.paste }); } },
11
- { title: '-' },
12
11
  { title: 'delete', action: () => { designerView.executeCommand({ type: CommandType.delete }); } },
13
12
  { title: '-' }
14
13
  ];
@@ -0,0 +1,8 @@
1
+ import { IContextMenuItem } from "../../../../helper/contextMenu/IContextmenuItem";
2
+ import { IDesignItem } from "../../../../item/IDesignItem";
3
+ import { IDesignerCanvas } from "../../IDesignerCanvas";
4
+ import { ContextmenuInitiator, IContextMenuExtension } from "./IContextMenuExtension";
5
+ export declare class PathContextMenu implements IContextMenuExtension {
6
+ shouldProvideContextmenu(event: MouseEvent, designerView: IDesignerCanvas, designItem: IDesignItem, initiator: ContextmenuInitiator): boolean;
7
+ provideContextMenuItems(event: MouseEvent, designerCanvas: IDesignerCanvas, designItem: IDesignItem): IContextMenuItem[];
8
+ }
@@ -0,0 +1,31 @@
1
+ import { createPathD } from "../../../../helper/PathDataPolyfill";
2
+ export class PathContextMenu {
3
+ shouldProvideContextmenu(event, designerView, designItem, initiator) {
4
+ if (designItem.element instanceof SVGPathElement)
5
+ return true;
6
+ return false;
7
+ }
8
+ provideContextMenuItems(event, designerCanvas, designItem) {
9
+ const pathdata = designItem.node.getPathData({ normalize: true });
10
+ const items = [];
11
+ const lastType = pathdata[pathdata.length - 1].type;
12
+ items.push({ title: '-' });
13
+ if (lastType == 'z' || lastType == 'Z') {
14
+ items.push({
15
+ title: 'open path ', action: () => {
16
+ pathdata.splice(pathdata.length - 1, 1);
17
+ designItem.setAttribute('d', createPathD(pathdata));
18
+ }
19
+ });
20
+ }
21
+ else {
22
+ items.push({
23
+ title: 'close path ', action: () => {
24
+ pathdata.push({ type: 'Z' });
25
+ designItem.setAttribute('d', createPathD(pathdata));
26
+ }
27
+ });
28
+ }
29
+ return items;
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ import { IContextMenuItem } from "../../../../helper/contextMenu/IContextmenuItem";
2
+ import { IDesignItem } from "../../../../item/IDesignItem";
3
+ import { IDesignerCanvas } from "../../IDesignerCanvas";
4
+ import { ContextmenuInitiator, IContextMenuExtension } from "./IContextMenuExtension";
5
+ export declare class RectContextMenu implements IContextMenuExtension {
6
+ shouldProvideContextmenu(event: MouseEvent, designerView: IDesignerCanvas, designItem: IDesignItem, initiator: ContextmenuInitiator): boolean;
7
+ provideContextMenuItems(event: MouseEvent, designerCanvas: IDesignerCanvas, designItem: IDesignItem): IContextMenuItem[];
8
+ }
@@ -0,0 +1,34 @@
1
+ import { DeleteAction } from "../../../../..";
2
+ import { DesignItem } from "../../../../item/DesignItem";
3
+ import { InsertAction } from "../../../../services/undoService/transactionItems/InsertAction";
4
+ export class RectContextMenu {
5
+ shouldProvideContextmenu(event, designerView, designItem, initiator) {
6
+ if (designItem.element instanceof SVGRectElement)
7
+ return true;
8
+ return false;
9
+ }
10
+ provideContextMenuItems(event, designerCanvas, designItem) {
11
+ return [
12
+ { title: '-' },
13
+ {
14
+ title: 'convert to path', action: () => {
15
+ let rect = designItem.element;
16
+ let pathD = "";
17
+ pathD += "M" + rect.x.baseVal.value + " " + rect.y.baseVal.value +
18
+ "L" + (rect.x.baseVal.value + rect.width.baseVal.value) + " " + rect.y.baseVal.value +
19
+ "L" + (rect.x.baseVal.value + rect.width.baseVal.value) + " " + (rect.y.baseVal.value + rect.height.baseVal.value) +
20
+ "L" + rect.x.baseVal.value + " " + (rect.y.baseVal.value + rect.height.baseVal.value) +
21
+ "Z";
22
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
23
+ path.setAttribute("d", pathD);
24
+ path.setAttribute("stroke", rect.getAttribute("stroke"));
25
+ path.setAttribute("fill", rect.getAttribute("fill"));
26
+ path.setAttribute("stroke-width", rect.getAttribute("stroke-width"));
27
+ const di = DesignItem.createDesignItemFromInstance(path, designerCanvas.serviceContainer, designerCanvas.instanceServiceContainer);
28
+ designerCanvas.instanceServiceContainer.undoService.execute(new InsertAction(designItem.parent, designItem.childCount, di));
29
+ designerCanvas.instanceServiceContainer.undoService.execute(new DeleteAction([designItem]));
30
+ }
31
+ }
32
+ ];
33
+ }
34
+ }
@@ -13,7 +13,7 @@ export class DrawPathTool {
13
13
  _pointerMoved = false;
14
14
  _eventStarted = false;
15
15
  _lastPoint;
16
- _startPoint = { x: 0, y: 0 };
16
+ _startPoint;
17
17
  constructor() {
18
18
  }
19
19
  activated(serviceContainer) {
@@ -43,6 +43,9 @@ export class DrawPathTool {
43
43
  if (this._lastPoint == null) {
44
44
  this._lastPoint = currentPoint;
45
45
  }
46
+ if (this._startPoint == null) {
47
+ this._startPoint = currentPoint;
48
+ }
46
49
  break;
47
50
  case EventNames.PointerMove:
48
51
  if (this._eventStarted) {
@@ -108,6 +111,7 @@ export class DrawPathTool {
108
111
  //designerView.rootDesignItem.element.appendChild(svg);
109
112
  this._path = null;
110
113
  this._pathD = null;
114
+ this._lastPoint = null;
111
115
  const di = DesignItem.createDesignItemFromInstance(svg, designerCanvas.serviceContainer, designerCanvas.instanceServiceContainer);
112
116
  designerCanvas.instanceServiceContainer.undoService.execute(new InsertAction(designerCanvas.rootDesignItem, designerCanvas.rootDesignItem.childCount, di));
113
117
  designerCanvas.serviceContainer.globalContext.finishedWithTool(this);
@@ -59,6 +59,7 @@ export class TreeViewExtended extends BaseCustomWebComponentConstructorAppend {
59
59
  background: #ffffffc9;
60
60
  width: 70px;
61
61
  justify-content: flex-end;
62
+ background: white;
62
63
  }
63
64
 
64
65
  table.fancytree-ext-table tbody tr.fancytree-selected {
package/dist/index.d.ts CHANGED
@@ -45,6 +45,7 @@ export * from "./elements/services/elementsService/JsonFileElementsService.js";
45
45
  export * from "./elements/services/elementsService/PreDefinedElementsService.js";
46
46
  export type { IHtmlWriterService } from "./elements/services/htmlWriterService/IHtmlWriterService.js";
47
47
  export type { IHtmlWriterOptions } from "./elements/services/htmlWriterService/IHtmlWriterOptions.js";
48
+ export * from "./elements/services/htmlWriterService/AbstractHtmlWriterService.js";
48
49
  export * from "./elements/services/htmlWriterService/FormatingHtmlWriterService.js";
49
50
  export * from "./elements/services/htmlWriterService/HtmlWriterService.js";
50
51
  export * from "./elements/services/htmlWriterService/LitTsElementWriterService.js";
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ export * from "./elements/services/demoProviderService/DemoProviderService.js";
26
26
  export * from "./elements/services/dragDropService/DragDropService.js";
27
27
  export * from "./elements/services/elementsService/JsonFileElementsService.js";
28
28
  export * from "./elements/services/elementsService/PreDefinedElementsService.js";
29
+ export * from "./elements/services/htmlWriterService/AbstractHtmlWriterService.js";
29
30
  export * from "./elements/services/htmlWriterService/FormatingHtmlWriterService.js";
30
31
  export * from "./elements/services/htmlWriterService/HtmlWriterService.js";
31
32
  export * from "./elements/services/htmlWriterService/LitTsElementWriterService.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A UI designer for Polymer apps",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.0.80",
4
+ "version": "0.0.81",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "",
@@ -20,7 +20,7 @@
20
20
  "@node-projects/lean-he-esm": "^3.3.0",
21
21
  "@node-projects/node-html-parser-esm": "^2.4.1",
22
22
  "@types/codemirror": "^5.60.5",
23
- "@types/jquery": "^3.5.11",
23
+ "@types/jquery": "^3.5.13",
24
24
  "@types/jquery.fancytree": "0.0.7",
25
25
  "ace-builds": "^1.4.13",
26
26
  "codemirror": "^5.65.0",
@@ -29,9 +29,9 @@
29
29
  "html2canvas": "*",
30
30
  "jest": "^27.4.7",
31
31
  "jquery": "^3.6.0",
32
- "jquery.fancytree": "^2.38.0",
32
+ "jquery.fancytree": "^2.38.1",
33
33
  "monaco-editor": "^0.31.1",
34
- "ts-jest": "^27.1.2",
34
+ "ts-jest": "^27.1.3",
35
35
  "typescript": "^4.5.4",
36
36
  "typescript-lit-html-plugin": "^0.9.0"
37
37
  },