Today I used patch-package to patch smiles-drawer@1.2.0 for the project I'm working on.
The issue this solves is two fold:
that no serverside DOM has viewBox.baseVal
the code should not enforce 1:1 aspect ratio, but set the viewBox to the intrinsic shape of the drawing.
Fixing the first problem allows serverside rendering. Fixing the second problem allows downstream code/css to determine the aspect ratio based on the intrinsic shape of the drawing.
This is all the setup needed to serverside render an SVG:
import {parseHTML} from 'linkedom'; var {document, window} = parseHTML(``); globalThis.document = document
Now, this simple code can produce an SVG (without polluting the global space):
`
function draw(smiles, options = {}) {
var smilesDrawer = new SmilesDrawer.Drawer(options);
var svgDrawer = new SmilesDrawer.SvgDrawer(options);
console.log((await draw("CCCO")).outerHTML)
`
This doesn't pollute the global namespace because smilesDrawer only uses document for "createElement" and to locate the target element. By providing the target element directly, instead of by ID string, there is no global polution.
Here is the diff that solved my problem:
diff --git a/node_modules/smiles-drawer/src/SvgWrapper.js b/node_modules/smiles-drawer/src/SvgWrapper.js
index adbc611..f9659fd 100644
--- a/node_modules/smiles-drawer/src/SvgWrapper.js
+++ b/node_modules/smiles-drawer/src/SvgWrapper.js
@@ -208,8 +208,8 @@ class SvgWrapper {
this.drawingWidth = maxX - minX;
this.drawingHeight = maxY - minY;
- let w = this.svg.clientWidth > 0 ? this.svg.clientWidth : this.svg.viewBox.baseVal.width;
- let h = this.svg.clientHeight > 0 ? this.svg.clientHeight : this.svg.viewBox.baseVal.height;
+ let w = this.drawingWidth
+ let h = this.drawingHeight
let scaleX = w / this.drawingWidth;
let scaleY = h / this.drawingHeight;
@@ -217,7 +217,7 @@ class SvgWrapper {
let scale = (scaleX < scaleY) ? scaleX : scaleY;
let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);
- this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);
+ this.svg.setAttributeNS(null, 'viewBox', `0 0 ${Math.round(w)} ${Math.round(h)}`);
this.offsetX = -minX;
this.offsetY = -minY;
Today I used patch-package to patch
smiles-drawer@1.2.0
for the project I'm working on.The issue this solves is two fold:
Fixing the first problem allows serverside rendering. Fixing the second problem allows downstream code/css to determine the aspect ratio based on the intrinsic shape of the drawing.
This is all the setup needed to serverside render an SVG:
import {parseHTML} from 'linkedom'; var {document, window} = parseHTML(``); globalThis.document = document
Now, this simple code can produce an SVG (without polluting the global space):
` function draw(smiles, options = {}) { var smilesDrawer = new SmilesDrawer.Drawer(options); var svgDrawer = new SmilesDrawer.SvgDrawer(options);
}
console.log((await draw("CCCO")).outerHTML) ` This doesn't pollute the global namespace because smilesDrawer only uses document for "createElement" and to locate the target element. By providing the target element directly, instead of by ID string, there is no global polution.
Here is the diff that solved my problem:
This issue body was partially generated by patch-package.