headless-svg-to-excalidraw 0.0.9 → 0.0.11
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/index.d.mts +147 -2
- package/dist/index.mjs +76 -76
- package/package.json +53 -54
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,153 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
declare const FONT_FAMILY: {
|
|
3
|
+
readonly 1: "Virgil";
|
|
4
|
+
readonly 2: "Helvetica";
|
|
5
|
+
readonly 3: "Cascadia";
|
|
6
|
+
};
|
|
7
|
+
declare type RoughPoint = [number, number];
|
|
8
|
+
type Point$1 = Readonly<RoughPoint>;
|
|
9
|
+
type FillStyle = "hachure" | "cross-hatch" | "solid";
|
|
10
|
+
type FontFamily = keyof typeof FONT_FAMILY;
|
|
11
|
+
type GroupId = string;
|
|
12
|
+
type StrokeSharpness = "round" | "sharp";
|
|
13
|
+
type StrokeStyle = "solid" | "dashed" | "dotted";
|
|
14
|
+
type TextAlign = "left" | "center" | "right";
|
|
15
|
+
type VerticalAlign = "top" | "middle";
|
|
16
|
+
type _ExcalidrawElementBase = Readonly<{
|
|
17
|
+
id: string;
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
strokeColor: string;
|
|
21
|
+
backgroundColor: string;
|
|
22
|
+
fillStyle: FillStyle;
|
|
23
|
+
strokeWidth: number;
|
|
24
|
+
strokeStyle: StrokeStyle;
|
|
25
|
+
strokeSharpness: StrokeSharpness;
|
|
26
|
+
roughness: number;
|
|
27
|
+
opacity: number;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
angle: number;
|
|
31
|
+
/** Random integer used to seed shape generation so that the roughjs shape
|
|
32
|
+
doesn't differ across renders. */
|
|
33
|
+
seed: number;
|
|
34
|
+
/** Integer that is sequentially incremented on each change. Used to reconcile
|
|
35
|
+
elements during collaboration or when saving to server. */
|
|
36
|
+
version: number;
|
|
37
|
+
/** Random integer that is regenerated on each change.
|
|
38
|
+
Used for deterministic reconciliation of updates during collaboration,
|
|
39
|
+
in case the versions (see above) are identical. */
|
|
40
|
+
versionNonce: number;
|
|
41
|
+
isDeleted: boolean;
|
|
42
|
+
/** List of groups the element belongs to.
|
|
43
|
+
Ordered from deepest to shallowest. */
|
|
44
|
+
groupIds: readonly GroupId[]; /** Ids of (linear) elements that are bound to this element. */
|
|
45
|
+
boundElementIds: readonly ExcalidrawLinearElement["id"][] | null;
|
|
46
|
+
}>;
|
|
47
|
+
type ExcalidrawRectangleElement = _ExcalidrawElementBase & {
|
|
48
|
+
type: "rectangle";
|
|
49
|
+
};
|
|
50
|
+
type ExcalidrawDiamondElement = _ExcalidrawElementBase & {
|
|
51
|
+
type: "diamond";
|
|
52
|
+
};
|
|
53
|
+
type ExcalidrawEllipseElement = _ExcalidrawElementBase & {
|
|
54
|
+
type: "ellipse";
|
|
55
|
+
};
|
|
56
|
+
type ExcalidrawTextElement = _ExcalidrawElementBase & Readonly<{
|
|
57
|
+
type: "text";
|
|
58
|
+
fontSize: number;
|
|
59
|
+
fontFamily: FontFamily;
|
|
60
|
+
text: string;
|
|
61
|
+
baseline: number;
|
|
62
|
+
textAlign: TextAlign;
|
|
63
|
+
verticalAlign: VerticalAlign;
|
|
64
|
+
}>;
|
|
65
|
+
type ExcalidrawBindableElement = ExcalidrawRectangleElement | ExcalidrawDiamondElement | ExcalidrawEllipseElement | ExcalidrawTextElement;
|
|
66
|
+
type PointBinding = {
|
|
67
|
+
elementId: ExcalidrawBindableElement["id"];
|
|
68
|
+
focus: number;
|
|
69
|
+
gap: number;
|
|
70
|
+
};
|
|
71
|
+
type Arrowhead = "arrow" | "bar" | "dot";
|
|
72
|
+
type ExcalidrawLinearElement = _ExcalidrawElementBase & Readonly<{
|
|
73
|
+
type: "line" | "draw" | "arrow";
|
|
74
|
+
points: readonly Point$1[];
|
|
75
|
+
lastCommittedPoint: Point$1 | null;
|
|
76
|
+
startBinding: PointBinding | null;
|
|
77
|
+
endBinding: PointBinding | null;
|
|
78
|
+
startArrowhead: Arrowhead | null;
|
|
79
|
+
endArrowhead: Arrowhead | null;
|
|
80
|
+
}>;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/elements/ExcalidrawElement.d.ts
|
|
83
|
+
type Point = [number, number];
|
|
84
|
+
type ExcalidrawElementBase = {
|
|
85
|
+
id: string;
|
|
86
|
+
x: number;
|
|
87
|
+
y: number;
|
|
88
|
+
strokeColor: string;
|
|
89
|
+
backgroundColor: string;
|
|
90
|
+
fillStyle: FillStyle;
|
|
91
|
+
strokeWidth: number;
|
|
92
|
+
strokeStyle: StrokeStyle;
|
|
93
|
+
strokeSharpness: StrokeSharpness;
|
|
94
|
+
roughness: number;
|
|
95
|
+
opacity: number;
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
angle: number;
|
|
99
|
+
/** Random integer used to seed shape generation so that the roughjs shape
|
|
100
|
+
doesn't differ across renders. */
|
|
101
|
+
seed: number;
|
|
102
|
+
/** Integer that is sequentially incremented on each change. Used to reconcile
|
|
103
|
+
elements during collaboration or when saving to server. */
|
|
104
|
+
version: number;
|
|
105
|
+
/** Random integer that is regenerated on each change.
|
|
106
|
+
Used for deterministic reconciliation of updates during collaboration,
|
|
107
|
+
in case the versions (see above) are identical. */
|
|
108
|
+
versionNonce: number;
|
|
109
|
+
isDeleted: boolean;
|
|
110
|
+
/** List of groups the element belongs to.
|
|
111
|
+
Ordered from deepest to shallowest. */
|
|
112
|
+
groupIds: GroupId[]; /** Ids of (linear) elements that are bound to this element. */
|
|
113
|
+
boundElementIds: ExcalidrawLinearElement["id"][] | null;
|
|
114
|
+
};
|
|
115
|
+
type ExcalidrawRectangle = ExcalidrawElementBase & {
|
|
116
|
+
type: "rectangle";
|
|
117
|
+
};
|
|
118
|
+
type ExcalidrawLine = ExcalidrawElementBase & {
|
|
119
|
+
type: "line";
|
|
120
|
+
points: readonly Point[];
|
|
121
|
+
};
|
|
122
|
+
type ExcalidrawEllipse = ExcalidrawElementBase & {
|
|
123
|
+
type: "ellipse";
|
|
124
|
+
};
|
|
125
|
+
type ExcalidrawGenericElement = ExcalidrawRectangle | ExcalidrawEllipse | ExcalidrawLine | ExcalidrawDraw;
|
|
126
|
+
type ExcalidrawDraw = ExcalidrawElementBase & {
|
|
127
|
+
type: "draw";
|
|
128
|
+
points: readonly Point[];
|
|
129
|
+
};
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/elements/ExcalidrawScene.d.ts
|
|
132
|
+
declare class ExcalidrawScene {
|
|
133
|
+
type: string;
|
|
134
|
+
version: number;
|
|
135
|
+
source: string;
|
|
136
|
+
elements: ExcalidrawGenericElement[];
|
|
137
|
+
constructor(elements?: ExcalidrawGenericElement[]);
|
|
138
|
+
toExJSON(): {
|
|
139
|
+
type: string;
|
|
140
|
+
version: number;
|
|
141
|
+
source: string;
|
|
142
|
+
elements: ExcalidrawGenericElement[];
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
1
146
|
//#region src/parser.d.ts
|
|
2
147
|
type ConversionResult = {
|
|
3
148
|
hasErrors: boolean;
|
|
4
|
-
errors:
|
|
5
|
-
content:
|
|
149
|
+
errors: NodeList | null;
|
|
150
|
+
content: ReturnType<ExcalidrawScene["toExJSON"]> | null;
|
|
6
151
|
warnings: string[];
|
|
7
152
|
};
|
|
8
153
|
declare const convert: (svgString: string) => ConversionResult;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
|
-
import { Random } from "roughjs/bin/math";
|
|
2
|
-
import { nanoid } from "nanoid";
|
|
3
|
-
import chroma from "chroma-js";
|
|
4
|
-
import { mat4, vec3 } from "gl-matrix";
|
|
5
1
|
import { DOMParser, parseHTML } from "linkedom";
|
|
2
|
+
import { mat4, vec3 } from "gl-matrix";
|
|
6
3
|
import { pointsOnPath } from "points-on-path";
|
|
4
|
+
import chroma from "chroma-js";
|
|
5
|
+
import { nanoid } from "nanoid";
|
|
6
|
+
import { Random } from "roughjs/bin/math";
|
|
7
|
+
|
|
8
|
+
//#region src/dom.ts
|
|
9
|
+
/**
|
|
10
|
+
* DOM API provider using linkedom
|
|
11
|
+
* Works in browser, Node.js, and serverless/edge environments
|
|
12
|
+
*/
|
|
13
|
+
const dom = parseHTML("<!DOCTYPE html>");
|
|
14
|
+
const DOMParser$1 = new DOMParser();
|
|
15
|
+
const document = dom.document;
|
|
16
|
+
const NodeFilter = {
|
|
17
|
+
SHOW_ALL: 4294967295,
|
|
18
|
+
SHOW_ELEMENT: 1,
|
|
19
|
+
SHOW_ATTRIBUTE: 2,
|
|
20
|
+
SHOW_TEXT: 4,
|
|
21
|
+
SHOW_CDATA_SECTION: 8,
|
|
22
|
+
SHOW_ENTITY_REFERENCE: 16,
|
|
23
|
+
SHOW_ENTITY: 32,
|
|
24
|
+
SHOW_PROCESSING_INSTRUCTION: 64,
|
|
25
|
+
SHOW_COMMENT: 128,
|
|
26
|
+
SHOW_DOCUMENT: 256,
|
|
27
|
+
SHOW_DOCUMENT_TYPE: 512,
|
|
28
|
+
SHOW_DOCUMENT_FRAGMENT: 1024,
|
|
29
|
+
SHOW_NOTATION: 2048,
|
|
30
|
+
FILTER_ACCEPT: 1,
|
|
31
|
+
FILTER_REJECT: 2,
|
|
32
|
+
FILTER_SKIP: 3
|
|
33
|
+
};
|
|
7
34
|
|
|
35
|
+
//#endregion
|
|
8
36
|
//#region src/elements/ExcalidrawScene.ts
|
|
9
37
|
var ExcalidrawScene = class {
|
|
10
38
|
type = "excalidraw";
|
|
@@ -16,36 +44,15 @@ var ExcalidrawScene = class {
|
|
|
16
44
|
}
|
|
17
45
|
toExJSON() {
|
|
18
46
|
return {
|
|
19
|
-
|
|
47
|
+
type: this.type,
|
|
48
|
+
version: this.version,
|
|
49
|
+
source: this.source,
|
|
20
50
|
elements: this.elements.map((el) => ({ ...el }))
|
|
21
51
|
};
|
|
22
52
|
}
|
|
23
53
|
};
|
|
24
54
|
var ExcalidrawScene_default = ExcalidrawScene;
|
|
25
55
|
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/utils.ts
|
|
28
|
-
const random = new Random(Date.now());
|
|
29
|
-
const randomInteger = () => Math.floor(random.next() * 2 ** 31);
|
|
30
|
-
const randomId = () => nanoid();
|
|
31
|
-
function dimensionsFromPoints(points) {
|
|
32
|
-
const xCoords = points.map(([x]) => x);
|
|
33
|
-
const yCoords = points.map(([, y]) => y);
|
|
34
|
-
const minX = Math.min(...xCoords);
|
|
35
|
-
const minY = Math.min(...yCoords);
|
|
36
|
-
const maxX = Math.max(...xCoords);
|
|
37
|
-
const maxY = Math.max(...yCoords);
|
|
38
|
-
return [maxX - minX, maxY - minY];
|
|
39
|
-
}
|
|
40
|
-
function getWindingOrder(points) {
|
|
41
|
-
return points.reduce((acc, [x1, y1], idx, arr) => {
|
|
42
|
-
const p2 = arr[idx + 1];
|
|
43
|
-
const x2 = p2 ? p2[0] : 0;
|
|
44
|
-
const y2 = p2 ? p2[1] : 0;
|
|
45
|
-
return (x2 - x1) * (y2 + y1) + acc;
|
|
46
|
-
}, 0) > 0 ? "clockwise" : "counterclockwise";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
56
|
//#endregion
|
|
50
57
|
//#region src/attributes.ts
|
|
51
58
|
function hexWithAlpha(color, alpha) {
|
|
@@ -108,52 +115,27 @@ function pointsAttrToPoints(el) {
|
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
//#endregion
|
|
111
|
-
//#region src/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
//#region src/utils.ts
|
|
119
|
+
const random = new Random(Date.now());
|
|
120
|
+
const randomInteger = () => Math.floor(random.next() * 2 ** 31);
|
|
121
|
+
const randomId = () => nanoid();
|
|
122
|
+
function dimensionsFromPoints(points) {
|
|
123
|
+
const xCoords = points.map(([x]) => x);
|
|
124
|
+
const yCoords = points.map(([, y]) => y);
|
|
125
|
+
const minX = Math.min(...xCoords);
|
|
126
|
+
const minY = Math.min(...yCoords);
|
|
127
|
+
const maxX = Math.max(...xCoords);
|
|
128
|
+
const maxY = Math.max(...yCoords);
|
|
129
|
+
return [maxX - minX, maxY - minY];
|
|
130
|
+
}
|
|
131
|
+
function getWindingOrder(points) {
|
|
132
|
+
return points.reduce((acc, [x1, y1], idx, arr) => {
|
|
133
|
+
const p2 = arr[idx + 1];
|
|
134
|
+
const x2 = p2 ? p2[0] : 0;
|
|
135
|
+
const y2 = p2 ? p2[1] : 0;
|
|
136
|
+
return (x2 - x1) * (y2 + y1) + acc;
|
|
137
|
+
}, 0) > 0 ? "clockwise" : "counterclockwise";
|
|
120
138
|
}
|
|
121
|
-
var Group = class {
|
|
122
|
-
id = randomId();
|
|
123
|
-
element;
|
|
124
|
-
constructor(element) {
|
|
125
|
-
this.element = element;
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
var Group_default = Group;
|
|
129
|
-
|
|
130
|
-
//#endregion
|
|
131
|
-
//#region src/dom.ts
|
|
132
|
-
/**
|
|
133
|
-
* DOM API provider using linkedom
|
|
134
|
-
* Works in browser, Node.js, and serverless/edge environments
|
|
135
|
-
*/
|
|
136
|
-
const dom = parseHTML("<!DOCTYPE html>");
|
|
137
|
-
const DOMParser$1 = new DOMParser();
|
|
138
|
-
const document = dom.document;
|
|
139
|
-
const NodeFilter = {
|
|
140
|
-
SHOW_ALL: 4294967295,
|
|
141
|
-
SHOW_ELEMENT: 1,
|
|
142
|
-
SHOW_ATTRIBUTE: 2,
|
|
143
|
-
SHOW_TEXT: 4,
|
|
144
|
-
SHOW_CDATA_SECTION: 8,
|
|
145
|
-
SHOW_ENTITY_REFERENCE: 16,
|
|
146
|
-
SHOW_ENTITY: 32,
|
|
147
|
-
SHOW_PROCESSING_INSTRUCTION: 64,
|
|
148
|
-
SHOW_COMMENT: 128,
|
|
149
|
-
SHOW_DOCUMENT: 256,
|
|
150
|
-
SHOW_DOCUMENT_TYPE: 512,
|
|
151
|
-
SHOW_DOCUMENT_FRAGMENT: 1024,
|
|
152
|
-
SHOW_NOTATION: 2048,
|
|
153
|
-
FILTER_ACCEPT: 1,
|
|
154
|
-
FILTER_REJECT: 2,
|
|
155
|
-
FILTER_SKIP: 3
|
|
156
|
-
};
|
|
157
139
|
|
|
158
140
|
//#endregion
|
|
159
141
|
//#region src/elements/ExcalidrawElement.ts
|
|
@@ -208,6 +190,23 @@ function createExDraw() {
|
|
|
208
190
|
};
|
|
209
191
|
}
|
|
210
192
|
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/elements/Group.ts
|
|
195
|
+
function getGroupAttrs(groups) {
|
|
196
|
+
return groups.reduce((acc, { element }) => {
|
|
197
|
+
const elVals = presAttrsToElementValues(element);
|
|
198
|
+
return Object.assign(acc, elVals);
|
|
199
|
+
}, {});
|
|
200
|
+
}
|
|
201
|
+
var Group = class {
|
|
202
|
+
id = randomId();
|
|
203
|
+
element;
|
|
204
|
+
constructor(element) {
|
|
205
|
+
this.element = element;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
var Group_default = Group;
|
|
209
|
+
|
|
211
210
|
//#endregion
|
|
212
211
|
//#region src/transform.ts
|
|
213
212
|
const transformFunctionsArr = Object.keys({
|
|
@@ -531,7 +530,7 @@ const walkers = {
|
|
|
531
530
|
let elements = [];
|
|
532
531
|
let localGroup = randomId();
|
|
533
532
|
switch (fillRule) {
|
|
534
|
-
case "nonzero":
|
|
533
|
+
case "nonzero": {
|
|
535
534
|
let initialWindingOrder = "clockwise";
|
|
536
535
|
elements = points.map((pointArr, idx) => {
|
|
537
536
|
const tPoints = transformPoints(pointArr, mat4.clone(mat));
|
|
@@ -561,6 +560,7 @@ const walkers = {
|
|
|
561
560
|
};
|
|
562
561
|
});
|
|
563
562
|
break;
|
|
563
|
+
}
|
|
564
564
|
case "evenodd":
|
|
565
565
|
elements = points.map((pointArr, idx) => {
|
|
566
566
|
const tPoints = transformPoints(pointArr, mat4.clone(mat));
|
|
@@ -608,9 +608,9 @@ const convert = (svgString) => {
|
|
|
608
608
|
console.error(error);
|
|
609
609
|
return {
|
|
610
610
|
hasErrors: true,
|
|
611
|
-
errors:
|
|
611
|
+
errors: null,
|
|
612
612
|
content: null,
|
|
613
|
-
warnings
|
|
613
|
+
warnings: [error]
|
|
614
614
|
};
|
|
615
615
|
}
|
|
616
616
|
const svgDOM = DOMParser$1.parseFromString(svgString, "image/svg+xml");
|
package/package.json
CHANGED
|
@@ -1,56 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
2
|
+
"name": "headless-svg-to-excalidraw",
|
|
3
|
+
"version": "0.0.11",
|
|
4
|
+
"description": "Convert SVG to Excalidraw's file format, no browser required.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": "github:awhiteside1/headless-svg-to-excalidraw",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/awhiteside1/headless-svg-to-excalidraw/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/awhiteside1/headless-svg-to-excalidraw#readme",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.mts",
|
|
18
|
+
"default": "./dist/index.mjs"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"package.json"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsdown",
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"test": "bun test",
|
|
31
|
+
"lint": "biome check --write"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@biomejs/biome": "^2.3.13",
|
|
36
|
+
"@tsconfig/bun": "^1.0.10",
|
|
37
|
+
"@types/bun": "^1.3.7",
|
|
38
|
+
"@types/chroma-js": "^2.1.3",
|
|
39
|
+
"tsdown": "^0.20.1",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"typescript": "^4.5.5"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"chroma-js": "^2.1.2",
|
|
47
|
+
"gl-matrix": "^3.3.0",
|
|
48
|
+
"linkedom": "^0.18.12",
|
|
49
|
+
"nanoid": "5.0.9",
|
|
50
|
+
"path-data-parser": "^0.1.0",
|
|
51
|
+
"points-on-curve": "^0.2.0",
|
|
52
|
+
"points-on-path": "^0.2.1",
|
|
53
|
+
"roughjs": "^4.4.1"
|
|
54
|
+
}
|
|
56
55
|
}
|