@node-projects/web-component-designer 0.0.185 → 0.0.186
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/dist/elements/helper/ClipboardHelper.d.ts +4 -0
- package/dist/elements/helper/ClipboardHelper.js +84 -0
- package/dist/elements/services/copyPasteService/CopyPasteService.js +19 -19
- package/dist/elements/services/htmlParserService/AbstractClassElementParserService.d.ts +12 -0
- package/dist/elements/services/htmlParserService/AbstractClassElementParserService.js +120 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function copyTextToClipboard(text: any): Promise<void>;
|
|
2
|
+
export declare function copyToClipboard(items: [format: string, data: string][]): Promise<void>;
|
|
3
|
+
export declare function getTextFromClipboard(): Promise<string>;
|
|
4
|
+
export declare function getFromClipboard(): Promise<ClipboardItems>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export async function copyTextToClipboard(text) {
|
|
2
|
+
copyToClipboard(['text/plain', text]);
|
|
3
|
+
}
|
|
4
|
+
export async function copyToClipboard(items) {
|
|
5
|
+
if (navigator.clipboard) {
|
|
6
|
+
try {
|
|
7
|
+
let data = [];
|
|
8
|
+
for (let n of items) {
|
|
9
|
+
data.push(new ClipboardItem({ [n[0]]: new Blob([n[1]], { type: n[0] }) }));
|
|
10
|
+
}
|
|
11
|
+
await navigator.clipboard.write(data);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
await navigator.clipboard.writeText(items[0][1]);
|
|
15
|
+
}
|
|
16
|
+
console.info('Copy to clipboard successful');
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const textArea = document.createElement('textarea');
|
|
20
|
+
textArea.style.position = 'fixed';
|
|
21
|
+
textArea.style.top = '0';
|
|
22
|
+
textArea.style.left = '0';
|
|
23
|
+
textArea.style.width = '2em';
|
|
24
|
+
textArea.style.height = '2em';
|
|
25
|
+
textArea.style.padding = '0';
|
|
26
|
+
textArea.style.border = 'none';
|
|
27
|
+
textArea.style.outline = 'none';
|
|
28
|
+
textArea.style.boxShadow = 'none';
|
|
29
|
+
textArea.style.background = 'transparent';
|
|
30
|
+
textArea.value = items[0][1];
|
|
31
|
+
document.body.appendChild(textArea);
|
|
32
|
+
textArea.select();
|
|
33
|
+
try {
|
|
34
|
+
document.execCommand('copy');
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
try {
|
|
38
|
+
document.execCommand('copy');
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
console.error(err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
document.body.removeChild(textArea);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function getTextFromClipboard() {
|
|
48
|
+
if (navigator.clipboard) {
|
|
49
|
+
return new Promise(async (resolve, reject) => {
|
|
50
|
+
const clipText = await navigator.clipboard.readText();
|
|
51
|
+
resolve(clipText);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return new Promise(async (resolve, reject) => {
|
|
56
|
+
const textArea = document.createElement('textarea');
|
|
57
|
+
textArea.style.position = 'fixed';
|
|
58
|
+
textArea.style.top = '0';
|
|
59
|
+
textArea.style.left = '0';
|
|
60
|
+
textArea.style.width = '2em';
|
|
61
|
+
textArea.style.height = '2em';
|
|
62
|
+
textArea.style.padding = '0';
|
|
63
|
+
textArea.style.border = 'none';
|
|
64
|
+
textArea.style.outline = 'none';
|
|
65
|
+
textArea.style.boxShadow = 'none';
|
|
66
|
+
textArea.style.background = 'transparent';
|
|
67
|
+
document.body.appendChild(textArea);
|
|
68
|
+
textArea.focus();
|
|
69
|
+
textArea.select();
|
|
70
|
+
document.execCommand('paste');
|
|
71
|
+
let value = textArea.value;
|
|
72
|
+
document.body.removeChild(textArea);
|
|
73
|
+
resolve(value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function getFromClipboard() {
|
|
78
|
+
if (navigator.clipboard) {
|
|
79
|
+
return await navigator.clipboard.read();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { DomConverter } from "../../widgets/designerView/DomConverter.js";
|
|
2
|
+
import { copyToClipboard, getFromClipboard, getTextFromClipboard } from "../../helper/ClipboardHelper.js";
|
|
2
3
|
export const positionsJsonMime = 'web text/positions';
|
|
3
4
|
export class CopyPasteService {
|
|
4
5
|
async copyItems(designItems) {
|
|
5
6
|
const copyText = DomConverter.ConvertToString(designItems, null, false);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const data = [new ClipboardItem({ ["text/html"]: new Blob([copyText], { type: 'text/html' }), [positionsJsonMime]: new Blob([JSON.stringify(positions)], { type: positionsJsonMime }) })];
|
|
9
|
-
await navigator.clipboard.write(data);
|
|
10
|
-
}
|
|
11
|
-
catch (err) {
|
|
12
|
-
await navigator.clipboard.writeText(copyText);
|
|
13
|
-
}
|
|
7
|
+
const positions = designItems.map(x => x.instanceServiceContainer.designerCanvas.getNormalizedElementCoordinates(x.element));
|
|
8
|
+
copyToClipboard([["text/html", copyText], [positionsJsonMime, JSON.stringify(positions)]]);
|
|
14
9
|
}
|
|
15
10
|
async getPasteItems(serviceContainer, instanceServiceContainer) {
|
|
16
|
-
const items = await navigator.clipboard.read();
|
|
17
11
|
let html = '';
|
|
18
|
-
try {
|
|
19
|
-
html = await (await items[0].getType('text/html'))?.text();
|
|
20
|
-
}
|
|
21
|
-
catch { }
|
|
22
|
-
if (!html)
|
|
23
|
-
html = await (await items[0].getType('text/plain'))?.text();
|
|
24
12
|
let positions = null;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
const items = await getFromClipboard();
|
|
14
|
+
if (items != null) {
|
|
15
|
+
try {
|
|
16
|
+
html = await (await items[0].getType('text/html'))?.text();
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
if (!html)
|
|
20
|
+
html = await (await items[0].getType('text/plain'))?.text();
|
|
21
|
+
try {
|
|
22
|
+
let positionsJson = await (await items[0].getType(positionsJsonMime))?.text();
|
|
23
|
+
positions = JSON.parse(positionsJson);
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
html = await getTextFromClipboard();
|
|
28
29
|
}
|
|
29
|
-
catch { }
|
|
30
30
|
const parserService = serviceContainer.htmlParserService;
|
|
31
31
|
return [await parserService.parse(html, serviceContainer, instanceServiceContainer), positions];
|
|
32
32
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InstanceServiceContainer } from '../InstanceServiceContainer.js';
|
|
2
|
+
import { ServiceContainer } from '../ServiceContainer.js';
|
|
3
|
+
import { IHtmlParserService } from './IHtmlParserService.js';
|
|
4
|
+
import { IDesignItem } from '../../item/IDesignItem.js';
|
|
5
|
+
export declare abstract class AbstractClassElementParserService implements IHtmlParserService {
|
|
6
|
+
private _parserUrl;
|
|
7
|
+
private _esprimaUrl;
|
|
8
|
+
constructor(parserUrl?: string, esprimaUrl?: string);
|
|
9
|
+
parse(module: string, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<IDesignItem[]>;
|
|
10
|
+
private _parseDiv;
|
|
11
|
+
_createDesignItemsRecursive(item: any, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer, namespace: string): IDesignItem;
|
|
12
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { DesignItem } from '../../item/DesignItem.js';
|
|
2
|
+
import { CssAttributeParser } from '../../helper/CssAttributeParser.js';
|
|
3
|
+
import { newElementFromString } from '../../helper/ElementHelper.js';
|
|
4
|
+
import * as esprima from "esprima-next/dist/esm/esprima";
|
|
5
|
+
function* getChildNodes(node) {
|
|
6
|
+
switch (node.type) {
|
|
7
|
+
case esprima.Syntax.Program:
|
|
8
|
+
yield node.body;
|
|
9
|
+
break;
|
|
10
|
+
case esprima.Syntax.ClassDeclaration:
|
|
11
|
+
yield node.body;
|
|
12
|
+
break;
|
|
13
|
+
case esprima.Syntax.MethodDefinition:
|
|
14
|
+
yield node.value;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Alternative Parser, cause when you use the Browser, it instanciates the CusomElements, and some Elemnts remove
|
|
19
|
+
// attributes from their DOM, so you loose Data
|
|
20
|
+
export class AbstractClassElementParserService {
|
|
21
|
+
_parserUrl;
|
|
22
|
+
_esprimaUrl;
|
|
23
|
+
constructor(parserUrl = '../../../../../node-html-parser-esm/dist/index.js', esprimaUrl = '../../../../../esprima-next/dist/esm/esprima.js') {
|
|
24
|
+
this._parserUrl = parserUrl;
|
|
25
|
+
this._esprimaUrl = esprimaUrl;
|
|
26
|
+
}
|
|
27
|
+
async parse(module, serviceContainer, instanceServiceContainer) {
|
|
28
|
+
let esprima = await import(this._esprimaUrl);
|
|
29
|
+
const parsedModule = esprima.parseModule(module);
|
|
30
|
+
const classDecl = parsedModule.body.find(x => x.type == esprima.Syntax.ClassDeclaration);
|
|
31
|
+
const renderMethod = classDecl.body.body.find(x => x.type == esprima.Syntax.MethodDefinition && x.key.name == 'render');
|
|
32
|
+
const renderMethodStatement = renderMethod.value.body.body[0];
|
|
33
|
+
const taggedTemplate = renderMethodStatement.argument;
|
|
34
|
+
const templateLiteral = taggedTemplate.quasi;
|
|
35
|
+
const html = templateLiteral.quasis.map(x => x.value.raw).join();
|
|
36
|
+
//@ts-ignore
|
|
37
|
+
let parser = await import(this._parserUrl);
|
|
38
|
+
const parsed = parser.parse(html, { comment: true });
|
|
39
|
+
let designItems = [];
|
|
40
|
+
for (let p of parsed.childNodes) {
|
|
41
|
+
let di = this._createDesignItemsRecursive(p, serviceContainer, instanceServiceContainer, null);
|
|
42
|
+
if (di != null)
|
|
43
|
+
designItems.push(di);
|
|
44
|
+
else
|
|
45
|
+
console.warn("NodeHtmlParserService - could not parse element", p);
|
|
46
|
+
}
|
|
47
|
+
return designItems;
|
|
48
|
+
}
|
|
49
|
+
_parseDiv = document.createElement("div");
|
|
50
|
+
_createDesignItemsRecursive(item, serviceContainer, instanceServiceContainer, namespace) {
|
|
51
|
+
let designItem = null;
|
|
52
|
+
if (item.nodeType == 1) {
|
|
53
|
+
let element;
|
|
54
|
+
let manualCreatedElement = false;
|
|
55
|
+
if (!namespace)
|
|
56
|
+
element = newElementFromString('<' + item.rawTagName + ' ' + item.rawAttrs + '></' + item.rawTagName + '>'); // some custom elements only parse attributes during constructor call
|
|
57
|
+
if (!element) {
|
|
58
|
+
if (namespace)
|
|
59
|
+
element = document.createElementNS(namespace, item.rawTagName);
|
|
60
|
+
else
|
|
61
|
+
element = document.createElement(item.rawTagName);
|
|
62
|
+
manualCreatedElement = true;
|
|
63
|
+
}
|
|
64
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
65
|
+
let hideAtDesignTime = false;
|
|
66
|
+
let hideAtRunTime = false;
|
|
67
|
+
let lockAtDesignTime = false;
|
|
68
|
+
let style = '';
|
|
69
|
+
let attr = item.attributes;
|
|
70
|
+
for (let a in attr) {
|
|
71
|
+
if (a !== 'style') {
|
|
72
|
+
designItem._withoutUndoSetAttribute(a, attr[a]);
|
|
73
|
+
if (manualCreatedElement) {
|
|
74
|
+
element.setAttribute(a, attr[a]);
|
|
75
|
+
}
|
|
76
|
+
if (a === 'node-projects-hide-at-design-time')
|
|
77
|
+
hideAtDesignTime = true;
|
|
78
|
+
else if (a === 'node-projects-hide-at-run-time')
|
|
79
|
+
hideAtRunTime = true;
|
|
80
|
+
else if (a === 'node-projects-lock-at-design-time')
|
|
81
|
+
lockAtDesignTime = true;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
style = attr[a];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if ((element instanceof HTMLElement || element instanceof SVGElement) && style) {
|
|
88
|
+
let styleParser = new CssAttributeParser();
|
|
89
|
+
styleParser.parse(style);
|
|
90
|
+
for (let s of styleParser.entries) {
|
|
91
|
+
designItem._withoutUndoSetStyle(s.name, s.value);
|
|
92
|
+
if (manualCreatedElement) {
|
|
93
|
+
element.style[s.name] = s.value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!lockAtDesignTime && (element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
98
|
+
requestAnimationFrame(() => element.style.pointerEvents = 'auto');
|
|
99
|
+
}
|
|
100
|
+
designItem.hideAtDesignTime = hideAtDesignTime;
|
|
101
|
+
designItem.hideAtRunTime = hideAtRunTime;
|
|
102
|
+
designItem.lockAtDesignTime = lockAtDesignTime;
|
|
103
|
+
element.draggable = false; //even if it should be true, for better designer exp.
|
|
104
|
+
for (let c of item.childNodes) {
|
|
105
|
+
let di = this._createDesignItemsRecursive(c, serviceContainer, instanceServiceContainer, element instanceof SVGElement ? 'http://www.w3.org/2000/svg' : null);
|
|
106
|
+
designItem._insertChildInternal(di);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (item.nodeType == 3) {
|
|
110
|
+
this._parseDiv.innerHTML = item.rawText;
|
|
111
|
+
let element = this._parseDiv.childNodes[0];
|
|
112
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
113
|
+
}
|
|
114
|
+
else if (item.nodeType == 8) {
|
|
115
|
+
let element = document.createComment(item.rawText);
|
|
116
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
117
|
+
}
|
|
118
|
+
return designItem;
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./elements/helper/ElementHelper.js";
|
|
|
7
7
|
export * from "./elements/helper/IndentedTextWriter.js";
|
|
8
8
|
export * from "./elements/helper/PathDataPolyfill.js";
|
|
9
9
|
export * from "./elements/helper/Screenshot.js";
|
|
10
|
+
export * from "./elements/helper/ClipboardHelper.js";
|
|
10
11
|
export * from "./elements/loader/OldCustomElementsManifestLoader.js";
|
|
11
12
|
export * from "./elements/helper/w3color.js";
|
|
12
13
|
export * from "./elements/helper/contextMenu/ContextMenu.js";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./elements/helper/ElementHelper.js";
|
|
|
7
7
|
export * from "./elements/helper/IndentedTextWriter.js";
|
|
8
8
|
export * from "./elements/helper/PathDataPolyfill.js";
|
|
9
9
|
export * from "./elements/helper/Screenshot.js";
|
|
10
|
+
export * from "./elements/helper/ClipboardHelper.js";
|
|
10
11
|
export * from "./elements/loader/OldCustomElementsManifestLoader.js";
|
|
11
12
|
export * from "./elements/helper/w3color.js";
|
|
12
13
|
export * from "./elements/helper/contextMenu/ContextMenu.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.
|
|
4
|
+
"version": "0.0.186",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"author": "",
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@node-projects/base-custom-webcomponent": "^0.10.9",
|
|
17
|
-
"@types/node": "^18.11.19",
|
|
18
17
|
"construct-style-sheets-polyfill": "^3.1.0"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
@@ -23,19 +22,20 @@
|
|
|
23
22
|
"@node-projects/node-html-parser-esm": "^2.5.1",
|
|
24
23
|
"@papyrs/stylo": "^0.0.42",
|
|
25
24
|
"@types/codemirror": "^5.60.7",
|
|
26
|
-
"@types/css-tree": "^2.0
|
|
25
|
+
"@types/css-tree": "^2.3.0",
|
|
27
26
|
"@types/jquery": "^3.5.16",
|
|
28
27
|
"@types/jquery.fancytree": "0.0.7",
|
|
28
|
+
"@types/node": "^18.13.0",
|
|
29
29
|
"ace-builds": "^1.15.0",
|
|
30
30
|
"codemirror": "^6.0.1",
|
|
31
31
|
"css-tree": "^2.3.1",
|
|
32
32
|
"esprima-next": "^5.8.4",
|
|
33
33
|
"html2canvas": "*",
|
|
34
|
-
"jest": "^29.4.
|
|
34
|
+
"jest": "^29.4.2",
|
|
35
35
|
"jquery": "^3.6.3",
|
|
36
36
|
"jquery.fancytree": "^2.38.3",
|
|
37
37
|
"mdn-data": "^2.0.31",
|
|
38
|
-
"monaco-editor": "^0.
|
|
38
|
+
"monaco-editor": "^0.35.0",
|
|
39
39
|
"ts-jest": "^29.0.5",
|
|
40
40
|
"typescript": "^4.9.5",
|
|
41
41
|
"typescript-lit-html-plugin": "^0.9.0"
|