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.
@@ -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.draggable ?? !1, next.draggable ?? !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({
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(element.icon) && hasIcon,
23780
+ n$4(elementIcon2) && hasIcon,
23782
23781
  "likec4-element"
23783
23782
  ),
23784
23783
  children: [
23785
- n$4(element.icon) && /* @__PURE__ */ jsx(ElementIcon, { node: element }),
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,9 @@
1
+ import { d2Source } from "virtual:likec4/d2-sources";
2
+ import { dotSource, svgSource } from "virtual:likec4/dot-sources";
3
+ import { mmdSource } from "virtual:likec4/mmd-sources";
4
+ export {
5
+ d2Source,
6
+ dotSource,
7
+ mmdSource,
8
+ svgSource
9
+ };
@@ -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
+ };