It looks like the toSVG method mutates the models passed into it, which is expected. This came up while trying to cache submodels to improve performance.
Here's a minimal repro case:
const makerjs = require("makerjs");
const opentype = require("opentype.js");
const font = opentype.loadSync("./src/fonts/ReliefSingleLineCAD-Regular.ttf");
const text = new makerjs.models.Text(font, "Hi", 12);
const model = {
models: {
text1: text,
text2: text,
},
};
const svg = makerjs.exporter.toSVG(model);
console.log(svg);
The result is this exception:
TypeError: Cannot read properties of undefined (reading 'startT')
at getActualBezierRange (/Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:8591:43)
at /Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:8790:37
at Array.forEach (<anonymous>)
at /Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:8785:27
at _loop_3 (/Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:6054:21)
at Object.findChains (/Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:6058:17)
at BezierCurve.getBezierSeeds (/Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:8773:31)
at /Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:6170:73
at Array.forEach (<anonymous>)
at swapBezierPathsWithSeeds (/Users/xavi/code/maker-test/server/node_modules/makerjs/dist/index.js:6161:21)
I'm using node v22.11.0 with makerjs@0.18.1 and opentype.js@1.3.4
The issue seems to be somewhere in here:
|
beziers.forEach(wm => { |
|
var b = wm.childModel as models.BezierCurve; |
|
|
|
if (swap) { |
|
|
|
//set layer prior to looking for seeds by layer |
|
if (wm.layer != undefined && wm.layer !== '') { |
|
b[tempLayerKey] = (b as IModel).layer; |
|
(b as IModel).layer = wm.layer; |
|
} |
|
|
|
//use seeds as path, hide the arc paths from findChains() |
|
var bezierPartsByLayer = models.BezierCurve.getBezierSeeds(b, { byLayers: true, pointMatchingDistance }); |
|
|
|
for (var layer in bezierPartsByLayer) { |
|
var bezierSeeds = bezierPartsByLayer[layer]; |
|
if (bezierSeeds.length > 0) { |
|
b[tempKey] = b.paths; |
|
|
|
var newPaths: IPathMap = {}; |
|
|
|
bezierSeeds.forEach(function (seed, i) { |
|
seed.layer = layer; |
|
newPaths['seed_' + i] = seed; |
|
}); |
|
|
|
b.paths = newPaths; |
|
} |
|
} |
|
|
|
} else { |
|
//revert the above |
|
|
|
if (tempKey in b) { |
|
b.paths = b[tempKey] as IPathMap; |
|
delete b[tempKey]; |
|
} |
|
|
|
if (tempLayerKey in b) { |
|
if (b[tempLayerKey] == undefined) { |
|
delete (b as IModel).layer; |
|
} else { |
|
(b as IModel).layer = b[tempLayerKey] as string; |
|
} |
|
delete b[tempLayerKey]; |
|
} |
|
|
|
} |
|
}); |
It's not obvious to me how to fix it, so I figured I'd open an issue
The exception doesn't occur when useSvgPathOnly option is enabled, which double confirms that the issue is related to the findChains function
Workaround
// Clone submodels
const model = {
models: {
text1: makerjs.cloneObject(text),
text2: makerjs.cloneObject(text),
},
};
This does works, but it add a bit of overhead. Also, it's surprising that an exporter mutates the underlying model
It looks like the
toSVGmethod mutates the models passed into it, which is expected. This came up while trying to cache submodels to improve performance.Here's a minimal repro case:
The result is this exception:
I'm using node v22.11.0 with makerjs@0.18.1 and opentype.js@1.3.4
The issue seems to be somewhere in here:
maker.js/packages/maker.js/src/core/chain.ts
Lines 405 to 453 in 1ed796b
It's not obvious to me how to fix it, so I figured I'd open an issue
The exception doesn't occur when
useSvgPathOnlyoption is enabled, which double confirms that the issue is related to thefindChainsfunctionWorkaround
This does works, but it add a bit of overhead. Also, it's surprising that an exporter mutates the underlying model