@tldraw/editor 4.5.2 → 4.6.0-canary.4ec045c286e1
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-cjs/index.d.ts +37 -6
- package/dist-cjs/index.js +6 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +7 -5
- package/dist-cjs/lib/TldrawEditor.js.map +3 -3
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +8 -5
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +8 -5
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +3 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -0
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +52 -16
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +62 -6
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +4 -3
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +5 -0
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +3 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/exports/FontEmbedder.js +9 -8
- package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +27 -15
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +3 -3
- package/dist-cjs/lib/exports/domUtils.js +15 -0
- package/dist-cjs/lib/exports/domUtils.js.map +2 -2
- package/dist-cjs/lib/exports/embedMedia.js +15 -12
- package/dist-cjs/lib/exports/embedMedia.js.map +2 -2
- package/dist-cjs/lib/exports/exportToSvg.js +8 -7
- package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgAsImage.js +181 -29
- package/dist-cjs/lib/exports/getSvgAsImage.js.map +3 -3
- package/dist-cjs/lib/exports/getSvgJsx.js +21 -9
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +4 -3
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +13 -11
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +3 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js +10 -6
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/hooks/useViewportHeight.js +13 -11
- package/dist-cjs/lib/hooks/useViewportHeight.js.map +3 -3
- package/dist-cjs/lib/license/Watermark.js +10 -0
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +35 -22
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +6 -13
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +31 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +9 -0
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +9 -0
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +32 -18
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +12 -0
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +51 -12
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +12 -0
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js +133 -0
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +7 -0
- package/dist-cjs/lib/primitives/intersect.js +16 -15
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +0 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js +3 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
- package/dist-cjs/lib/utils/dom.js +15 -2
- package/dist-cjs/lib/utils/dom.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +37 -6
- package/dist-esm/index.mjs +8 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +7 -5
- package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +2 -1
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +8 -5
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +8 -5
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +3 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -0
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +53 -17
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +64 -6
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +4 -3
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +5 -0
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +3 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs +9 -8
- package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +29 -16
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +3 -3
- package/dist-esm/lib/exports/domUtils.mjs +15 -0
- package/dist-esm/lib/exports/domUtils.mjs.map +2 -2
- package/dist-esm/lib/exports/embedMedia.mjs +16 -13
- package/dist-esm/lib/exports/embedMedia.mjs.map +2 -2
- package/dist-esm/lib/exports/exportToSvg.mjs +8 -7
- package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgAsImage.mjs +181 -29
- package/dist-esm/lib/exports/getSvgAsImage.mjs.map +3 -3
- package/dist-esm/lib/exports/getSvgJsx.mjs +21 -9
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +4 -3
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +13 -11
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +3 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs +10 -6
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useViewportHeight.mjs +13 -11
- package/dist-esm/lib/hooks/useViewportHeight.mjs.map +3 -3
- package/dist-esm/lib/license/Watermark.mjs +10 -0
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +35 -22
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +6 -13
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +31 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +9 -0
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +9 -0
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +32 -18
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +13 -1
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +51 -12
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +13 -1
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +132 -0
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +7 -0
- package/dist-esm/lib/primitives/intersect.mjs +17 -16
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +0 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +3 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
- package/dist-esm/lib/utils/dom.mjs +15 -2
- package/dist-esm/lib/utils/dom.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +3 -0
- package/src/lib/TldrawEditor.tsx +7 -5
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +2 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +8 -5
- package/src/lib/config/TLSessionStateSnapshot.ts +8 -5
- package/src/lib/config/TLUserPreferences.ts +3 -2
- package/src/lib/config/createTLStore.ts +3 -0
- package/src/lib/editor/Editor.ts +53 -15
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +7 -6
- package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -7
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
- package/src/lib/editor/managers/FontManager/FontManager.ts +4 -3
- package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +16 -0
- package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +7 -2
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +4 -5
- package/src/lib/editor/managers/TextManager/TextManager.ts +2 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +3 -2
- package/src/lib/editor/types/misc-types.ts +8 -2
- package/src/lib/exports/FontEmbedder.ts +10 -9
- package/src/lib/exports/StyleEmbedder.ts +33 -15
- package/src/lib/exports/domUtils.ts +20 -0
- package/src/lib/exports/embedMedia.ts +23 -17
- package/src/lib/exports/exportToSvg.tsx +8 -7
- package/src/lib/exports/getSvgAsImage.ts +292 -32
- package/src/lib/exports/getSvgJsx.test.ts +103 -101
- package/src/lib/exports/getSvgJsx.tsx +33 -10
- package/src/lib/globals/environment.ts +4 -3
- package/src/lib/hooks/useCanvasEvents.ts +2 -3
- package/src/lib/hooks/useDocumentEvents.ts +16 -11
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +3 -3
- package/src/lib/hooks/useScreenBounds.ts +10 -6
- package/src/lib/hooks/useViewportHeight.ts +13 -11
- package/src/lib/license/Watermark.tsx +10 -0
- package/src/lib/primitives/Vec.ts +51 -24
- package/src/lib/primitives/geometry/Arc2d.ts +10 -15
- package/src/lib/primitives/geometry/Circle2d.ts +40 -2
- package/src/lib/primitives/geometry/CubicBezier2d.ts +10 -0
- package/src/lib/primitives/geometry/CubicSpline2d.ts +10 -0
- package/src/lib/primitives/geometry/Edge2d.ts +41 -18
- package/src/lib/primitives/geometry/Ellipse2d.ts +14 -1
- package/src/lib/primitives/geometry/Polyline2d.ts +60 -12
- package/src/lib/primitives/geometry/Stadium2d.ts +14 -1
- package/src/lib/primitives/geometry/geometry.bench.ts +179 -0
- package/src/lib/primitives/intersect.ts +27 -27
- package/src/lib/primitives/utils.ts +4 -4
- package/src/lib/test/TestEditor.ts +1 -0
- package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
- package/src/lib/utils/dom.ts +34 -2
- package/src/version.ts +3 -3
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
elementStyle,
|
|
6
6
|
getComputedStyle,
|
|
7
7
|
getRenderedChildNodes,
|
|
8
|
-
getRenderedChildren
|
|
8
|
+
getRenderedChildren,
|
|
9
|
+
isElement
|
|
9
10
|
} from "./domUtils.mjs";
|
|
10
11
|
import { resourceToDataUrl } from "./fetchCache.mjs";
|
|
11
12
|
import { parseCssValueUrls, shouldIncludeCssProperty } from "./parseCss.mjs";
|
|
@@ -32,7 +33,7 @@ class StyleEmbedder {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
readElementStyles(element, { shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }) {
|
|
35
|
-
const defaultStyles = shouldRespectDefaults ? getDefaultStylesForTagName(element.tagName.toLowerCase()) : NO_STYLES;
|
|
36
|
+
const defaultStyles = shouldRespectDefaults ? getDefaultStylesForTagName(element.ownerDocument, element.tagName.toLowerCase()) : NO_STYLES;
|
|
36
37
|
const parentStyles = Object.assign({}, NO_STYLES);
|
|
37
38
|
if (shouldSkipInheritedParentStyles) {
|
|
38
39
|
let el = element.parentElement;
|
|
@@ -86,12 +87,12 @@ class StyleEmbedder {
|
|
|
86
87
|
visited.add(element);
|
|
87
88
|
const shadowRoot = element.shadowRoot;
|
|
88
89
|
if (shadowRoot) {
|
|
89
|
-
const clonedCustomEl =
|
|
90
|
+
const clonedCustomEl = element.ownerDocument.createElement("div");
|
|
90
91
|
this.styles.set(clonedCustomEl, this.styles.get(element));
|
|
91
92
|
clonedCustomEl.setAttribute("data-tl-custom-element", element.tagName);
|
|
92
93
|
(clonedParent ?? element.parentElement).appendChild(clonedCustomEl);
|
|
93
94
|
for (const child of shadowRoot.childNodes) {
|
|
94
|
-
if (child
|
|
95
|
+
if (isElement(child)) {
|
|
95
96
|
visit(child, clonedCustomEl);
|
|
96
97
|
} else {
|
|
97
98
|
clonedCustomEl.appendChild(child.cloneNode(true));
|
|
@@ -106,7 +107,7 @@ class StyleEmbedder {
|
|
|
106
107
|
this.styles.set(clonedEl, this.styles.get(element));
|
|
107
108
|
clonedParent.appendChild(clonedEl);
|
|
108
109
|
for (const child of getRenderedChildNodes(element)) {
|
|
109
|
-
if (child
|
|
110
|
+
if (isElement(child)) {
|
|
110
111
|
visit(child, clonedEl);
|
|
111
112
|
} else {
|
|
112
113
|
clonedEl.appendChild(child.cloneNode(true));
|
|
@@ -212,32 +213,44 @@ function formatCss(style) {
|
|
|
212
213
|
}
|
|
213
214
|
let defaultStyleFrame;
|
|
214
215
|
const defaultStylesByTagName = {};
|
|
215
|
-
function getDefaultStyleFrame() {
|
|
216
|
-
if (!defaultStyleFrame) {
|
|
217
|
-
|
|
216
|
+
function getDefaultStyleFrame(ownerDoc) {
|
|
217
|
+
if (!defaultStyleFrame || defaultStyleFrame.ownerDocument !== ownerDoc) {
|
|
218
|
+
destroyDefaultStyleFrame();
|
|
219
|
+
const frame = ownerDoc.createElement("iframe");
|
|
218
220
|
frame.style.display = "none";
|
|
219
|
-
|
|
221
|
+
ownerDoc.body.appendChild(frame);
|
|
220
222
|
const frameDocument = assertExists(frame.contentDocument, "frame must have a document");
|
|
221
|
-
const svg =
|
|
222
|
-
const foreignObject =
|
|
223
|
+
const svg = frameDocument.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
224
|
+
const foreignObject = frameDocument.createElementNS(
|
|
225
|
+
"http://www.w3.org/2000/svg",
|
|
226
|
+
"foreignObject"
|
|
227
|
+
);
|
|
223
228
|
svg.appendChild(foreignObject);
|
|
224
229
|
frameDocument.body.appendChild(svg);
|
|
225
|
-
defaultStyleFrame = {
|
|
230
|
+
defaultStyleFrame = {
|
|
231
|
+
iframe: frame,
|
|
232
|
+
foreignObject,
|
|
233
|
+
document: frameDocument,
|
|
234
|
+
ownerDocument: ownerDoc
|
|
235
|
+
};
|
|
226
236
|
}
|
|
227
237
|
return defaultStyleFrame;
|
|
228
238
|
}
|
|
229
239
|
function destroyDefaultStyleFrame() {
|
|
230
240
|
if (defaultStyleFrame) {
|
|
231
|
-
|
|
241
|
+
defaultStyleFrame.iframe.remove();
|
|
232
242
|
defaultStyleFrame = void 0;
|
|
233
243
|
}
|
|
244
|
+
for (const tagName in defaultStylesByTagName) {
|
|
245
|
+
delete defaultStylesByTagName[tagName];
|
|
246
|
+
}
|
|
234
247
|
}
|
|
235
248
|
const defaultStyleReadOptions = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES };
|
|
236
|
-
function getDefaultStylesForTagName(tagName) {
|
|
249
|
+
function getDefaultStylesForTagName(ownerDoc, tagName) {
|
|
237
250
|
let existing = defaultStylesByTagName[tagName];
|
|
238
251
|
if (!existing) {
|
|
239
|
-
const { foreignObject, document
|
|
240
|
-
const element =
|
|
252
|
+
const { foreignObject, document } = getDefaultStyleFrame(ownerDoc);
|
|
253
|
+
const element = document.createElement(tagName);
|
|
241
254
|
foreignObject.appendChild(element);
|
|
242
255
|
existing = element.computedStyleMap ? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions) : styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions);
|
|
243
256
|
foreignObject.removeChild(element);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/exports/StyleEmbedder.ts"],
|
|
4
|
-
"sourcesContent": ["import { assertExists, getOwnProperty, objectMapValues, uniqueId } from '@tldraw/utils'\nimport { FontEmbedder } from './FontEmbedder'\nimport { ReadonlyStyles, Styles, cssRules } from './cssRules'\nimport {\n\telementStyle,\n\tgetComputedStyle,\n\tgetRenderedChildNodes,\n\tgetRenderedChildren,\n} from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\nimport { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'\n\nconst NO_STYLES = {} as const\n\ninterface ElementStyleInfo {\n\tself: Styles\n\tbefore: Styles | undefined\n\tafter: Styles | undefined\n}\n\nexport class StyleEmbedder {\n\tconstructor(private readonly root: Element) {}\n\tprivate readonly styles = new Map<Element, ElementStyleInfo>()\n\treadonly fonts = new FontEmbedder()\n\n\treadRootElementStyles(rootElement: Element) {\n\t\t// when reading a root, we always apply _all_ the styles, even if they match the defaults\n\t\tthis.readElementStyles(rootElement, {\n\t\t\tshouldRespectDefaults: false,\n\t\t\tshouldSkipInheritedParentStyles: false,\n\t\t})\n\n\t\tconst children = Array.from(getRenderedChildren(rootElement))\n\t\twhile (children.length) {\n\t\t\tconst child = children.pop()!\n\t\t\tchildren.push(...getRenderedChildren(child))\n\n\t\t\t// when reading children, we don't apply styles that match the defaults for that\n\t\t\t// element, or that would be inherited from the parent\n\t\t\tthis.readElementStyles(child, {\n\t\t\t\tshouldRespectDefaults: true,\n\t\t\t\tshouldSkipInheritedParentStyles: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate readElementStyles(\n\t\telement: Element,\n\t\t{ shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }\n\t) {\n\t\tconst defaultStyles = shouldRespectDefaults\n\t\t\t? getDefaultStylesForTagName(element.tagName.toLowerCase())\n\t\t\t: NO_STYLES\n\n\t\tconst parentStyles = Object.assign({}, NO_STYLES) as Styles\n\t\tif (shouldSkipInheritedParentStyles) {\n\t\t\tlet el = element.parentElement\n\t\t\t// Keep going up the tree to find all the relevant styles\n\t\t\twhile (el) {\n\t\t\t\tconst currentStyles = this.styles.get(el)?.self\n\t\t\t\tfor (const style in currentStyles) {\n\t\t\t\t\tif (!parentStyles[style]) {\n\t\t\t\t\t\tparentStyles[style] = currentStyles[style]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tel = el.parentElement\n\t\t\t}\n\t\t}\n\n\t\tconst info: ElementStyleInfo = {\n\t\t\tself: styleFromElement(element, { defaultStyles, parentStyles }),\n\t\t\tbefore: styleFromPseudoElement(element, '::before'),\n\t\t\tafter: styleFromPseudoElement(element, '::after'),\n\t\t}\n\t\tthis.styles.set(element, info)\n\t}\n\n\tfetchResources() {\n\t\tconst promises: Promise<void>[] = []\n\n\t\tfor (const info of this.styles.values()) {\n\t\t\tfor (const styles of objectMapValues(info)) {\n\t\t\t\tif (!styles) continue\n\t\t\t\tfor (const [property, value] of Object.entries(styles)) {\n\t\t\t\t\tif (!value) continue\n\t\t\t\t\tif (property === 'font-family') {\n\t\t\t\t\t\tthis.fonts.onFontFamilyValue(value)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst urlMatches = parseCssValueUrls(value)\n\t\t\t\t\tif (urlMatches.length === 0) continue\n\n\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t...urlMatches.map(async ({ url, original }) => {\n\t\t\t\t\t\t\tconst dataUrl = (await resourceToDataUrl(url)) ?? 'data:'\n\t\t\t\t\t\t\tstyles[property] = value.replace(original, `url(\"${dataUrl}\")`)\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Promise.all(promises)\n\t}\n\n\t// custom elements are tricky. if we serialize the dom as-is, the custom elements wont have\n\t// their shadow-dom contents serialized. after we've read all the styles, we need to unwrap the\n\t// contents of each custom elements shadow dom directly into the parent element itself.\n\tunwrapCustomElements() {\n\t\tconst visited = new Set<Node>()\n\n\t\tconst visit = (element: Element, clonedParent: Element | null) => {\n\t\t\tif (visited.has(element)) return\n\t\t\tvisited.add(element)\n\n\t\t\tconst shadowRoot = element.shadowRoot\n\n\t\t\tif (shadowRoot) {\n\t\t\t\tconst clonedCustomEl = document.createElement('div')\n\t\t\t\tthis.styles.set(clonedCustomEl, this.styles.get(element)!)\n\n\t\t\t\tclonedCustomEl.setAttribute('data-tl-custom-element', element.tagName)\n\t\t\t\t;(clonedParent ?? element.parentElement!).appendChild(clonedCustomEl)\n\n\t\t\t\tfor (const child of shadowRoot.childNodes) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedCustomEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedCustomEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.remove()\n\t\t\t} else if (clonedParent) {\n\t\t\t\tif (element.tagName.toLowerCase() === 'style') {\n\t\t\t\t\t// we don't clone style tags at that would break the style scoping. instead we\n\t\t\t\t\t// rely on the computed styles we've already read\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst clonedEl = element.cloneNode(false) as Element\n\t\t\t\tthis.styles.set(clonedEl, this.styles.get(element)!)\n\n\t\t\t\tclonedParent.appendChild(clonedEl)\n\n\t\t\t\tfor (const child of getRenderedChildNodes(element)) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const element of this.styles.keys()) {\n\t\t\tvisit(element, null)\n\t\t}\n\t}\n\n\tembedStyles(): string {\n\t\tlet css = ''\n\n\t\tfor (const [element, info] of this.styles) {\n\t\t\tif (info.after || info.before) {\n\t\t\t\tconst className = `pseudo-${uniqueId()}`\n\t\t\t\telement.classList.add(className)\n\n\t\t\t\tif (info.before) {\n\t\t\t\t\tcss += `.${className}::before {${formatCss(info.before)}}\\n`\n\t\t\t\t}\n\t\t\t\tif (info.after) {\n\t\t\t\t\tcss += `.${className}::after {${formatCss(info.after)}}\\n`\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst style = elementStyle(element)\n\t\t\tfor (const [property, value] of Object.entries(info.self)) {\n\t\t\t\tif (!value) continue\n\t\t\t\tstyle.setProperty(property, value)\n\t\t\t}\n\n\t\t\t// in HTML, font-kerning: auto is equivalent to font-kerning: normal. But in SVG, it's\n\t\t\t// none. We set it to normal here to match the HTML behavior, as otherwise this can\n\t\t\t// cause rendering differences.\n\t\t\tif (style.fontKerning === 'auto') {\n\t\t\t\tstyle.fontKerning = 'normal'\n\t\t\t}\n\t\t}\n\n\t\treturn css\n\t}\n\n\tasync getFontFaceCss() {\n\t\treturn await this.fonts.createCss()\n\t}\n\n\tdispose() {\n\t\tdestroyDefaultStyleFrame()\n\t}\n}\n\ninterface ReadStyleOpts {\n\tdefaultStyles: ReadonlyStyles\n\tparentStyles: ReadonlyStyles\n}\n\nfunction styleFromElement(element: Element, { defaultStyles, parentStyles }: ReadStyleOpts) {\n\t// `computedStyleMap` produces a more accurate representation of the styles, but it's not\n\t// supported in firefox at the time of writing. So we fall back to `getComputedStyle` if it's\n\t// not available.\n\tif (element.computedStyleMap) {\n\t\treturn styleFromComputedStyleMap(element.computedStyleMap(), { defaultStyles, parentStyles })\n\t}\n\treturn styleFromComputedStyle(getComputedStyle(element), { defaultStyles, parentStyles })\n}\n\nfunction styleFromPseudoElement(element: Element, pseudo: string) {\n\t// the equivalent of `computedStyleMap` for pseudo-elements isn't even fully specced out yet, so\n\t// for those we have to use `getComputedStyle` in all browsers.\n\tconst style = getComputedStyle(element, pseudo)\n\n\tconst content = style.getPropertyValue('content')\n\tif (content === '' || content === 'none') {\n\t\treturn undefined\n\t}\n\n\treturn styleFromComputedStyle(style, { defaultStyles: NO_STYLES, parentStyles: NO_STYLES })\n}\n\nfunction styleFromComputedStyleMap(\n\tstyle: StylePropertyMapReadOnly,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tconst currentColor = style.get('color')?.toString() || ''\n\tconst ruleOptions = {\n\t\tcurrentColor,\n\t\tparentStyles,\n\t\tdefaultStyles,\n\t\tgetStyle: (property: string) => style.get(property)?.toString() ?? '',\n\t}\n\tfor (const property of style.keys()) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.get(property)!.toString()\n\n\t\tif (defaultStyles[property] === value) continue\n\n\t\tconst rule = getOwnProperty(cssRules, property)\n\t\tif (rule && rule(value, property, ruleOptions)) continue\n\n\t\tstyles[property] = value\n\t}\n\n\treturn styles\n}\n\nfunction styleFromComputedStyle(\n\tstyle: CSSStyleDeclaration,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tconst currentColor = style.color\n\tconst ruleOptions = {\n\t\tcurrentColor,\n\t\tparentStyles,\n\t\tdefaultStyles,\n\t\tgetStyle: (property: string) => style.getPropertyValue(property),\n\t}\n\n\tfor (const property in style) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.getPropertyValue(property)\n\n\t\tif (defaultStyles[property] === value) continue\n\n\t\tconst rule = getOwnProperty(cssRules, property)\n\t\tif (rule && rule(value, property, ruleOptions)) continue\n\n\t\tstyles[property] = value\n\t}\n\treturn styles\n}\n\nfunction formatCss(style: ReadonlyStyles) {\n\tlet cssText = ''\n\tfor (const [property, value] of Object.entries(style)) {\n\t\tcssText += `${property}: ${value};`\n\t}\n\treturn cssText\n}\n\n// when we're figuring out the default values for a tag, we need read them from a separate document\n// so they're not affected by the current document's styles\nlet defaultStyleFrame:\n\t| { iframe: HTMLIFrameElement; foreignObject: SVGForeignObjectElement; document: Document }\n\t| undefined\nconst defaultStylesByTagName: Record<string, ReadonlyStyles> = {}\nfunction getDefaultStyleFrame() {\n\tif (!defaultStyleFrame) {\n\t\tconst frame = document.createElement('iframe')\n\t\tframe.style.display = 'none'\n\t\tdocument.body.appendChild(frame)\n\t\tconst frameDocument = assertExists(frame.contentDocument, 'frame must have a document')\n\t\tconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n\t\tconst foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')\n\t\tsvg.appendChild(foreignObject)\n\t\tframeDocument.body.appendChild(svg)\n\t\tdefaultStyleFrame = { iframe: frame, foreignObject, document: frameDocument }\n\t}\n\treturn defaultStyleFrame\n}\n\nfunction destroyDefaultStyleFrame() {\n\tif (defaultStyleFrame) {\n\t\tdocument.body.removeChild(defaultStyleFrame.iframe)\n\t\tdefaultStyleFrame = undefined\n\t}\n}\n\nconst defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }\nfunction getDefaultStylesForTagName(tagName: string) {\n\tlet existing = defaultStylesByTagName[tagName]\n\tif (!existing) {\n\t\tconst { foreignObject, document } = getDefaultStyleFrame()\n\t\tconst element = document.createElement(tagName)\n\t\tforeignObject.appendChild(element)\n\t\texisting = element.computedStyleMap\n\t\t\t? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions)\n\t\t\t: styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions)\n\t\tforeignObject.removeChild(element)\n\t\tdefaultStylesByTagName[tagName] = existing\n\t}\n\treturn existing\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,cAAc,gBAAgB,iBAAiB,gBAAgB;AACxE,SAAS,oBAAoB;AAC7B,SAAiC,gBAAgB;AACjD;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,yBAAyB;AAClC,SAAS,mBAAmB,gCAAgC;AAE5D,MAAM,YAAY,CAAC;AAQZ,MAAM,cAAc;AAAA,EAC1B,YAA6B,MAAe;AAAf;AAAA,EAAgB;AAAA,EAC5B,SAAS,oBAAI,IAA+B;AAAA,EACpD,QAAQ,IAAI,aAAa;AAAA,EAElC,sBAAsB,aAAsB;AAE3C,SAAK,kBAAkB,aAAa;AAAA,MACnC,uBAAuB;AAAA,MACvB,iCAAiC;AAAA,IAClC,CAAC;AAED,UAAM,WAAW,MAAM,KAAK,oBAAoB,WAAW,CAAC;AAC5D,WAAO,SAAS,QAAQ;AACvB,YAAM,QAAQ,SAAS,IAAI;AAC3B,eAAS,KAAK,GAAG,oBAAoB,KAAK,CAAC;AAI3C,WAAK,kBAAkB,OAAO;AAAA,QAC7B,uBAAuB;AAAA,QACvB,iCAAiC;AAAA,MAClC,CAAC;AAAA,IACF;AAAA,EACD;AAAA,EAEQ,kBACP,SACA,EAAE,wBAAwB,MAAM,kCAAkC,KAAK,GACtE;AACD,UAAM,gBAAgB,wBACnB,2BAA2B,QAAQ,QAAQ,YAAY,CAAC,
|
|
6
|
-
"names": [
|
|
4
|
+
"sourcesContent": ["import { assertExists, getOwnProperty, objectMapValues, uniqueId } from '@tldraw/utils'\nimport { FontEmbedder } from './FontEmbedder'\nimport { ReadonlyStyles, Styles, cssRules } from './cssRules'\nimport {\n\telementStyle,\n\tgetComputedStyle,\n\tgetRenderedChildNodes,\n\tgetRenderedChildren,\n\tisElement,\n} from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\nimport { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'\n\nconst NO_STYLES = {} as const\n\ninterface ElementStyleInfo {\n\tself: Styles\n\tbefore: Styles | undefined\n\tafter: Styles | undefined\n}\n\nexport class StyleEmbedder {\n\tconstructor(private readonly root: Element) {}\n\tprivate readonly styles = new Map<Element, ElementStyleInfo>()\n\treadonly fonts = new FontEmbedder()\n\n\treadRootElementStyles(rootElement: Element) {\n\t\t// when reading a root, we always apply _all_ the styles, even if they match the defaults\n\t\tthis.readElementStyles(rootElement, {\n\t\t\tshouldRespectDefaults: false,\n\t\t\tshouldSkipInheritedParentStyles: false,\n\t\t})\n\n\t\tconst children = Array.from(getRenderedChildren(rootElement))\n\t\twhile (children.length) {\n\t\t\tconst child = children.pop()!\n\t\t\tchildren.push(...getRenderedChildren(child))\n\n\t\t\t// when reading children, we don't apply styles that match the defaults for that\n\t\t\t// element, or that would be inherited from the parent\n\t\t\tthis.readElementStyles(child, {\n\t\t\t\tshouldRespectDefaults: true,\n\t\t\t\tshouldSkipInheritedParentStyles: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate readElementStyles(\n\t\telement: Element,\n\t\t{ shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }\n\t) {\n\t\tconst defaultStyles = shouldRespectDefaults\n\t\t\t? getDefaultStylesForTagName(element.ownerDocument, element.tagName.toLowerCase())\n\t\t\t: NO_STYLES\n\n\t\tconst parentStyles = Object.assign({}, NO_STYLES) as Styles\n\t\tif (shouldSkipInheritedParentStyles) {\n\t\t\tlet el = element.parentElement\n\t\t\t// Keep going up the tree to find all the relevant styles\n\t\t\twhile (el) {\n\t\t\t\tconst currentStyles = this.styles.get(el)?.self\n\t\t\t\tfor (const style in currentStyles) {\n\t\t\t\t\tif (!parentStyles[style]) {\n\t\t\t\t\t\tparentStyles[style] = currentStyles[style]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tel = el.parentElement\n\t\t\t}\n\t\t}\n\n\t\tconst info: ElementStyleInfo = {\n\t\t\tself: styleFromElement(element, { defaultStyles, parentStyles }),\n\t\t\tbefore: styleFromPseudoElement(element, '::before'),\n\t\t\tafter: styleFromPseudoElement(element, '::after'),\n\t\t}\n\t\tthis.styles.set(element, info)\n\t}\n\n\tfetchResources() {\n\t\tconst promises: Promise<void>[] = []\n\n\t\tfor (const info of this.styles.values()) {\n\t\t\tfor (const styles of objectMapValues(info)) {\n\t\t\t\tif (!styles) continue\n\t\t\t\tfor (const [property, value] of Object.entries(styles)) {\n\t\t\t\t\tif (!value) continue\n\t\t\t\t\tif (property === 'font-family') {\n\t\t\t\t\t\tthis.fonts.onFontFamilyValue(value)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst urlMatches = parseCssValueUrls(value)\n\t\t\t\t\tif (urlMatches.length === 0) continue\n\n\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t...urlMatches.map(async ({ url, original }) => {\n\t\t\t\t\t\t\tconst dataUrl = (await resourceToDataUrl(url)) ?? 'data:'\n\t\t\t\t\t\t\tstyles[property] = value.replace(original, `url(\"${dataUrl}\")`)\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Promise.all(promises)\n\t}\n\n\t// custom elements are tricky. if we serialize the dom as-is, the custom elements wont have\n\t// their shadow-dom contents serialized. after we've read all the styles, we need to unwrap the\n\t// contents of each custom elements shadow dom directly into the parent element itself.\n\tunwrapCustomElements() {\n\t\tconst visited = new Set<Node>()\n\n\t\tconst visit = (element: Element, clonedParent: Element | null) => {\n\t\t\tif (visited.has(element)) return\n\t\t\tvisited.add(element)\n\n\t\t\tconst shadowRoot = element.shadowRoot\n\n\t\t\tif (shadowRoot) {\n\t\t\t\tconst clonedCustomEl = element.ownerDocument.createElement('div')\n\t\t\t\tthis.styles.set(clonedCustomEl, this.styles.get(element)!)\n\n\t\t\t\tclonedCustomEl.setAttribute('data-tl-custom-element', element.tagName)\n\t\t\t\t;(clonedParent ?? element.parentElement!).appendChild(clonedCustomEl)\n\n\t\t\t\tfor (const child of shadowRoot.childNodes) {\n\t\t\t\t\tif (isElement(child)) {\n\t\t\t\t\t\tvisit(child, clonedCustomEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedCustomEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.remove()\n\t\t\t} else if (clonedParent) {\n\t\t\t\tif (element.tagName.toLowerCase() === 'style') {\n\t\t\t\t\t// we don't clone style tags at that would break the style scoping. instead we\n\t\t\t\t\t// rely on the computed styles we've already read\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst clonedEl = element.cloneNode(false) as Element\n\t\t\t\tthis.styles.set(clonedEl, this.styles.get(element)!)\n\n\t\t\t\tclonedParent.appendChild(clonedEl)\n\n\t\t\t\tfor (const child of getRenderedChildNodes(element)) {\n\t\t\t\t\tif (isElement(child)) {\n\t\t\t\t\t\tvisit(child, clonedEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const element of this.styles.keys()) {\n\t\t\tvisit(element, null)\n\t\t}\n\t}\n\n\tembedStyles(): string {\n\t\tlet css = ''\n\n\t\tfor (const [element, info] of this.styles) {\n\t\t\tif (info.after || info.before) {\n\t\t\t\tconst className = `pseudo-${uniqueId()}`\n\t\t\t\telement.classList.add(className)\n\n\t\t\t\tif (info.before) {\n\t\t\t\t\tcss += `.${className}::before {${formatCss(info.before)}}\\n`\n\t\t\t\t}\n\t\t\t\tif (info.after) {\n\t\t\t\t\tcss += `.${className}::after {${formatCss(info.after)}}\\n`\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst style = elementStyle(element)\n\t\t\tfor (const [property, value] of Object.entries(info.self)) {\n\t\t\t\tif (!value) continue\n\t\t\t\tstyle.setProperty(property, value)\n\t\t\t}\n\n\t\t\t// in HTML, font-kerning: auto is equivalent to font-kerning: normal. But in SVG, it's\n\t\t\t// none. We set it to normal here to match the HTML behavior, as otherwise this can\n\t\t\t// cause rendering differences.\n\t\t\tif (style.fontKerning === 'auto') {\n\t\t\t\tstyle.fontKerning = 'normal'\n\t\t\t}\n\t\t}\n\n\t\treturn css\n\t}\n\n\tasync getFontFaceCss() {\n\t\treturn await this.fonts.createCss()\n\t}\n\n\tdispose() {\n\t\tdestroyDefaultStyleFrame()\n\t}\n}\n\ninterface ReadStyleOpts {\n\tdefaultStyles: ReadonlyStyles\n\tparentStyles: ReadonlyStyles\n}\n\nfunction styleFromElement(element: Element, { defaultStyles, parentStyles }: ReadStyleOpts) {\n\t// `computedStyleMap` produces a more accurate representation of the styles, but it's not\n\t// supported in firefox at the time of writing. So we fall back to `getComputedStyle` if it's\n\t// not available.\n\tif (element.computedStyleMap) {\n\t\treturn styleFromComputedStyleMap(element.computedStyleMap(), { defaultStyles, parentStyles })\n\t}\n\treturn styleFromComputedStyle(getComputedStyle(element), { defaultStyles, parentStyles })\n}\n\nfunction styleFromPseudoElement(element: Element, pseudo: string) {\n\t// the equivalent of `computedStyleMap` for pseudo-elements isn't even fully specced out yet, so\n\t// for those we have to use `getComputedStyle` in all browsers.\n\tconst style = getComputedStyle(element, pseudo)\n\n\tconst content = style.getPropertyValue('content')\n\tif (content === '' || content === 'none') {\n\t\treturn undefined\n\t}\n\n\treturn styleFromComputedStyle(style, { defaultStyles: NO_STYLES, parentStyles: NO_STYLES })\n}\n\nfunction styleFromComputedStyleMap(\n\tstyle: StylePropertyMapReadOnly,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tconst currentColor = style.get('color')?.toString() || ''\n\tconst ruleOptions = {\n\t\tcurrentColor,\n\t\tparentStyles,\n\t\tdefaultStyles,\n\t\tgetStyle: (property: string) => style.get(property)?.toString() ?? '',\n\t}\n\tfor (const property of style.keys()) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.get(property)!.toString()\n\n\t\tif (defaultStyles[property] === value) continue\n\n\t\tconst rule = getOwnProperty(cssRules, property)\n\t\tif (rule && rule(value, property, ruleOptions)) continue\n\n\t\tstyles[property] = value\n\t}\n\n\treturn styles\n}\n\nfunction styleFromComputedStyle(\n\tstyle: CSSStyleDeclaration,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tconst currentColor = style.color\n\tconst ruleOptions = {\n\t\tcurrentColor,\n\t\tparentStyles,\n\t\tdefaultStyles,\n\t\tgetStyle: (property: string) => style.getPropertyValue(property),\n\t}\n\n\tfor (const property in style) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.getPropertyValue(property)\n\n\t\tif (defaultStyles[property] === value) continue\n\n\t\tconst rule = getOwnProperty(cssRules, property)\n\t\tif (rule && rule(value, property, ruleOptions)) continue\n\n\t\tstyles[property] = value\n\t}\n\treturn styles\n}\n\nfunction formatCss(style: ReadonlyStyles) {\n\tlet cssText = ''\n\tfor (const [property, value] of Object.entries(style)) {\n\t\tcssText += `${property}: ${value};`\n\t}\n\treturn cssText\n}\n\n// when we're figuring out the default values for a tag, we need read them from a separate document\n// so they're not affected by the current document's styles\nlet defaultStyleFrame:\n\t| {\n\t\t\tiframe: HTMLIFrameElement\n\t\t\tforeignObject: SVGForeignObjectElement\n\t\t\tdocument: Document\n\t\t\townerDocument: Document\n\t }\n\t| undefined\nconst defaultStylesByTagName: Record<string, ReadonlyStyles> = {}\nfunction getDefaultStyleFrame(ownerDoc: Document) {\n\tif (!defaultStyleFrame || defaultStyleFrame.ownerDocument !== ownerDoc) {\n\t\tdestroyDefaultStyleFrame()\n\t\tconst frame = ownerDoc.createElement('iframe')\n\t\tframe.style.display = 'none'\n\t\townerDoc.body.appendChild(frame)\n\t\tconst frameDocument = assertExists(frame.contentDocument, 'frame must have a document')\n\t\tconst svg = frameDocument.createElementNS('http://www.w3.org/2000/svg', 'svg')\n\t\tconst foreignObject = frameDocument.createElementNS(\n\t\t\t'http://www.w3.org/2000/svg',\n\t\t\t'foreignObject'\n\t\t)\n\t\tsvg.appendChild(foreignObject)\n\t\tframeDocument.body.appendChild(svg)\n\t\tdefaultStyleFrame = {\n\t\t\tiframe: frame,\n\t\t\tforeignObject,\n\t\t\tdocument: frameDocument,\n\t\t\townerDocument: ownerDoc,\n\t\t}\n\t}\n\treturn defaultStyleFrame\n}\n\nfunction destroyDefaultStyleFrame() {\n\tif (defaultStyleFrame) {\n\t\tdefaultStyleFrame.iframe.remove()\n\t\tdefaultStyleFrame = undefined\n\t}\n\tfor (const tagName in defaultStylesByTagName) {\n\t\tdelete defaultStylesByTagName[tagName]\n\t}\n}\n\nconst defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }\nfunction getDefaultStylesForTagName(ownerDoc: Document, tagName: string) {\n\tlet existing = defaultStylesByTagName[tagName]\n\tif (!existing) {\n\t\tconst { foreignObject, document } = getDefaultStyleFrame(ownerDoc)\n\t\tconst element = document.createElement(tagName)\n\t\tforeignObject.appendChild(element)\n\t\texisting = element.computedStyleMap\n\t\t\t? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions)\n\t\t\t: styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions)\n\t\tforeignObject.removeChild(element)\n\t\tdefaultStylesByTagName[tagName] = existing\n\t}\n\treturn existing\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
|
@@ -15,6 +15,19 @@ function* getRenderedChildren(node) {
|
|
|
15
15
|
if (isElement(child)) yield child;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
+
function getOwnerWindow(nodeOrDocument) {
|
|
19
|
+
if (!nodeOrDocument) return globalThis;
|
|
20
|
+
const doc = isDocument(nodeOrDocument) ? nodeOrDocument : nodeOrDocument.ownerDocument;
|
|
21
|
+
return doc?.defaultView ?? globalThis;
|
|
22
|
+
}
|
|
23
|
+
function getOwnerDocument(nodeOrDocument) {
|
|
24
|
+
if (!nodeOrDocument) return globalThis.document;
|
|
25
|
+
if (isDocument(nodeOrDocument)) return nodeOrDocument;
|
|
26
|
+
return nodeOrDocument.ownerDocument ?? globalThis.document;
|
|
27
|
+
}
|
|
28
|
+
function isDocument(node) {
|
|
29
|
+
return node.nodeType === Node.DOCUMENT_NODE;
|
|
30
|
+
}
|
|
18
31
|
function getWindow(node) {
|
|
19
32
|
return node.ownerDocument?.defaultView ?? globalThis;
|
|
20
33
|
}
|
|
@@ -39,6 +52,8 @@ function getComputedStyle(element, pseudoElement) {
|
|
|
39
52
|
export {
|
|
40
53
|
elementStyle,
|
|
41
54
|
getComputedStyle,
|
|
55
|
+
getOwnerDocument,
|
|
56
|
+
getOwnerWindow,
|
|
42
57
|
getRenderedChildNodes,
|
|
43
58
|
getRenderedChildren,
|
|
44
59
|
isElement
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/exports/domUtils.ts"],
|
|
4
|
-
"sourcesContent": ["export function getRenderedChildNodes(node: Element): Iterable<Node> {\n\tif (node.shadowRoot) {\n\t\t// if this is a custom element with a shadow root, then it's the shadow root's children that\n\t\t// are visible in the DOM. This is only accessible if they created the shadow root with\n\t\t// `mode: 'open'` though.\n\t\treturn node.shadowRoot.childNodes\n\t}\n\tif (isShadowSlotElement(node)) {\n\t\t// if this is a `<slot>` within a shadow root, we should render the nodes that are being\n\t\t// templated into the slot instead of the slot children itself.\n\t\tconst assignedNodes = node.assignedNodes()\n\t\tif (assignedNodes?.length) {\n\t\t\treturn assignedNodes\n\t\t}\n\t}\n\treturn node.childNodes\n}\n\nexport function* getRenderedChildren(node: Element) {\n\tfor (const child of getRenderedChildNodes(node)) {\n\t\tif (isElement(child)) yield child\n\t}\n}\n\nfunction getWindow(node: Node) {\n\treturn node.ownerDocument?.defaultView ?? globalThis\n}\n\nexport function isElement(node: Node): node is Element {\n\treturn node instanceof getWindow(node).Element\n}\n\nfunction isShadowRoot(node: Node): node is ShadowRoot {\n\treturn node instanceof getWindow(node).ShadowRoot\n}\n\nfunction isInShadowRoot(node: Node) {\n\treturn 'getRootNode' in node && isShadowRoot(node.getRootNode())\n}\n\nfunction isShadowSlotElement(node: Node): node is HTMLSlotElement {\n\treturn isInShadowRoot(node) && node instanceof getWindow(node).HTMLSlotElement\n}\n\nexport function elementStyle(element: Element) {\n\treturn (element as HTMLElement | SVGElement).style\n}\n\nexport function getComputedStyle(element: Element, pseudoElement?: string) {\n\treturn getWindow(element).getComputedStyle(element, pseudoElement)\n}\n"],
|
|
5
|
-
"mappings": "AAAO,SAAS,sBAAsB,MAA+B;AACpE,MAAI,KAAK,YAAY;AAIpB,WAAO,KAAK,WAAW;AAAA,EACxB;AACA,MAAI,oBAAoB,IAAI,GAAG;AAG9B,UAAM,gBAAgB,KAAK,cAAc;AACzC,QAAI,eAAe,QAAQ;AAC1B,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO,KAAK;AACb;AAEO,UAAU,oBAAoB,MAAe;AACnD,aAAW,SAAS,sBAAsB,IAAI,GAAG;AAChD,QAAI,UAAU,KAAK,EAAG,OAAM;AAAA,EAC7B;AACD;AAEA,SAAS,UAAU,MAAY;AAC9B,SAAO,KAAK,eAAe,eAAe;AAC3C;AAEO,SAAS,UAAU,MAA6B;AACtD,SAAO,gBAAgB,UAAU,IAAI,EAAE;AACxC;AAEA,SAAS,aAAa,MAAgC;AACrD,SAAO,gBAAgB,UAAU,IAAI,EAAE;AACxC;AAEA,SAAS,eAAe,MAAY;AACnC,SAAO,iBAAiB,QAAQ,aAAa,KAAK,YAAY,CAAC;AAChE;AAEA,SAAS,oBAAoB,MAAqC;AACjE,SAAO,eAAe,IAAI,KAAK,gBAAgB,UAAU,IAAI,EAAE;AAChE;AAEO,SAAS,aAAa,SAAkB;AAC9C,SAAQ,QAAqC;AAC9C;AAEO,SAAS,iBAAiB,SAAkB,eAAwB;AAC1E,SAAO,UAAU,OAAO,EAAE,iBAAiB,SAAS,aAAa;AAClE;",
|
|
4
|
+
"sourcesContent": ["export function getRenderedChildNodes(node: Element): Iterable<Node> {\n\tif (node.shadowRoot) {\n\t\t// if this is a custom element with a shadow root, then it's the shadow root's children that\n\t\t// are visible in the DOM. This is only accessible if they created the shadow root with\n\t\t// `mode: 'open'` though.\n\t\treturn node.shadowRoot.childNodes\n\t}\n\tif (isShadowSlotElement(node)) {\n\t\t// if this is a `<slot>` within a shadow root, we should render the nodes that are being\n\t\t// templated into the slot instead of the slot children itself.\n\t\tconst assignedNodes = node.assignedNodes()\n\t\tif (assignedNodes?.length) {\n\t\t\treturn assignedNodes\n\t\t}\n\t}\n\treturn node.childNodes\n}\n\nexport function* getRenderedChildren(node: Element) {\n\tfor (const child of getRenderedChildNodes(node)) {\n\t\tif (isElement(child)) yield child\n\t}\n}\n\n/** @internal */\nexport function getOwnerWindow(\n\tnodeOrDocument: Node | Document | null | undefined\n): Window & typeof globalThis {\n\tif (!nodeOrDocument) return globalThis as Window & typeof globalThis\n\tconst doc = isDocument(nodeOrDocument) ? nodeOrDocument : nodeOrDocument.ownerDocument\n\treturn (doc?.defaultView ?? globalThis) as Window & typeof globalThis\n}\n\n/** @internal */\nexport function getOwnerDocument(nodeOrDocument: Node | Document | null | undefined): Document {\n\tif (!nodeOrDocument) return globalThis.document\n\tif (isDocument(nodeOrDocument)) return nodeOrDocument\n\treturn nodeOrDocument.ownerDocument ?? globalThis.document\n}\n\nfunction isDocument(node: Node | Document): node is Document {\n\treturn node.nodeType === Node.DOCUMENT_NODE\n}\n\nfunction getWindow(node: Node) {\n\treturn node.ownerDocument?.defaultView ?? globalThis\n}\n\nexport function isElement(node: Node): node is Element {\n\treturn node instanceof getWindow(node).Element\n}\n\nfunction isShadowRoot(node: Node): node is ShadowRoot {\n\treturn node instanceof getWindow(node).ShadowRoot\n}\n\nfunction isInShadowRoot(node: Node) {\n\treturn 'getRootNode' in node && isShadowRoot(node.getRootNode())\n}\n\nfunction isShadowSlotElement(node: Node): node is HTMLSlotElement {\n\treturn isInShadowRoot(node) && node instanceof getWindow(node).HTMLSlotElement\n}\n\nexport function elementStyle(element: Element) {\n\treturn (element as HTMLElement | SVGElement).style\n}\n\nexport function getComputedStyle(element: Element, pseudoElement?: string) {\n\treturn getWindow(element).getComputedStyle(element, pseudoElement)\n}\n"],
|
|
5
|
+
"mappings": "AAAO,SAAS,sBAAsB,MAA+B;AACpE,MAAI,KAAK,YAAY;AAIpB,WAAO,KAAK,WAAW;AAAA,EACxB;AACA,MAAI,oBAAoB,IAAI,GAAG;AAG9B,UAAM,gBAAgB,KAAK,cAAc;AACzC,QAAI,eAAe,QAAQ;AAC1B,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO,KAAK;AACb;AAEO,UAAU,oBAAoB,MAAe;AACnD,aAAW,SAAS,sBAAsB,IAAI,GAAG;AAChD,QAAI,UAAU,KAAK,EAAG,OAAM;AAAA,EAC7B;AACD;AAGO,SAAS,eACf,gBAC6B;AAC7B,MAAI,CAAC,eAAgB,QAAO;AAC5B,QAAM,MAAM,WAAW,cAAc,IAAI,iBAAiB,eAAe;AACzE,SAAQ,KAAK,eAAe;AAC7B;AAGO,SAAS,iBAAiB,gBAA8D;AAC9F,MAAI,CAAC,eAAgB,QAAO,WAAW;AACvC,MAAI,WAAW,cAAc,EAAG,QAAO;AACvC,SAAO,eAAe,iBAAiB,WAAW;AACnD;AAEA,SAAS,WAAW,MAAyC;AAC5D,SAAO,KAAK,aAAa,KAAK;AAC/B;AAEA,SAAS,UAAU,MAAY;AAC9B,SAAO,KAAK,eAAe,eAAe;AAC3C;AAEO,SAAS,UAAU,MAA6B;AACtD,SAAO,gBAAgB,UAAU,IAAI,EAAE;AACxC;AAEA,SAAS,aAAa,MAAgC;AACrD,SAAO,gBAAgB,UAAU,IAAI,EAAE;AACxC;AAEA,SAAS,eAAe,MAAY;AACnC,SAAO,iBAAiB,QAAQ,aAAa,KAAK,YAAY,CAAC;AAChE;AAEA,SAAS,oBAAoB,MAAqC;AACjE,SAAO,eAAe,IAAI,KAAK,gBAAgB,UAAU,IAAI,EAAE;AAChE;AAEO,SAAS,aAAa,SAAkB;AAC9C,SAAQ,QAAqC;AAC9C;AAEO,SAAS,iBAAiB,SAAkB,eAAwB;AAC1E,SAAO,UAAU,OAAO,EAAE,iBAAiB,SAAS,aAAa;AAClE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MediaHelpers } from "@tldraw/utils";
|
|
2
|
-
import { getRenderedChildren } from "./domUtils.mjs";
|
|
2
|
+
import { getOwnerWindow, getRenderedChildren } from "./domUtils.mjs";
|
|
3
3
|
import { resourceToDataUrl } from "./fetchCache.mjs";
|
|
4
4
|
function copyAttrs(source, target) {
|
|
5
5
|
const attrs = Array.from(source.attributes);
|
|
@@ -11,8 +11,8 @@ function replace(original, replacement) {
|
|
|
11
11
|
original.replaceWith(replacement);
|
|
12
12
|
return replacement;
|
|
13
13
|
}
|
|
14
|
-
async function createImage(dataUrl, cloneAttributesFrom) {
|
|
15
|
-
const image =
|
|
14
|
+
async function createImage(doc, dataUrl, cloneAttributesFrom) {
|
|
15
|
+
const image = doc.createElement("img");
|
|
16
16
|
if (cloneAttributesFrom) {
|
|
17
17
|
copyAttrs(cloneAttributesFrom, image);
|
|
18
18
|
}
|
|
@@ -26,32 +26,35 @@ async function createImage(dataUrl, cloneAttributesFrom) {
|
|
|
26
26
|
return image;
|
|
27
27
|
}
|
|
28
28
|
async function getCanvasReplacement(canvas) {
|
|
29
|
+
const doc = canvas.ownerDocument;
|
|
29
30
|
try {
|
|
30
31
|
const dataURL = canvas.toDataURL();
|
|
31
|
-
return await createImage(dataURL, canvas);
|
|
32
|
+
return await createImage(doc, dataURL, canvas);
|
|
32
33
|
} catch {
|
|
33
|
-
return await createImage(null, canvas);
|
|
34
|
+
return await createImage(doc, null, canvas);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
async function getVideoReplacement(video) {
|
|
38
|
+
const doc = video.ownerDocument;
|
|
37
39
|
try {
|
|
38
40
|
const dataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video);
|
|
39
|
-
return createImage(dataUrl, video);
|
|
41
|
+
return createImage(doc, dataUrl, video);
|
|
40
42
|
} catch (err) {
|
|
41
43
|
console.error("Could not get video frame", err);
|
|
42
44
|
}
|
|
43
45
|
if (video.poster) {
|
|
44
46
|
const dataUrl = await resourceToDataUrl(video.poster);
|
|
45
|
-
return createImage(dataUrl, video);
|
|
47
|
+
return createImage(doc, dataUrl, video);
|
|
46
48
|
}
|
|
47
|
-
return createImage(null, video);
|
|
49
|
+
return createImage(doc, null, video);
|
|
48
50
|
}
|
|
49
51
|
async function embedMedia(node) {
|
|
50
|
-
|
|
52
|
+
const win = getOwnerWindow(node);
|
|
53
|
+
if (node instanceof win.HTMLCanvasElement) {
|
|
51
54
|
return replace(node, await getCanvasReplacement(node));
|
|
52
|
-
} else if (node instanceof HTMLVideoElement) {
|
|
55
|
+
} else if (node instanceof win.HTMLVideoElement) {
|
|
53
56
|
return replace(node, await getVideoReplacement(node));
|
|
54
|
-
} else if (node instanceof HTMLImageElement) {
|
|
57
|
+
} else if (node instanceof win.HTMLImageElement) {
|
|
55
58
|
const src = node.currentSrc || node.src;
|
|
56
59
|
const dataUrl = await resourceToDataUrl(src);
|
|
57
60
|
node.setAttribute("src", dataUrl ?? "data:");
|
|
@@ -62,9 +65,9 @@ async function embedMedia(node) {
|
|
|
62
65
|
} catch {
|
|
63
66
|
}
|
|
64
67
|
return node;
|
|
65
|
-
} else if (node instanceof HTMLInputElement) {
|
|
68
|
+
} else if (node instanceof win.HTMLInputElement) {
|
|
66
69
|
node.setAttribute("value", node.value);
|
|
67
|
-
} else if (node instanceof HTMLTextAreaElement) {
|
|
70
|
+
} else if (node instanceof win.HTMLTextAreaElement) {
|
|
68
71
|
node.textContent = node.value;
|
|
69
72
|
}
|
|
70
73
|
await Promise.all(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/exports/embedMedia.ts"],
|
|
4
|
-
"sourcesContent": ["import { MediaHelpers } from '@tldraw/utils'\nimport { getRenderedChildren } from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\n\nfunction copyAttrs(source: Element, target: Element) {\n\tconst attrs = Array.from(source.attributes)\n\tattrs.forEach((attr) => {\n\t\ttarget.setAttribute(attr.name, attr.value)\n\t})\n}\n\nfunction replace(original: HTMLElement, replacement: HTMLElement) {\n\toriginal.replaceWith(replacement)\n\treturn replacement\n}\n\nasync function createImage(
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;
|
|
4
|
+
"sourcesContent": ["import { MediaHelpers } from '@tldraw/utils'\nimport { getOwnerWindow, getRenderedChildren } from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\n\nfunction copyAttrs(source: Element, target: Element) {\n\tconst attrs = Array.from(source.attributes)\n\tattrs.forEach((attr) => {\n\t\ttarget.setAttribute(attr.name, attr.value)\n\t})\n}\n\nfunction replace(original: HTMLElement, replacement: HTMLElement) {\n\toriginal.replaceWith(replacement)\n\treturn replacement\n}\n\nasync function createImage(\n\tdoc: Document,\n\tdataUrl: string | null,\n\tcloneAttributesFrom?: HTMLElement\n) {\n\tconst image = doc.createElement('img')\n\n\tif (cloneAttributesFrom) {\n\t\tcopyAttrs(cloneAttributesFrom, image)\n\t}\n\n\timage.setAttribute('src', dataUrl ?? 'data:')\n\timage.setAttribute('decoding', 'sync')\n\timage.setAttribute('loading', 'eager')\n\n\ttry {\n\t\tawait image.decode()\n\t} catch {\n\t\t// this is fine\n\t}\n\treturn image\n}\n\nasync function getCanvasReplacement(canvas: HTMLCanvasElement) {\n\tconst doc = canvas.ownerDocument\n\ttry {\n\t\tconst dataURL = canvas.toDataURL()\n\t\treturn await createImage(doc, dataURL, canvas)\n\t} catch {\n\t\treturn await createImage(doc, null, canvas)\n\t}\n}\n\nasync function getVideoReplacement(video: HTMLVideoElement) {\n\tconst doc = video.ownerDocument\n\ttry {\n\t\tconst dataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video)\n\t\treturn createImage(doc, dataUrl, video)\n\t} catch (err) {\n\t\tconsole.error('Could not get video frame', err)\n\t}\n\n\tif (video.poster) {\n\t\tconst dataUrl = await resourceToDataUrl(video.poster)\n\t\treturn createImage(doc, dataUrl, video)\n\t}\n\n\treturn createImage(doc, null, video)\n}\n\nexport async function embedMedia(node: HTMLElement) {\n\tconst win = getOwnerWindow(node)\n\tif (node instanceof win.HTMLCanvasElement) {\n\t\treturn replace(node, await getCanvasReplacement(node))\n\t} else if (node instanceof win.HTMLVideoElement) {\n\t\treturn replace(node, await getVideoReplacement(node))\n\t} else if (node instanceof win.HTMLImageElement) {\n\t\tconst src = node.currentSrc || node.src\n\t\tconst dataUrl = await resourceToDataUrl(src)\n\t\tnode.setAttribute('src', dataUrl ?? 'data:')\n\t\tnode.setAttribute('decoding', 'sync')\n\t\tnode.setAttribute('loading', 'eager')\n\t\ttry {\n\t\t\tawait (node as HTMLImageElement).decode()\n\t\t} catch {\n\t\t\t// this is fine\n\t\t}\n\t\treturn node\n\t} else if (node instanceof win.HTMLInputElement) {\n\t\tnode.setAttribute('value', (node as HTMLInputElement).value)\n\t} else if (node instanceof win.HTMLTextAreaElement) {\n\t\tnode.textContent = (node as HTMLTextAreaElement).value\n\t}\n\n\tawait Promise.all(\n\t\tArray.from(getRenderedChildren(node), (child) => embedMedia(child as HTMLElement))\n\t)\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,2BAA2B;AACpD,SAAS,yBAAyB;AAElC,SAAS,UAAU,QAAiB,QAAiB;AACpD,QAAM,QAAQ,MAAM,KAAK,OAAO,UAAU;AAC1C,QAAM,QAAQ,CAAC,SAAS;AACvB,WAAO,aAAa,KAAK,MAAM,KAAK,KAAK;AAAA,EAC1C,CAAC;AACF;AAEA,SAAS,QAAQ,UAAuB,aAA0B;AACjE,WAAS,YAAY,WAAW;AAChC,SAAO;AACR;AAEA,eAAe,YACd,KACA,SACA,qBACC;AACD,QAAM,QAAQ,IAAI,cAAc,KAAK;AAErC,MAAI,qBAAqB;AACxB,cAAU,qBAAqB,KAAK;AAAA,EACrC;AAEA,QAAM,aAAa,OAAO,WAAW,OAAO;AAC5C,QAAM,aAAa,YAAY,MAAM;AACrC,QAAM,aAAa,WAAW,OAAO;AAErC,MAAI;AACH,UAAM,MAAM,OAAO;AAAA,EACpB,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAEA,eAAe,qBAAqB,QAA2B;AAC9D,QAAM,MAAM,OAAO;AACnB,MAAI;AACH,UAAM,UAAU,OAAO,UAAU;AACjC,WAAO,MAAM,YAAY,KAAK,SAAS,MAAM;AAAA,EAC9C,QAAQ;AACP,WAAO,MAAM,YAAY,KAAK,MAAM,MAAM;AAAA,EAC3C;AACD;AAEA,eAAe,oBAAoB,OAAyB;AAC3D,QAAM,MAAM,MAAM;AAClB,MAAI;AACH,UAAM,UAAU,MAAM,aAAa,uBAAuB,KAAK;AAC/D,WAAO,YAAY,KAAK,SAAS,KAAK;AAAA,EACvC,SAAS,KAAK;AACb,YAAQ,MAAM,6BAA6B,GAAG;AAAA,EAC/C;AAEA,MAAI,MAAM,QAAQ;AACjB,UAAM,UAAU,MAAM,kBAAkB,MAAM,MAAM;AACpD,WAAO,YAAY,KAAK,SAAS,KAAK;AAAA,EACvC;AAEA,SAAO,YAAY,KAAK,MAAM,KAAK;AACpC;AAEA,eAAsB,WAAW,MAAmB;AACnD,QAAM,MAAM,eAAe,IAAI;AAC/B,MAAI,gBAAgB,IAAI,mBAAmB;AAC1C,WAAO,QAAQ,MAAM,MAAM,qBAAqB,IAAI,CAAC;AAAA,EACtD,WAAW,gBAAgB,IAAI,kBAAkB;AAChD,WAAO,QAAQ,MAAM,MAAM,oBAAoB,IAAI,CAAC;AAAA,EACrD,WAAW,gBAAgB,IAAI,kBAAkB;AAChD,UAAM,MAAM,KAAK,cAAc,KAAK;AACpC,UAAM,UAAU,MAAM,kBAAkB,GAAG;AAC3C,SAAK,aAAa,OAAO,WAAW,OAAO;AAC3C,SAAK,aAAa,YAAY,MAAM;AACpC,SAAK,aAAa,WAAW,OAAO;AACpC,QAAI;AACH,YAAO,KAA0B,OAAO;AAAA,IACzC,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACR,WAAW,gBAAgB,IAAI,kBAAkB;AAChD,SAAK,aAAa,SAAU,KAA0B,KAAK;AAAA,EAC5D,WAAW,gBAAgB,IAAI,qBAAqB;AACnD,SAAK,cAAe,KAA6B;AAAA,EAClD;AAEA,QAAM,QAAQ;AAAA,IACb,MAAM,KAAK,oBAAoB,IAAI,GAAG,CAAC,UAAU,WAAW,KAAoB,CAAC;AAAA,EAClF;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { assert } from "@tldraw/utils";
|
|
2
2
|
import { flushSync } from "react-dom";
|
|
3
3
|
import { createRoot } from "react-dom/client";
|
|
4
|
-
import {
|
|
5
|
-
import { StyleEmbedder } from "./StyleEmbedder.mjs";
|
|
4
|
+
import { getOwnerWindow } from "./domUtils.mjs";
|
|
6
5
|
import { embedMedia } from "./embedMedia.mjs";
|
|
6
|
+
import { SVG_EXPORT_CLASSNAME } from "./FontEmbedder.mjs";
|
|
7
7
|
import { getSvgJsx } from "./getSvgJsx.mjs";
|
|
8
|
+
import { StyleEmbedder } from "./StyleEmbedder.mjs";
|
|
8
9
|
let idCounter = 1;
|
|
9
10
|
async function exportToSvg(editor, shapeIds, opts = {}) {
|
|
10
11
|
const result = getSvgJsx(editor, shapeIds, opts);
|
|
11
12
|
if (!result) return void 0;
|
|
12
13
|
const container = editor.getContainer();
|
|
13
|
-
const renderTarget =
|
|
14
|
+
const renderTarget = container.ownerDocument.createElement("div");
|
|
14
15
|
renderTarget.className = SVG_EXPORT_CLASSNAME;
|
|
15
16
|
renderTarget.inert = true;
|
|
16
17
|
renderTarget.tabIndex = -1;
|
|
@@ -32,9 +33,9 @@ async function exportToSvg(editor, shapeIds, opts = {}) {
|
|
|
32
33
|
});
|
|
33
34
|
await result.exportDelay.resolve();
|
|
34
35
|
const svg = renderTarget.firstElementChild;
|
|
35
|
-
assert(svg instanceof SVGSVGElement, "Expected an SVG element");
|
|
36
|
+
assert(svg instanceof getOwnerWindow(container).SVGSVGElement, "Expected an SVG element");
|
|
36
37
|
await applyChangesToForeignObjects(svg);
|
|
37
|
-
return { svg, width: result.width, height: result.height };
|
|
38
|
+
return { svg, width: result.width, height: result.height, trimPadding: result.trimPadding };
|
|
38
39
|
} finally {
|
|
39
40
|
setTimeout(() => {
|
|
40
41
|
root.unmount();
|
|
@@ -49,7 +50,7 @@ async function applyChangesToForeignObjects(svg) {
|
|
|
49
50
|
if (!foreignObjectChildren.length) return;
|
|
50
51
|
const styleEmbedder = new StyleEmbedder(svg);
|
|
51
52
|
try {
|
|
52
|
-
styleEmbedder.fonts.
|
|
53
|
+
styleEmbedder.fonts.startFindingDocumentFontFaces(svg.ownerDocument);
|
|
53
54
|
await Promise.all(foreignObjectChildren.map((el) => embedMedia(el)));
|
|
54
55
|
for (const el of foreignObjectChildren) {
|
|
55
56
|
styleEmbedder.readRootElementStyles(el);
|
|
@@ -59,7 +60,7 @@ async function applyChangesToForeignObjects(svg) {
|
|
|
59
60
|
styleEmbedder.unwrapCustomElements();
|
|
60
61
|
const pseudoCss = styleEmbedder.embedStyles();
|
|
61
62
|
if (fontCss || pseudoCss) {
|
|
62
|
-
const style =
|
|
63
|
+
const style = svg.ownerDocument.createElementNS("http://www.w3.org/2000/svg", "style");
|
|
63
64
|
style.textContent = `${fontCss}
|
|
64
65
|
${pseudoCss}`;
|
|
65
66
|
svg.prepend(style);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/exports/exportToSvg.tsx"],
|
|
4
|
-
"sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport type { Editor } from '../editor/Editor'\nimport { TLSvgExportOptions } from '../editor/types/misc-types'\nimport {
|
|
5
|
-
"mappings": "AACA,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAG3B,SAAS,
|
|
4
|
+
"sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport type { Editor } from '../editor/Editor'\nimport { TLSvgExportOptions } from '../editor/types/misc-types'\nimport { getOwnerWindow } from './domUtils'\nimport { embedMedia } from './embedMedia'\nimport { SVG_EXPORT_CLASSNAME } from './FontEmbedder'\nimport { getSvgJsx } from './getSvgJsx'\nimport { StyleEmbedder } from './StyleEmbedder'\n\nlet idCounter = 1\n\nexport async function exportToSvg(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts: TLSvgExportOptions = {}\n) {\n\t// when rendering to SVG, we start by creating a JSX representation of the SVG that we can\n\t// render with react. Hopefully elements will have a `toSvg` method that renders them to SVG,\n\t// but if they don't we'll render their normal HTML content into an svg <foreignObject> element.\n\tconst result = getSvgJsx(editor, shapeIds, opts)\n\tif (!result) return undefined\n\n\t// we need to render that SVG into a real DOM element that's actually laid out in the document.\n\t// without this CSS and layout aren't computed correctly, which we need to make sure any\n\t// <foreignObject> elements have their styles and content inlined correctly.\n\tconst container = editor.getContainer()\n\tconst renderTarget = container.ownerDocument.createElement('div')\n\trenderTarget.className = SVG_EXPORT_CLASSNAME\n\t// we hide the element visually, but we don't want it to be focusable or interactive in any way either\n\trenderTarget.inert = true\n\trenderTarget.tabIndex = -1\n\tObject.assign(renderTarget.style, {\n\t\tposition: 'absolute',\n\t\ttop: '0px',\n\t\tleft: '0px',\n\t\twidth: result.width + 'px',\n\t\theight: result.height + 'px',\n\t\tpointerEvents: 'none',\n\t\topacity: 0,\n\t})\n\t// we have to add the element to the document as otherwise styles won't be computed correctly.\n\tcontainer.appendChild(renderTarget)\n\n\t// create a react root...\n\tconst root = createRoot(renderTarget, { identifierPrefix: `export_${idCounter++}_` })\n\ttry {\n\t\t// ...wait for a tick so we know we're not in e.g. a react lifecycle method...\n\t\tawait Promise.resolve()\n\n\t\t// ...and render the SVG into it.\n\t\tflushSync(() => {\n\t\t\troot.render(result.jsx)\n\t\t})\n\n\t\t// Some operations take a while - for example, waiting for an asset to load in. We give\n\t\t// shape authors a way to delay snap-shotting the export until they're ready.\n\t\tawait result.exportDelay.resolve()\n\n\t\t// Extract the rendered SVG element from the react root\n\t\tconst svg = renderTarget.firstElementChild\n\t\tassert(svg instanceof getOwnerWindow(container).SVGSVGElement, 'Expected an SVG element')\n\n\t\t// And apply any changes to <foreignObject> elements that we need to make. while we're in\n\t\t// the document, these elements work exactly as we'd expect from other dom elements - they\n\t\t// can load external resources, and any stylesheets in the document apply to them as we\n\t\t// would expect them to. But when we pull the SVG into its own file or draw it to a canvas\n\t\t// though, it has to be completely self-contained. We embed any external resources, and\n\t\t// apply any styles directly to the elements themselves.\n\t\tawait applyChangesToForeignObjects(svg)\n\n\t\treturn { svg, width: result.width, height: result.height, trimPadding: result.trimPadding }\n\t} finally {\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tsetTimeout(() => {\n\t\t\t// we wait for a cycle of the event loop to allow the svg to be cloned etc. before\n\t\t\t// unmounting\n\t\t\troot.unmount()\n\t\t\tcontainer.removeChild(renderTarget)\n\t\t}, 0)\n\t}\n}\n\nasync function applyChangesToForeignObjects(svg: SVGSVGElement) {\n\t// If any shapes have their own <foreignObject> elements, we don't want to mess with them. Our\n\t// ones that we need to embed will have a class of `tl-export-embed-styles`.\n\tconst foreignObjectChildren = [\n\t\t...svg.querySelectorAll('foreignObject.tl-export-embed-styles > *'),\n\t]\n\tif (!foreignObjectChildren.length) return\n\n\t// StyleEmbedder embeds any CSS - including resources like fonts and images.\n\tconst styleEmbedder = new StyleEmbedder(svg)\n\n\ttry {\n\t\t// begin traversing stylesheets to find @font-face declarations we might need to embed\n\t\tstyleEmbedder.fonts.startFindingDocumentFontFaces(svg.ownerDocument)\n\n\t\t// embed any media elements in the foreignObject children. images will get converted to data\n\t\t// urls, and things like videos will be converted to images.\n\t\tawait Promise.all(foreignObjectChildren.map((el) => embedMedia(el as HTMLElement)))\n\n\t\t// read the computed styles of every element (+ it's children & pseudo-elements) in the\n\t\t// document. we do this in a single pass before we start embedding any CSS stuff to avoid\n\t\t// constantly forcing the browser to recompute styles & layout.\n\t\tfor (const el of foreignObjectChildren) {\n\t\t\tstyleEmbedder.readRootElementStyles(el as HTMLElement)\n\t\t}\n\n\t\t// fetch any resources that we need to embed in the CSS, like background images.\n\t\tawait styleEmbedder.fetchResources()\n\t\tconst fontCss = await styleEmbedder.getFontFaceCss()\n\n\t\t// custom elements that make use of the shadow dom won't be serialized correctly by default:\n\t\t// the contents of the shadow dom will be ignored. once we've read the styles from the\n\t\t// document, we go through and replace any custom elements with plain `<div>`s. as we do so,\n\t\t// we traverse the shadow dom and clone it into the new plain div. any scoped stylesheets\n\t\t// are removed, as we've already read all the computed styles above.\n\t\tstyleEmbedder.unwrapCustomElements()\n\n\t\t// apply the computed styles (with their embedded resources) directly to the elements with\n\t\t// their `style` attribute. Anything that can't be done this way (pseudo-elements) will be\n\t\t// returned as a string of CSS.\n\t\tconst pseudoCss = styleEmbedder.embedStyles()\n\n\t\t// add the CSS to the SVG\n\t\tif (fontCss || pseudoCss) {\n\t\t\tconst style = svg.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'style')\n\t\t\tstyle.textContent = `${fontCss}\\n${pseudoCss}`\n\t\t\tsvg.prepend(style)\n\t\t}\n\t} finally {\n\t\tstyleEmbedder.dispose()\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAG3B,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;AACrC,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAE9B,IAAI,YAAY;AAEhB,eAAsB,YACrB,QACA,UACA,OAA2B,CAAC,GAC3B;AAID,QAAM,SAAS,UAAU,QAAQ,UAAU,IAAI;AAC/C,MAAI,CAAC,OAAQ,QAAO;AAKpB,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,eAAe,UAAU,cAAc,cAAc,KAAK;AAChE,eAAa,YAAY;AAEzB,eAAa,QAAQ;AACrB,eAAa,WAAW;AACxB,SAAO,OAAO,aAAa,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO,OAAO,QAAQ;AAAA,IACtB,QAAQ,OAAO,SAAS;AAAA,IACxB,eAAe;AAAA,IACf,SAAS;AAAA,EACV,CAAC;AAED,YAAU,YAAY,YAAY;AAGlC,QAAM,OAAO,WAAW,cAAc,EAAE,kBAAkB,UAAU,WAAW,IAAI,CAAC;AACpF,MAAI;AAEH,UAAM,QAAQ,QAAQ;AAGtB,cAAU,MAAM;AACf,WAAK,OAAO,OAAO,GAAG;AAAA,IACvB,CAAC;AAID,UAAM,OAAO,YAAY,QAAQ;AAGjC,UAAM,MAAM,aAAa;AACzB,WAAO,eAAe,eAAe,SAAS,EAAE,eAAe,yBAAyB;AAQxF,UAAM,6BAA6B,GAAG;AAEtC,WAAO,EAAE,KAAK,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,aAAa,OAAO,YAAY;AAAA,EAC3F,UAAE;AAED,eAAW,MAAM;AAGhB,WAAK,QAAQ;AACb,gBAAU,YAAY,YAAY;AAAA,IACnC,GAAG,CAAC;AAAA,EACL;AACD;AAEA,eAAe,6BAA6B,KAAoB;AAG/D,QAAM,wBAAwB;AAAA,IAC7B,GAAG,IAAI,iBAAiB,0CAA0C;AAAA,EACnE;AACA,MAAI,CAAC,sBAAsB,OAAQ;AAGnC,QAAM,gBAAgB,IAAI,cAAc,GAAG;AAE3C,MAAI;AAEH,kBAAc,MAAM,8BAA8B,IAAI,aAAa;AAInE,UAAM,QAAQ,IAAI,sBAAsB,IAAI,CAAC,OAAO,WAAW,EAAiB,CAAC,CAAC;AAKlF,eAAW,MAAM,uBAAuB;AACvC,oBAAc,sBAAsB,EAAiB;AAAA,IACtD;AAGA,UAAM,cAAc,eAAe;AACnC,UAAM,UAAU,MAAM,cAAc,eAAe;AAOnD,kBAAc,qBAAqB;AAKnC,UAAM,YAAY,cAAc,YAAY;AAG5C,QAAI,WAAW,WAAW;AACzB,YAAM,QAAQ,IAAI,cAAc,gBAAgB,8BAA8B,OAAO;AACrF,YAAM,cAAc,GAAG,OAAO;AAAA,EAAK,SAAS;AAC5C,UAAI,QAAQ,KAAK;AAAA,IAClB;AAAA,EACD,UAAE;AACD,kBAAc,QAAQ;AAAA,EACvB;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|