Nodes.append is not a function

I have a custom schema with specific nodes and marks, and I’d like to add lists to it. My nodes look like:

const nodes = {
  doc: {
    content: 'block+'
  },
  paragraph: {
    content: 'inline*',
    group: 'block',
    parseDOM: [{tag: 'p'}],
    toDOM() {
      return ['p', 0];
    }
  },
  text: {
    group: 'inline'
  },
  hard_break: {
    inline: true,
    group: 'inline',
    selectable: false,
    parseDOM: [{tag: 'br'}],
    toDOM() {
      return ['br']
    }
  },
[…]

and my marks are also pretty basic, with several of my own additions:

const marks = {
  link: {
    attrs: {
      href: {},
      title: {default: null}
    },
    inclusive: false,
    parseDOM: [
      {
        tag: 'a[href]',
        getAttrs(dom) {
          return {
            href: dom.getAttribute('href'),
            title: dom.getAttribute('title')
          };
        }
      }
    ],
    toDOM(node) {
      return ['a', node.attrs];
    }
  },
  // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
  // Has parse rules that also match `<i>` and `font-style: italic`.
  em: {
    parseDOM: [{tag: 'i'}, {tag: 'em'}, {style: 'font-style=italic'}],
    toDOM() {
      return ['em'];
    }
  },
[…]

As there already is prosemirror-schema-list I tried to add that package and issue

import { addListNodes } from 'prosemirror-schema-list';
[…]
const schema = new Schema({nodes: addListNodes(nodes, "paragraph block*", "block"), marks: marks});

However, now the browser complains

Uncaught TypeError: nodes.append is not a function at addListNodes

Indeed there is a nodes.append in addListNodes, but I can’t find where it is implemented.

addListNodes expects an OrderedMap instance, but you’re passing it a raw object.

Thanks, I looked better, now, and I had to pass it schema.spec.nodes from an already defined schema. Now everything works as expected.

In the future, I’ll take a deep dive into ProseMirror’s internals, as I think they’re a great example of software engineering.

Do you pass the schema.spec.nodes after you run new Schema? How does such an add function work within the setup code. This patterns seems common, but undocumented in each example I find.

Sorry for the late reply, didn’t notice your question earlier. In my code, I now use:

const schemaOrg = new Schema({nodes, marks});
const schema = new Schema({nodes: addListNodes(schemaOrg.spec.nodes, 'paragraph block*', 'block'), marks: marks});

This creates an intermediate Schema, which will be hopefully thrown away sooner than later by the garbage collector.