Fix svg exporting for images with not fully qualified url (/tldraw.png or ./tldraw.png) (#2676)

Local images (like in our Local images example) could not be exported as
svg. We need to base64 encode them, but our check only matched images
with a `http` prefix, which local images like `/tldraw.png` don't have.

Fixes an issue reported here

https://discord.com/channels/859816885297741824/1198343938155745280/1198343938155745280

### Change Type

- [x] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Use our Local images example.
2. Export as svg.
3. The export should correctly show the image.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Fix the svg export for images that have a local url.

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
Mitja Bezenšek 2024-01-30 11:11:10 +01:00 committed by GitHub
parent 6fe829f990
commit 7ac003cc05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 1 deletions

View file

@ -830,6 +830,8 @@ export class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {
} | null>;
};
// (undocumented)
shouldGetDataURI(src: string): "" | boolean;
// (undocumented)
toSvg(shape: TLImageShape): Promise<SVGGElement>;
// (undocumented)
static type: "image";

View file

@ -9756,6 +9756,54 @@
"isProtected": false,
"isAbstract": false
},
{
"kind": "Method",
"canonicalReference": "@tldraw/tldraw!ImageShapeUtil#shouldGetDataURI:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "shouldGetDataURI(src: "
},
{
"kind": "Content",
"text": "string"
},
{
"kind": "Content",
"text": "): "
},
{
"kind": "Content",
"text": "\"\" | boolean"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 3,
"endIndex": 4
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [
{
"parameterName": "src",
"parameterTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"isOptional": false
}
],
"isOptional": false,
"isAbstract": false,
"name": "shouldGetDataURI"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/tldraw!ImageShapeUtil#toSvg:member(1)",

View file

@ -170,12 +170,16 @@ export class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {
return <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />
}
shouldGetDataURI(src: string) {
return src && (src.startsWith('http') || src.startsWith('/') || src.startsWith('./'))
}
override async toSvg(shape: TLImageShape) {
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
const asset = shape.props.assetId ? this.editor.getAsset(shape.props.assetId) : null
let src = asset?.props.src || ''
if (src && src.startsWith('http')) {
if (this.shouldGetDataURI(src)) {
// If it's a remote image, we need to fetch it and convert it to a data URI
src = (await getDataURIFromURL(src)) || ''
}