npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sciflow/schema-prosemirror

v0.1.1

Published

The canonical manuscript ProseMirror schema for the [SciFlow](https://docs.sciflow.org) editor, plus the generators that derive other formats from it: JSON Schema, the snapshot schema, and a JATS 1.4 `<body>`.

Readme

@sciflow/schema-prosemirror

The canonical manuscript ProseMirror schema for the SciFlow editor, plus the generators that derive other formats from it: JSON Schema, the snapshot schema, and a JATS 1.4 <body>.

Install

npm install @sciflow/schema-prosemirror

prosemirror-model and the other prosemirror-* packages it builds on are ordinary dependencies of this package. If you also install @sciflow/editor-core or @sciflow/editor-start, keep every prosemirror-* version identical across your install — two copies of prosemirror-model produce schema instances that fail instanceof checks against each other.

Public API

| Export | Description | | --- | --- | | manuscript | The ProseMirror Schema instance the editor runs on. There is no separate manuscriptSchema alias. | | figure | The figure NodeSpec on its own, for hosts that inspect or extend that one node. | | generateJsonSchema(schema): JsonSchema | Derives a JSON Schema for the ProseMirror document tree from a live Schema. | | generateSnapshotSchema(schema): JsonSchema | Derives a JSON Schema for the whole snapshot wrapper (doc + files + references + selection state). | | generateJatsBody(doc, options?): string | Renders a JATS 1.4 <body> XML string from document JSON. | | JsonSchema, PMNode, PMMark, JatsBodyOptions | Types for the generators above. | | Node attribute types | BlockquoteNodeAttrs, BookmarkNodeAttrs, CitationNodeAttrs, CodeBlockNodeAttrs, DocNodeAttrs, FigureNodeAttrs, FootnoteNodeAttrs, HeadingNodeAttrs, ImageNodeAttrs, LinkNodeAttrs, MathNodeAttrs, OrderedListNodeAttrs, ParagraphNodeAttrs, PartNodeAttrs, PlaceholderNodeAttrs, PoetryNodeAttrs, Table*NodeAttrs, VerbatimNodeAttrs, and the shared ManuscriptNodeAttrMap, HasIdAttr, NodeId, PartType, Placement, NumberingStyle, TextDirection and related unions. |

Usage

Loading a stored document

Instantiating nodes is ProseMirror's own API — this package exports no nodeFromJSON or marksFromJSON helpers:

import { Node } from 'prosemirror-model';
import { manuscript } from '@sciflow/schema-prosemirror';

const doc = Node.fromJSON(manuscript, snapshot.doc);

Node.fromJSON does not validate content against the schema. A document that violates a content expression loads silently and fails later, at the first transform that re-validates it.

JATS export

generateJatsBody takes document JSON — PMNode, where type is a string and content is an array — not a live ProseMirror node. Passing a live node fails with nodes.map is not a function:

import { generateJatsBody } from '@sciflow/schema-prosemirror';

const xml = generateJatsBody({
  type: 'doc',
  content: [
    { type: 'paragraph', content: [{ type: 'text', text: 'Review sample' }] },
  ],
});
// → '<body><p>Review sample</p></body>'

Pass snapshot.doc directly, or pmDoc.toJSON() if you parsed the document first. Output is a single line unless you set options.pretty; when it is on, line breaks are inserted only between block-level elements, so mixed content is never broken across lines.

Scope of the output. This is a <body> fragment, not a complete article: a caller assembles <front>, <back> and the <article> wrapper around it. Which constructs are DTD-valid and which are known limitations is documented in the Content Import & Export reference.

Identifier rewriting, and a collision you must guard against. JATS types id as ID and rid as IDREFS, so both must be XML Names — they cannot start with a digit or contain arbitrary punctuation. Document identifiers routinely are plain numbers. The generator repairs them: characters an XML Name may not contain become -, and a result that still does not start legally is prefixed with id-. So a reference keyed "299" is written as id="id-299".

Two consequences for anyone assembling the surrounding article:

  • Your back matter must apply the same mapping, or <ref id="299"> will no longer match the rid="id-299" the body emits.
  • The mapping is pure but not injective. 299 and id-299 both map to id-299, as do ref 1, ref:1 and ref-1. A document carrying two such source identifiers produces duplicate ID values, which a validating parser rejects. Real manuscripts rarely carry both forms, but the generator does not detect or resolve the collision — ensure your source identifiers are distinct after the mapping.

JSON Schema

import { manuscript, generateSnapshotSchema } from '@sciflow/schema-prosemirror';

const snapshotSchema = generateSnapshotSchema(manuscript); // feed to Ajv, etc.

Descriptions in the generated schema are read from the description fields on each NodeSpec, MarkSpec and AttributeSpec.

Where this sits

@sciflow/schema-prosemirror and @sciflow/schema-core are siblings, not a stack: this package does not depend on @sciflow/schema-core. That package holds the helpers that must work without ProseMirror; everything here needs a live Schema.

This package is consumed by @sciflow/editor-core, @sciflow/pandoc-ast, and — as a peer dependency — @sciflow/editor-start.

Building

From the workspace root:

npx nx build @sciflow/schema-prosemirror

Running unit tests

npx nx test @sciflow/schema-prosemirror

Tests use Vitest.

License

MIT. See the repository LICENSE.