likec4 1.6.1-next.3 → 1.6.1
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/__app__/react/components.mjs +11 -12
- package/dist/__app__/src/-view-lazy-data-WZmbIsHq.js +9 -0
- package/dist/__app__/src/index-Wk755r9n.js +488 -0
- package/dist/__app__/src/main.js +33713 -99
- package/dist/__app__/tsconfig.tsbuildinfo +1 -0
- package/dist/__app__/webcomponent/webcomponent.js +15 -14
- package/dist/cli/index.mjs +181 -168
- package/package.json +12 -12
- package/react/index.mjs +11 -12
- package/dist/__app__/src/-view-lazy-data-BinAQ6yB.js +0 -1
- package/dist/__app__/src/favicon.svg +0 -6
- package/dist/__app__/src/index-Dx7-rAaw.js +0 -2
- package/dist/__app__/src/index.html +0 -14
- package/dist/__app__/src/renderIcon.js +0 -1
|
@@ -20880,13 +20880,11 @@ function DiagramContextProvider({
|
|
|
20880
20880
|
), useUpdateEffect(
|
|
20881
20881
|
() => {
|
|
20882
20882
|
if (!store.current) return;
|
|
20883
|
-
const state = store.current.getState();
|
|
20884
|
-
state.view !== view && state.updateView(view);
|
|
20885
|
-
const newProps = i$1(props, l$1);
|
|
20886
|
-
o$1(state, newProps) || store.current.setState(newProps, !1, "update incoming props");
|
|
20883
|
+
const state = store.current.getState(), newProps = i$1(props, l$1);
|
|
20884
|
+
o$1(state, newProps) || store.current.setState(newProps, !1, "update incoming props"), state.view !== view && state.updateView(view);
|
|
20887
20885
|
},
|
|
20888
20886
|
[view, props],
|
|
20889
|
-
shallowEqual
|
|
20887
|
+
(prev, next) => shallowEqual(prev[0], next[0]) && shallowEqual(prev[1], next[1])
|
|
20890
20888
|
), /* @__PURE__ */ jsx(
|
|
20891
20889
|
"div",
|
|
20892
20890
|
{
|
|
@@ -23682,7 +23680,7 @@ const Text = Text$1.withProps({
|
|
|
23682
23680
|
// tap: {
|
|
23683
23681
|
// scale: 0.9
|
|
23684
23682
|
// }
|
|
23685
|
-
}, isEqualProps = (prev, next) => prev.id === next.id && deepEqual$1(prev.selected ?? !1, next.selected ?? !1) && deepEqual$1(prev.dragging ?? !1, next.dragging ?? !1) && deepEqual$1(prev.
|
|
23683
|
+
}, isEqualProps = (prev, next) => prev.id === next.id && deepEqual$1(prev.selected ?? !1, next.selected ?? !1) && deepEqual$1(prev.dragging ?? !1, next.dragging ?? !1) && deepEqual$1(prev.width ?? 0, next.width ?? 0) && deepEqual$1(prev.height ?? 0, next.height ?? 0) && deepEqual$1(prev.data.element, next.data.element), ElementNodeMemo = memo$1(function({
|
|
23686
23684
|
id: id2,
|
|
23687
23685
|
data: {
|
|
23688
23686
|
element
|
|
@@ -23693,7 +23691,7 @@ const Text = Text$1.withProps({
|
|
|
23693
23691
|
width,
|
|
23694
23692
|
height
|
|
23695
23693
|
}) {
|
|
23696
|
-
const { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState((s2) => ({
|
|
23694
|
+
const store = useDiagramStoreApi(), { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState((s2) => ({
|
|
23697
23695
|
isHovered: s2.hoveredNodeId === id2,
|
|
23698
23696
|
isDimmed: s2.dimmed.has(id2),
|
|
23699
23697
|
isInteractive: s2.nodesDraggable || s2.nodesSelectable || !!s2.onNavigateTo,
|
|
@@ -23715,6 +23713,7 @@ const Text = Text$1.withProps({
|
|
|
23715
23713
|
animate = "selected";
|
|
23716
23714
|
break;
|
|
23717
23715
|
}
|
|
23716
|
+
const elementIcon2 = ElementIcon({ node: element, store });
|
|
23718
23717
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23719
23718
|
/* @__PURE__ */ jsx(
|
|
23720
23719
|
Handle,
|
|
@@ -23778,11 +23777,11 @@ const Text = Text$1.withProps({
|
|
|
23778
23777
|
{
|
|
23779
23778
|
className: clsx(
|
|
23780
23779
|
elementDataContainer,
|
|
23781
|
-
n$4(
|
|
23780
|
+
n$4(elementIcon2) && hasIcon,
|
|
23782
23781
|
"likec4-element"
|
|
23783
23782
|
),
|
|
23784
23783
|
children: [
|
|
23785
|
-
|
|
23784
|
+
elementIcon2,
|
|
23786
23785
|
/* @__PURE__ */ jsxs("div", { className: clsx(elementTextData, "likec4-element-main-props"), children: [
|
|
23787
23786
|
/* @__PURE__ */ jsx(
|
|
23788
23787
|
Text,
|
|
@@ -23823,13 +23822,12 @@ const Text = Text$1.withProps({
|
|
|
23823
23822
|
}
|
|
23824
23823
|
)
|
|
23825
23824
|
] });
|
|
23826
|
-
}, isEqualProps), ElementIcon = ({ node }) => {
|
|
23827
|
-
const RenderIcon = useDiagramState((s2) => s2.renderIcon);
|
|
23825
|
+
}, isEqualProps), ElementIcon = ({ node, store }) => {
|
|
23828
23826
|
if (!node.icon)
|
|
23829
23827
|
return null;
|
|
23830
23828
|
if (node.icon.startsWith("http://") || node.icon.startsWith("https://"))
|
|
23831
23829
|
return /* @__PURE__ */ jsx("div", { className: clsx(elementIcon, "likec4-element-icon"), children: /* @__PURE__ */ jsx("img", { src: node.icon, alt: node.title }) });
|
|
23832
|
-
const icon = RenderIcon ? /* @__PURE__ */ jsx(RenderIcon, { node }) : null;
|
|
23830
|
+
const RenderIcon = store.getState().renderIcon, icon = RenderIcon ? /* @__PURE__ */ jsx(RenderIcon, { node }) : null;
|
|
23833
23831
|
return icon ? /* @__PURE__ */ jsx("div", { className: clsx(elementIcon, "likec4-element-icon"), children: icon }) : null;
|
|
23834
23832
|
};
|
|
23835
23833
|
function useXYFlowEvents() {
|
|
@@ -24693,6 +24691,7 @@ const XYFlowInner = memo$1(function({
|
|
|
24693
24691
|
children2
|
|
24694
24692
|
] });
|
|
24695
24693
|
}, shallowEqual);
|
|
24694
|
+
XYFlowInner.displayName = "XYFlowInner";
|
|
24696
24695
|
function LikeC4Diagram({
|
|
24697
24696
|
view,
|
|
24698
24697
|
className,
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
function resolveUrl(url, baseUrl) {
|
|
2
|
+
if (url.match(/^[a-z]+:\/\//i))
|
|
3
|
+
return url;
|
|
4
|
+
if (url.match(/^\/\//))
|
|
5
|
+
return window.location.protocol + url;
|
|
6
|
+
if (url.match(/^[a-z]+:/i))
|
|
7
|
+
return url;
|
|
8
|
+
const doc = document.implementation.createHTMLDocument(), base = doc.createElement("base"), a = doc.createElement("a");
|
|
9
|
+
return doc.head.appendChild(base), doc.body.appendChild(a), baseUrl && (base.href = baseUrl), a.href = url, a.href;
|
|
10
|
+
}
|
|
11
|
+
const uuid = /* @__PURE__ */ (() => {
|
|
12
|
+
let counter = 0;
|
|
13
|
+
const random = () => (
|
|
14
|
+
// eslint-disable-next-line no-bitwise
|
|
15
|
+
`0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4)
|
|
16
|
+
);
|
|
17
|
+
return () => (counter += 1, `u${random()}${counter}`);
|
|
18
|
+
})();
|
|
19
|
+
function toArray(arrayLike) {
|
|
20
|
+
const arr = [];
|
|
21
|
+
for (let i = 0, l = arrayLike.length; i < l; i++)
|
|
22
|
+
arr.push(arrayLike[i]);
|
|
23
|
+
return arr;
|
|
24
|
+
}
|
|
25
|
+
function px(node, styleProperty) {
|
|
26
|
+
const val = (node.ownerDocument.defaultView || window).getComputedStyle(node).getPropertyValue(styleProperty);
|
|
27
|
+
return val ? parseFloat(val.replace("px", "")) : 0;
|
|
28
|
+
}
|
|
29
|
+
function getNodeWidth(node) {
|
|
30
|
+
const leftBorder = px(node, "border-left-width"), rightBorder = px(node, "border-right-width");
|
|
31
|
+
return node.clientWidth + leftBorder + rightBorder;
|
|
32
|
+
}
|
|
33
|
+
function getNodeHeight(node) {
|
|
34
|
+
const topBorder = px(node, "border-top-width"), bottomBorder = px(node, "border-bottom-width");
|
|
35
|
+
return node.clientHeight + topBorder + bottomBorder;
|
|
36
|
+
}
|
|
37
|
+
function getImageSize(targetNode, options = {}) {
|
|
38
|
+
const width = options.width || getNodeWidth(targetNode), height = options.height || getNodeHeight(targetNode);
|
|
39
|
+
return { width, height };
|
|
40
|
+
}
|
|
41
|
+
function getPixelRatio() {
|
|
42
|
+
let ratio, FINAL_PROCESS;
|
|
43
|
+
try {
|
|
44
|
+
FINAL_PROCESS = process;
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
const val = FINAL_PROCESS && FINAL_PROCESS.env ? FINAL_PROCESS.env.devicePixelRatio : null;
|
|
48
|
+
return val && (ratio = parseInt(val, 10), Number.isNaN(ratio) && (ratio = 1)), ratio || window.devicePixelRatio || 1;
|
|
49
|
+
}
|
|
50
|
+
const canvasDimensionLimit = 16384;
|
|
51
|
+
function checkCanvasDimensions(canvas) {
|
|
52
|
+
(canvas.width > canvasDimensionLimit || canvas.height > canvasDimensionLimit) && (canvas.width > canvasDimensionLimit && canvas.height > canvasDimensionLimit ?
|
|
53
|
+
canvas.width > canvas.height ? (canvas.height *= canvasDimensionLimit / canvas.width, canvas.width = canvasDimensionLimit) : (canvas.width *= canvasDimensionLimit /
|
|
54
|
+
canvas.height, canvas.height = canvasDimensionLimit) : canvas.width > canvasDimensionLimit ? (canvas.height *= canvasDimensionLimit / canvas.width, canvas.
|
|
55
|
+
width = canvasDimensionLimit) : (canvas.width *= canvasDimensionLimit / canvas.height, canvas.height = canvasDimensionLimit));
|
|
56
|
+
}
|
|
57
|
+
function createImage(url) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const img = new Image();
|
|
60
|
+
img.decode = () => resolve(img), img.onload = () => resolve(img), img.onerror = reject, img.crossOrigin = "anonymous", img.decoding = "async", img.
|
|
61
|
+
src = url;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function svgToDataURL(svg) {
|
|
65
|
+
return Promise.resolve().then(() => new XMLSerializer().serializeToString(svg)).then(encodeURIComponent).then((html) => `data:image/svg+xml;charset=\
|
|
66
|
+
utf-8,${html}`);
|
|
67
|
+
}
|
|
68
|
+
async function nodeToDataURL(node, width, height) {
|
|
69
|
+
const xmlns = "http://www.w3.org/2000/svg", svg = document.createElementNS(xmlns, "svg"), foreignObject = document.createElementNS(xmlns, "foreignOb\
|
|
70
|
+
ject");
|
|
71
|
+
return svg.setAttribute("width", `${width}`), svg.setAttribute("height", `${height}`), svg.setAttribute("viewBox", `0 0 ${width} ${height}`), foreignObject.
|
|
72
|
+
setAttribute("width", "100%"), foreignObject.setAttribute("height", "100%"), foreignObject.setAttribute("x", "0"), foreignObject.setAttribute("y", "\
|
|
73
|
+
0"), foreignObject.setAttribute("externalResourcesRequired", "true"), svg.appendChild(foreignObject), foreignObject.appendChild(node), svgToDataURL(svg);
|
|
74
|
+
}
|
|
75
|
+
const isInstanceOfElement = (node, instance) => {
|
|
76
|
+
if (node instanceof instance)
|
|
77
|
+
return !0;
|
|
78
|
+
const nodePrototype = Object.getPrototypeOf(node);
|
|
79
|
+
return nodePrototype === null ? !1 : nodePrototype.constructor.name === instance.name || isInstanceOfElement(nodePrototype, instance);
|
|
80
|
+
};
|
|
81
|
+
function formatCSSText(style) {
|
|
82
|
+
const content = style.getPropertyValue("content");
|
|
83
|
+
return `${style.cssText} content: '${content.replace(/'|"/g, "")}';`;
|
|
84
|
+
}
|
|
85
|
+
function formatCSSProperties(style) {
|
|
86
|
+
return toArray(style).map((name) => {
|
|
87
|
+
const value = style.getPropertyValue(name), priority = style.getPropertyPriority(name);
|
|
88
|
+
return `${name}: ${value}${priority ? " !important" : ""};`;
|
|
89
|
+
}).join(" ");
|
|
90
|
+
}
|
|
91
|
+
function getPseudoElementStyle(className, pseudo, style) {
|
|
92
|
+
const selector = `.${className}:${pseudo}`, cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style);
|
|
93
|
+
return document.createTextNode(`${selector}{${cssText}}`);
|
|
94
|
+
}
|
|
95
|
+
function clonePseudoElement(nativeNode, clonedNode, pseudo) {
|
|
96
|
+
const style = window.getComputedStyle(nativeNode, pseudo), content = style.getPropertyValue("content");
|
|
97
|
+
if (content === "" || content === "none")
|
|
98
|
+
return;
|
|
99
|
+
const className = uuid();
|
|
100
|
+
try {
|
|
101
|
+
clonedNode.className = `${clonedNode.className} ${className}`;
|
|
102
|
+
} catch {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const styleElement = document.createElement("style");
|
|
106
|
+
styleElement.appendChild(getPseudoElementStyle(className, pseudo, style)), clonedNode.appendChild(styleElement);
|
|
107
|
+
}
|
|
108
|
+
function clonePseudoElements(nativeNode, clonedNode) {
|
|
109
|
+
clonePseudoElement(nativeNode, clonedNode, ":before"), clonePseudoElement(nativeNode, clonedNode, ":after");
|
|
110
|
+
}
|
|
111
|
+
const WOFF = "application/font-woff", JPEG = "image/jpeg", mimes = {
|
|
112
|
+
woff: WOFF,
|
|
113
|
+
woff2: WOFF,
|
|
114
|
+
ttf: "application/font-truetype",
|
|
115
|
+
eot: "application/vnd.ms-fontobject",
|
|
116
|
+
png: "image/png",
|
|
117
|
+
jpg: JPEG,
|
|
118
|
+
jpeg: JPEG,
|
|
119
|
+
gif: "image/gif",
|
|
120
|
+
tiff: "image/tiff",
|
|
121
|
+
svg: "image/svg+xml",
|
|
122
|
+
webp: "image/webp"
|
|
123
|
+
};
|
|
124
|
+
function getExtension(url) {
|
|
125
|
+
const match = /\.([^./]*?)$/g.exec(url);
|
|
126
|
+
return match ? match[1] : "";
|
|
127
|
+
}
|
|
128
|
+
function getMimeType(url) {
|
|
129
|
+
const extension = getExtension(url).toLowerCase();
|
|
130
|
+
return mimes[extension] || "";
|
|
131
|
+
}
|
|
132
|
+
function getContentFromDataUrl(dataURL) {
|
|
133
|
+
return dataURL.split(/,/)[1];
|
|
134
|
+
}
|
|
135
|
+
function isDataUrl(url) {
|
|
136
|
+
return url.search(/^(data:)/) !== -1;
|
|
137
|
+
}
|
|
138
|
+
function makeDataUrl(content, mimeType) {
|
|
139
|
+
return `data:${mimeType};base64,${content}`;
|
|
140
|
+
}
|
|
141
|
+
async function fetchAsDataURL(url, init, process2) {
|
|
142
|
+
const res = await fetch(url, init);
|
|
143
|
+
if (res.status === 404)
|
|
144
|
+
throw new Error(`Resource "${res.url}" not found`);
|
|
145
|
+
const blob = await res.blob();
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
const reader = new FileReader();
|
|
148
|
+
reader.onerror = reject, reader.onloadend = () => {
|
|
149
|
+
try {
|
|
150
|
+
resolve(process2({ res, result: reader.result }));
|
|
151
|
+
} catch (error) {
|
|
152
|
+
reject(error);
|
|
153
|
+
}
|
|
154
|
+
}, reader.readAsDataURL(blob);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
const cache = {};
|
|
158
|
+
function getCacheKey(url, contentType, includeQueryParams) {
|
|
159
|
+
let key = url.replace(/\?.*/, "");
|
|
160
|
+
return includeQueryParams && (key = url), /ttf|otf|eot|woff2?/i.test(key) && (key = key.replace(/.*\//, "")), contentType ? `[${contentType}]${key}` :
|
|
161
|
+
key;
|
|
162
|
+
}
|
|
163
|
+
async function resourceToDataURL(resourceUrl, contentType, options) {
|
|
164
|
+
const cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams);
|
|
165
|
+
if (cache[cacheKey] != null)
|
|
166
|
+
return cache[cacheKey];
|
|
167
|
+
options.cacheBust && (resourceUrl += (/\?/.test(resourceUrl) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime());
|
|
168
|
+
let dataURL;
|
|
169
|
+
try {
|
|
170
|
+
const content = await fetchAsDataURL(resourceUrl, options.fetchRequestInit, ({ res, result }) => (contentType || (contentType = res.headers.get("C\
|
|
171
|
+
ontent-Type") || ""), getContentFromDataUrl(result)));
|
|
172
|
+
dataURL = makeDataUrl(content, contentType);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
dataURL = options.imagePlaceholder || "";
|
|
175
|
+
let msg = `Failed to fetch resource: ${resourceUrl}`;
|
|
176
|
+
error && (msg = typeof error == "string" ? error : error.message), msg && console.warn(msg);
|
|
177
|
+
}
|
|
178
|
+
return cache[cacheKey] = dataURL, dataURL;
|
|
179
|
+
}
|
|
180
|
+
async function cloneCanvasElement(canvas) {
|
|
181
|
+
const dataURL = canvas.toDataURL();
|
|
182
|
+
return dataURL === "data:," ? canvas.cloneNode(!1) : createImage(dataURL);
|
|
183
|
+
}
|
|
184
|
+
async function cloneVideoElement(video, options) {
|
|
185
|
+
if (video.currentSrc) {
|
|
186
|
+
const canvas = document.createElement("canvas"), ctx = canvas.getContext("2d");
|
|
187
|
+
canvas.width = video.clientWidth, canvas.height = video.clientHeight, ctx?.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
188
|
+
const dataURL2 = canvas.toDataURL();
|
|
189
|
+
return createImage(dataURL2);
|
|
190
|
+
}
|
|
191
|
+
const poster = video.poster, contentType = getMimeType(poster), dataURL = await resourceToDataURL(poster, contentType, options);
|
|
192
|
+
return createImage(dataURL);
|
|
193
|
+
}
|
|
194
|
+
async function cloneIFrameElement(iframe) {
|
|
195
|
+
var _a;
|
|
196
|
+
try {
|
|
197
|
+
if (!((_a = iframe?.contentDocument) === null || _a === void 0) && _a.body)
|
|
198
|
+
return await cloneNode(iframe.contentDocument.body, {}, !0);
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
return iframe.cloneNode(!1);
|
|
202
|
+
}
|
|
203
|
+
async function cloneSingleNode(node, options) {
|
|
204
|
+
return isInstanceOfElement(node, HTMLCanvasElement) ? cloneCanvasElement(node) : isInstanceOfElement(node, HTMLVideoElement) ? cloneVideoElement(node,
|
|
205
|
+
options) : isInstanceOfElement(node, HTMLIFrameElement) ? cloneIFrameElement(node) : node.cloneNode(!1);
|
|
206
|
+
}
|
|
207
|
+
const isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === "SLOT";
|
|
208
|
+
async function cloneChildren(nativeNode, clonedNode, options) {
|
|
209
|
+
var _a, _b;
|
|
210
|
+
let children = [];
|
|
211
|
+
return isSlotElement(nativeNode) && nativeNode.assignedNodes ? children = toArray(nativeNode.assignedNodes()) : isInstanceOfElement(nativeNode, HTMLIFrameElement) &&
|
|
212
|
+
(!((_a = nativeNode.contentDocument) === null || _a === void 0) && _a.body) ? children = toArray(nativeNode.contentDocument.body.childNodes) : children =
|
|
213
|
+
toArray(((_b = nativeNode.shadowRoot) !== null && _b !== void 0 ? _b : nativeNode).childNodes), children.length === 0 || isInstanceOfElement(nativeNode,
|
|
214
|
+
HTMLVideoElement) || await children.reduce((deferred, child) => deferred.then(() => cloneNode(child, options)).then((clonedChild) => {
|
|
215
|
+
clonedChild && clonedNode.appendChild(clonedChild);
|
|
216
|
+
}), Promise.resolve()), clonedNode;
|
|
217
|
+
}
|
|
218
|
+
function cloneCSSStyle(nativeNode, clonedNode) {
|
|
219
|
+
const targetStyle = clonedNode.style;
|
|
220
|
+
if (!targetStyle)
|
|
221
|
+
return;
|
|
222
|
+
const sourceStyle = window.getComputedStyle(nativeNode);
|
|
223
|
+
sourceStyle.cssText ? (targetStyle.cssText = sourceStyle.cssText, targetStyle.transformOrigin = sourceStyle.transformOrigin) : toArray(sourceStyle).
|
|
224
|
+
forEach((name) => {
|
|
225
|
+
let value = sourceStyle.getPropertyValue(name);
|
|
226
|
+
name === "font-size" && value.endsWith("px") && (value = `${Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1}px`), isInstanceOfElement(
|
|
227
|
+
nativeNode, HTMLIFrameElement) && name === "display" && value === "inline" && (value = "block"), name === "d" && clonedNode.getAttribute("d") && (value =
|
|
228
|
+
`path(${clonedNode.getAttribute("d")})`), targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function cloneInputValue(nativeNode, clonedNode) {
|
|
232
|
+
isInstanceOfElement(nativeNode, HTMLTextAreaElement) && (clonedNode.innerHTML = nativeNode.value), isInstanceOfElement(nativeNode, HTMLInputElement) &&
|
|
233
|
+
clonedNode.setAttribute("value", nativeNode.value);
|
|
234
|
+
}
|
|
235
|
+
function cloneSelectValue(nativeNode, clonedNode) {
|
|
236
|
+
if (isInstanceOfElement(nativeNode, HTMLSelectElement)) {
|
|
237
|
+
const clonedSelect = clonedNode, selectedOption = Array.from(clonedSelect.children).find((child) => nativeNode.value === child.getAttribute("value"));
|
|
238
|
+
selectedOption && selectedOption.setAttribute("selected", "");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function decorate(nativeNode, clonedNode) {
|
|
242
|
+
return isInstanceOfElement(clonedNode, Element) && (cloneCSSStyle(nativeNode, clonedNode), clonePseudoElements(nativeNode, clonedNode), cloneInputValue(
|
|
243
|
+
nativeNode, clonedNode), cloneSelectValue(nativeNode, clonedNode)), clonedNode;
|
|
244
|
+
}
|
|
245
|
+
async function ensureSVGSymbols(clone, options) {
|
|
246
|
+
const uses = clone.querySelectorAll ? clone.querySelectorAll("use") : [];
|
|
247
|
+
if (uses.length === 0)
|
|
248
|
+
return clone;
|
|
249
|
+
const processedDefs = {};
|
|
250
|
+
for (let i = 0; i < uses.length; i++) {
|
|
251
|
+
const id = uses[i].getAttribute("xlink:href");
|
|
252
|
+
if (id) {
|
|
253
|
+
const exist = clone.querySelector(id), definition = document.querySelector(id);
|
|
254
|
+
!exist && definition && !processedDefs[id] && (processedDefs[id] = await cloneNode(definition, options, !0));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const nodes = Object.values(processedDefs);
|
|
258
|
+
if (nodes.length) {
|
|
259
|
+
const ns = "http://www.w3.org/1999/xhtml", svg = document.createElementNS(ns, "svg");
|
|
260
|
+
svg.setAttribute("xmlns", ns), svg.style.position = "absolute", svg.style.width = "0", svg.style.height = "0", svg.style.overflow = "hidden", svg.
|
|
261
|
+
style.display = "none";
|
|
262
|
+
const defs = document.createElementNS(ns, "defs");
|
|
263
|
+
svg.appendChild(defs);
|
|
264
|
+
for (let i = 0; i < nodes.length; i++)
|
|
265
|
+
defs.appendChild(nodes[i]);
|
|
266
|
+
clone.appendChild(svg);
|
|
267
|
+
}
|
|
268
|
+
return clone;
|
|
269
|
+
}
|
|
270
|
+
async function cloneNode(node, options, isRoot) {
|
|
271
|
+
return !isRoot && options.filter && !options.filter(node) ? null : Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).
|
|
272
|
+
then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode)).then((clonedNode) => ensureSVGSymbols(
|
|
273
|
+
clonedNode, options));
|
|
274
|
+
}
|
|
275
|
+
const URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g, URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
|
|
276
|
+
function toRegex(url) {
|
|
277
|
+
const escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
|
|
278
|
+
return new RegExp(`(url\\(['"]?)(${escaped})(['"]?\\))`, "g");
|
|
279
|
+
}
|
|
280
|
+
function parseURLs(cssText) {
|
|
281
|
+
const urls = [];
|
|
282
|
+
return cssText.replace(URL_REGEX, (raw, quotation, url) => (urls.push(url), raw)), urls.filter((url) => !isDataUrl(url));
|
|
283
|
+
}
|
|
284
|
+
async function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) {
|
|
285
|
+
try {
|
|
286
|
+
const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL, contentType = getMimeType(resourceURL);
|
|
287
|
+
let dataURL;
|
|
288
|
+
return getContentFromUrl || (dataURL = await resourceToDataURL(resolvedURL, contentType, options)), cssText.replace(toRegex(resourceURL), `$1${dataURL}\
|
|
289
|
+
$3`);
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
return cssText;
|
|
293
|
+
}
|
|
294
|
+
function filterPreferredFontFormat(str, { preferredFontFormat }) {
|
|
295
|
+
return preferredFontFormat ? str.replace(FONT_SRC_REGEX, (match) => {
|
|
296
|
+
for (; ; ) {
|
|
297
|
+
const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || [];
|
|
298
|
+
if (!format)
|
|
299
|
+
return "";
|
|
300
|
+
if (format === preferredFontFormat)
|
|
301
|
+
return `src: ${src};`;
|
|
302
|
+
}
|
|
303
|
+
}) : str;
|
|
304
|
+
}
|
|
305
|
+
function shouldEmbed(url) {
|
|
306
|
+
return url.search(URL_REGEX) !== -1;
|
|
307
|
+
}
|
|
308
|
+
async function embedResources(cssText, baseUrl, options) {
|
|
309
|
+
if (!shouldEmbed(cssText))
|
|
310
|
+
return cssText;
|
|
311
|
+
const filteredCSSText = filterPreferredFontFormat(cssText, options);
|
|
312
|
+
return parseURLs(filteredCSSText).reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));
|
|
313
|
+
}
|
|
314
|
+
async function embedProp(propName, node, options) {
|
|
315
|
+
var _a;
|
|
316
|
+
const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);
|
|
317
|
+
if (propValue) {
|
|
318
|
+
const cssString = await embedResources(propValue, null, options);
|
|
319
|
+
return node.style.setProperty(propName, cssString, node.style.getPropertyPriority(propName)), !0;
|
|
320
|
+
}
|
|
321
|
+
return !1;
|
|
322
|
+
}
|
|
323
|
+
async function embedBackground(clonedNode, options) {
|
|
324
|
+
await embedProp("background", clonedNode, options) || await embedProp("background-image", clonedNode, options), await embedProp("mask", clonedNode, options) ||
|
|
325
|
+
await embedProp("mask-image", clonedNode, options);
|
|
326
|
+
}
|
|
327
|
+
async function embedImageNode(clonedNode, options) {
|
|
328
|
+
const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);
|
|
329
|
+
if (!(isImageElement && !isDataUrl(clonedNode.src)) && !(isInstanceOfElement(clonedNode, SVGImageElement) && !isDataUrl(clonedNode.href.baseVal)))
|
|
330
|
+
return;
|
|
331
|
+
const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal, dataURL = await resourceToDataURL(url, getMimeType(url), options);
|
|
332
|
+
await new Promise((resolve, reject) => {
|
|
333
|
+
clonedNode.onload = resolve, clonedNode.onerror = reject;
|
|
334
|
+
const image = clonedNode;
|
|
335
|
+
image.decode && (image.decode = resolve), image.loading === "lazy" && (image.loading = "eager"), isImageElement ? (clonedNode.srcset = "", clonedNode.
|
|
336
|
+
src = dataURL) : clonedNode.href.baseVal = dataURL;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
async function embedChildren(clonedNode, options) {
|
|
340
|
+
const deferreds = toArray(clonedNode.childNodes).map((child) => embedImages(child, options));
|
|
341
|
+
await Promise.all(deferreds).then(() => clonedNode);
|
|
342
|
+
}
|
|
343
|
+
async function embedImages(clonedNode, options) {
|
|
344
|
+
isInstanceOfElement(clonedNode, Element) && (await embedBackground(clonedNode, options), await embedImageNode(clonedNode, options), await embedChildren(
|
|
345
|
+
clonedNode, options));
|
|
346
|
+
}
|
|
347
|
+
function applyStyle(node, options) {
|
|
348
|
+
const { style } = node;
|
|
349
|
+
options.backgroundColor && (style.backgroundColor = options.backgroundColor), options.width && (style.width = `${options.width}px`), options.height &&
|
|
350
|
+
(style.height = `${options.height}px`);
|
|
351
|
+
const manual = options.style;
|
|
352
|
+
return manual != null && Object.keys(manual).forEach((key) => {
|
|
353
|
+
style[key] = manual[key];
|
|
354
|
+
}), node;
|
|
355
|
+
}
|
|
356
|
+
const cssFetchCache = {};
|
|
357
|
+
async function fetchCSS(url) {
|
|
358
|
+
let cache2 = cssFetchCache[url];
|
|
359
|
+
if (cache2 != null)
|
|
360
|
+
return cache2;
|
|
361
|
+
const cssText = await (await fetch(url)).text();
|
|
362
|
+
return cache2 = { url, cssText }, cssFetchCache[url] = cache2, cache2;
|
|
363
|
+
}
|
|
364
|
+
async function embedFonts(data, options) {
|
|
365
|
+
let cssText = data.cssText;
|
|
366
|
+
const regexUrl = /url\(["']?([^"')]+)["']?\)/g, loadFonts = (cssText.match(/url\([^)]+\)/g) || []).map(async (loc) => {
|
|
367
|
+
let url = loc.replace(regexUrl, "$1");
|
|
368
|
+
return url.startsWith("https://") || (url = new URL(url, data.url).href), fetchAsDataURL(url, options.fetchRequestInit, ({ result }) => (cssText =
|
|
369
|
+
cssText.replace(loc, `url(${result})`), [loc, result]));
|
|
370
|
+
});
|
|
371
|
+
return Promise.all(loadFonts).then(() => cssText);
|
|
372
|
+
}
|
|
373
|
+
function parseCSS(source) {
|
|
374
|
+
if (source == null)
|
|
375
|
+
return [];
|
|
376
|
+
const result = [], commentsRegex = /(\/\*[\s\S]*?\*\/)/gi;
|
|
377
|
+
let cssText = source.replace(commentsRegex, "");
|
|
378
|
+
const keyframesRegex = new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi");
|
|
379
|
+
for (; ; ) {
|
|
380
|
+
const matches = keyframesRegex.exec(cssText);
|
|
381
|
+
if (matches === null)
|
|
382
|
+
break;
|
|
383
|
+
result.push(matches[0]);
|
|
384
|
+
}
|
|
385
|
+
cssText = cssText.replace(keyframesRegex, "");
|
|
386
|
+
const importRegex = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi, combinedCSSRegex = "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(\
|
|
387
|
+
([\\s\\S]*?){([\\s\\S]*?)})", unifiedRegex = new RegExp(combinedCSSRegex, "gi");
|
|
388
|
+
for (; ; ) {
|
|
389
|
+
let matches = importRegex.exec(cssText);
|
|
390
|
+
if (matches === null) {
|
|
391
|
+
if (matches = unifiedRegex.exec(cssText), matches === null)
|
|
392
|
+
break;
|
|
393
|
+
importRegex.lastIndex = unifiedRegex.lastIndex;
|
|
394
|
+
} else
|
|
395
|
+
unifiedRegex.lastIndex = importRegex.lastIndex;
|
|
396
|
+
result.push(matches[0]);
|
|
397
|
+
}
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
async function getCSSRules(styleSheets, options) {
|
|
401
|
+
const ret = [], deferreds = [];
|
|
402
|
+
return styleSheets.forEach((sheet) => {
|
|
403
|
+
if ("cssRules" in sheet)
|
|
404
|
+
try {
|
|
405
|
+
toArray(sheet.cssRules || []).forEach((item, index) => {
|
|
406
|
+
if (item.type === CSSRule.IMPORT_RULE) {
|
|
407
|
+
let importIndex = index + 1;
|
|
408
|
+
const url = item.href, deferred = fetchCSS(url).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).forEach(
|
|
409
|
+
(rule) => {
|
|
410
|
+
try {
|
|
411
|
+
sheet.insertRule(rule, rule.startsWith("@import") ? importIndex += 1 : sheet.cssRules.length);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.error("Error inserting rule from remote css", {
|
|
414
|
+
rule,
|
|
415
|
+
error
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
})).catch((e) => {
|
|
419
|
+
console.error("Error loading remote css", e.toString());
|
|
420
|
+
});
|
|
421
|
+
deferreds.push(deferred);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
} catch (e) {
|
|
425
|
+
const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];
|
|
426
|
+
sheet.href != null && deferreds.push(fetchCSS(sheet.href).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).
|
|
427
|
+
forEach((rule) => {
|
|
428
|
+
inline.insertRule(rule, sheet.cssRules.length);
|
|
429
|
+
})).catch((err) => {
|
|
430
|
+
console.error("Error loading remote stylesheet", err);
|
|
431
|
+
})), console.error("Error inlining remote css file", e);
|
|
432
|
+
}
|
|
433
|
+
}), Promise.all(deferreds).then(() => (styleSheets.forEach((sheet) => {
|
|
434
|
+
if ("cssRules" in sheet)
|
|
435
|
+
try {
|
|
436
|
+
toArray(sheet.cssRules || []).forEach((item) => {
|
|
437
|
+
ret.push(item);
|
|
438
|
+
});
|
|
439
|
+
} catch (e) {
|
|
440
|
+
console.error(`Error while reading CSS rules from ${sheet.href}`, e);
|
|
441
|
+
}
|
|
442
|
+
}), ret));
|
|
443
|
+
}
|
|
444
|
+
function getWebFontRules(cssRules) {
|
|
445
|
+
return cssRules.filter((rule) => rule.type === CSSRule.FONT_FACE_RULE).filter((rule) => shouldEmbed(rule.style.getPropertyValue("src")));
|
|
446
|
+
}
|
|
447
|
+
async function parseWebFontRules(node, options) {
|
|
448
|
+
if (node.ownerDocument == null)
|
|
449
|
+
throw new Error("Provided element is not within a Document");
|
|
450
|
+
const styleSheets = toArray(node.ownerDocument.styleSheets), cssRules = await getCSSRules(styleSheets, options);
|
|
451
|
+
return getWebFontRules(cssRules);
|
|
452
|
+
}
|
|
453
|
+
async function getWebFontCSS(node, options) {
|
|
454
|
+
const rules = await parseWebFontRules(node, options);
|
|
455
|
+
return (await Promise.all(rules.map((rule) => {
|
|
456
|
+
const baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null;
|
|
457
|
+
return embedResources(rule.cssText, baseUrl, options);
|
|
458
|
+
}))).join(`
|
|
459
|
+
`);
|
|
460
|
+
}
|
|
461
|
+
async function embedWebFonts(clonedNode, options) {
|
|
462
|
+
const cssText = options.fontEmbedCSS != null ? options.fontEmbedCSS : options.skipFonts ? null : await getWebFontCSS(clonedNode, options);
|
|
463
|
+
if (cssText) {
|
|
464
|
+
const styleNode = document.createElement("style"), sytleContent = document.createTextNode(cssText);
|
|
465
|
+
styleNode.appendChild(sytleContent), clonedNode.firstChild ? clonedNode.insertBefore(styleNode, clonedNode.firstChild) : clonedNode.appendChild(styleNode);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
async function toSvg(node, options = {}) {
|
|
469
|
+
const { width, height } = getImageSize(node, options), clonedNode = await cloneNode(node, options, !0);
|
|
470
|
+
return await embedWebFonts(clonedNode, options), await embedImages(clonedNode, options), applyStyle(clonedNode, options), await nodeToDataURL(clonedNode,
|
|
471
|
+
width, height);
|
|
472
|
+
}
|
|
473
|
+
async function toCanvas(node, options = {}) {
|
|
474
|
+
const { width, height } = getImageSize(node, options), svg = await toSvg(node, options), img = await createImage(svg), canvas = document.createElement(
|
|
475
|
+
"canvas"), context = canvas.getContext("2d"), ratio = options.pixelRatio || getPixelRatio(), canvasWidth = options.canvasWidth || width, canvasHeight = options.
|
|
476
|
+
canvasHeight || height;
|
|
477
|
+
return canvas.width = canvasWidth * ratio, canvas.height = canvasHeight * ratio, options.skipAutoScale || checkCanvasDimensions(canvas), canvas.style.
|
|
478
|
+
width = `${canvasWidth}`, canvas.style.height = `${canvasHeight}`, options.backgroundColor && (context.fillStyle = options.backgroundColor, context.
|
|
479
|
+
fillRect(0, 0, canvas.width, canvas.height)), context.drawImage(img, 0, 0, canvas.width, canvas.height), canvas;
|
|
480
|
+
}
|
|
481
|
+
async function toPng(node, options = {}) {
|
|
482
|
+
return (await toCanvas(node, options)).toDataURL();
|
|
483
|
+
}
|
|
484
|
+
export {
|
|
485
|
+
toCanvas,
|
|
486
|
+
toPng,
|
|
487
|
+
toSvg
|
|
488
|
+
};
|