Types and function bindings for using Stencila from Node.js
This package provides bindings to core Stencila Rust functions. Most function take, or return, types defined in Stencila Schema and transpiled to @stencila/types.
The primary intended audience is developers who want to develop their own tools on top of Stencila's core functionality. For example, with this package you could construct Stencila documents programmatically using Node.js and write them to multiple formats (e.g. Markdown, JATS XML, PDF).
[!IMPORTANT] At present, there are only bindings to functions for format conversion, but future versions will expand this scope to include document management (e.g branching and merging) and execution.
npm install @stencila/node
The convert
module has five functions for encoding and decoding Stencila documents and for converting documents between formats. All functions are async
.
Use fromString
to decode a string in a certain format to a Stencila Schema type. Usually you will need to supply the format
argument (it defaults to JSON). e.g.
import { convert } from "@stencila/node";
import { Article, Paragraph, Text } from "@stencila/types";
const doc = await convert.fromString(
'{type: "Article", content: [{type: "Paragraph", content: ["Hello world"]}]}',
{
format: "json5",
},
);
doc instanceof Article; // true
doc instanceof CreativeWork; // true
doc instanceof Thing; // true
doc.content[0] instanceof Paragraph; // true
doc.content[0].content[0] instanceof Text; // true
Use fromPath
to decode a file system path (usually a file) to a Stencila Schema type. The format can be supplied, but if it is not, is inferred from the path. e.g.
import { convert } from "@stencila/node";
const doc = await convert.fromPath(
"../examples/nodes/paragraph/paragraph.jats.xml",
);
Both fromString
and fromPath
accept a DecodeOptions
object as the second argument with the options:
-
format: string
: The format to decode from -
losses: string
: What to do if there are losses when decoding from the input. Possible values includeignore
,trace
,debug
,info
,warn
,error
, orabort
, or a file path to write the losses to (json
oryaml
file extensions are supported).
Use toString
to encode a Stencila Schema type to a string. Usually you will want to supply the format
argument (it defaults to JSON).
import { convert } from "@stencila/node";
import { Article, Paragraph, Text } from "@stencila/types";
const doc = new Article([
new Paragraph(["Hello ", new Strong(["again"]), "!"]),
]);
const jats = await convert.toString(doc, { format: "jats" });
To encode a Stencila Schema type to a filesystem path, use toPath
. e.g.
import { convert } from "@stencila/node";
const doc = new Article([new Paragraph([new Text("Hello file system!")])]);
await convert.toPath(doc, "doc.html", { compact: false });
Both toString
and toPath
accept a EncodeOptions
object:
-
format: string
: The format to encode to -
standalone: bool
: Whether to encode as a valid, standalone document (e.g. for HTML ensuring there is a root<html>
element with a<head>
and<body>
). Unless specified otherwise, this is the default when encoding to a file. -
compact: bool
: Whether to encode in compact form. Some formats (e.g HTML and JSON) can be encoded in either compact or "pretty-printed" (e.g. indented) forms. -
losses: string
: What to do if there are losses when encoding to the output. Possible values includeignore
,trace
,debug
,info
,warn
,error
, orabort
, or a file path to write the losses to (json
oryaml
file extensions are supported).
Use fromTo
when you want to convert a file to another format (i.e. as a more performant shortcut to combining fromPath
and toPath
).
import { convert } from "@stencila/node";
await convert.fromTo("doc.jats.xml", "doc.html");
The fromTo
function accepts both DecodeOptions
and EncodeOptions
as third and fourth arguments respectively.
[!NOTE] Some of the usage examples above illustrate manually constructing in-memory JavaScript representations of small documents. This is for illustration only and would be unwieldy for large documents. Instead we imagine developers using the
convert.fromString
orconvert.fromPath
functions to load documents into memory from other formats, or writing functions to construct documents composed of the Stencila classes.
This packages uses NAPI-RS to generate a Node.js native addon from Stencila Rust functions. The addon (a binary file with a .node
extension) is generated using npm run build:addon
for releases and npm run build:debug
for testing. The file bindings.d.cts
is also generated by NAPI-RS.
NAPI-RS recommends distributing native addons using different NPM packages for each platform supported. However, given how we are distributing other binaries (e.g. for the CLI), and to avoid the complexity of multiple NPM packages, we have opted for the "download in a postinstall phase" approach. See install.js
.
The convert
module is implemented in Rust (src/convert.rs
) with a thin TypeScript wrapper (src/convert.mts
) to provide documentation and conversion to the types in the @stencila/types
.
When contributing code please run the following linting, formatting and testing scripts. Linting checks are run on CI, so for faster iteration, fewer failed runs and less noise, it's generally a good idea to run them locally before pushing code.
This module uses types from @stencila/types
, a package that is defined in the sibling ts
directory, and which is also part of the NPM workspace defined in the root package.json.
You may find that ESLint will complain that @stencila/types
does not exist because ../ts/dist does not yet exist. To fix this build that package:
cd ../ts && npm run build
or
make -C ../ts build
We use ESLint and Prettier for code linting and formatting respectively. To apply linting and formatting fixes:
npm run fix
To just check linting and formatting:
npm run lint
We use Jest for tests. To run them:
npm test
Some of the tests use snapshots. To update them:
npm test -- -u
The packaging and publishing configuration is checked using arethetypeswrong``)(https://github.com/arethetypeswrong/arethetypeswrong.github.io) and [
publint`:
npm pubcheck
As with most modules in this repo, there is a Makefile
which you may prefer to use for common development tasks. For example to easily run multiple NPM scripts at once:
make fix test
A recommended combination of recipes to run before committing code is:
make audit pubcheck lint test