paulrosen / abcjs

javascript for rendering abc music notation
Other
1.94k stars 285 forks source link

get svg in nodejs environment #987

Closed jjon closed 9 months ago

jjon commented 10 months ago

Some time ago abcjs was packaged up as a nodejs module. I've installed it via npm: signature: 'abcjs-basic v6.2.3',... and imported it into a nodejs script thus: var abcjs = require('abcjs'). Well and good, but abcjs.renderAbc() expects to be operating in the context of a DOM and expects the first parameter to be a DOM node to write the svg to. Is there any way to simply get svg as a string from a given parsed string of abc notation?

Apologies, as this isn't really a bug, but so far I'm pretty unclear about how abcjs might be used in a nodejs context.

jjon commented 10 months ago

Apologies again. I only just discovered that this was discussed in #742. Yes @paulrosen this:

const output = abcjs.renderAbc("X:1\n...");
console.log(output) // "<svg xmlns:xlink="http://www.w3.org/1999/xlink">...</svg>"

is exactly the sort of thing I was hoping to find. What I'm trying to do is to construct a BBEdit "Text Filter" that will allow me to preview some arbitrary abc notation. I thought I could simply call a nodejs script as is done in this example. If I can generate some raw svg, BBEdit can preview it nicely for me. Importing the abcjs module is one problem, but even if I get past that, tricking renderAbc into writing its svg into some imaginary DOM element using jsdom has proven tricky, and, so far, beyond my javascript skills.

The resulting svg doesn't need to be pretty, and can largely disregard text. I'm just looking to get the dots.

paulrosen commented 9 months ago

The problem is anywhere there is text - that requires a dom to figure out the space of the text so that I can move everything else.

There is the option of calling abcjs.renderAbc("*", abcString) to not draw, but it will still try to access the DOM for any text.

Another option might be parseOnly. That is deprecated, but if it is useful to you it can be un-deprecated: https://paulrosen.github.io/abcjs/deprecated/deprecated-api.html#parseonly

jjon commented 9 months ago

Thanks for your response @paulrosen. It would appear that my instinct was correct to deploy jsdom to provide a virtual DOM for renderAbc to write to, but I didn't make much progress before I discovered that somebody had already figured this out. Daniel Narey has a scoped ES module for nodejs that does this (and perhaps more)? @folkdb/abc-render-svg. I had to learn how to use a "scoped module" (that @ thingy), and how to arrange it for my special use case as a BBEdit text filter, but the final result works a treat, and is but a few lines:

#!/usr/bin/env node
import abcRenderSvg from '@folkdb/abc-render-svg'

process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on("data", data => {
    (async () => {
        const svg = await abcRenderSvg(data);
        process.stdout.write(svg);
    })();
})