godo.js/src-js/godo-schemas.mjs

135 lines
3.8 KiB
JavaScript

import {Schema} from 'prosemirror-model'
// :: Schema
// This schema roughly corresponds to the document schema used by
// [CommonMark](http://commonmark.org/), minus the list elements,
// which are defined in the [`prosemirror-schema-list`](#schema-list)
// module.
//
// To reuse elements from this schema, extend or read from its
// `spec.nodes` and `spec.marks` [properties](#model.Schema.spec).
// BASIC
const basicSchemaContent = {
nodes: {
// :: NodeSpec The top level document node.
doc: {
content: 'block+',
},
// :: NodeSpec A plain paragraph textblock. Represented in the DOM
// as a `<p>` element.
paragraph: {
content: 'inline*',
group: 'block',
parseDOM: [{tag: 'p'}],
toDOM () { return ['p', 0] },
},
// :: NodeSpec A hard line break, represented in the DOM as `<br>`.
hardBreak: {
inline: true,
group: 'inline',
selectable: false,
parseDOM: [{tag: 'br'}],
toDOM () { return ['br'] },
},
// :: NodeSpec The text node.
text: {
group: 'inline',
},
},
marks: {
// :: 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', 0] },
},
// :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
// also match `<b>` and `font-weight: bold`.
strong: {
parseDOM: [{tag: 'strong'},
// This works around a Google Docs misbehavior where
// pasted content will be inexplicably wrapped in `<b>`
// tags with a font-weight normal.
{tag: 'b', getAttrs: node => node.style.fontWeight !== 'normal' && null},
{style: 'font-weight', getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null}],
toDOM () { return ['strong', 0] },
},
},
}
// HEADERS
const headersSchemaContent = {
nodes: {
// :: NodeSpec A heading textblock, with a `level` attribute that
// should hold the number 1 to 6. Parsed and serialized as `<h1>` to
// `<h6>` elements.
heading: {
attrs: {level: {default: 1}},
content: 'inline*',
marks: 'em',
group: 'block',
defining: true,
parseDOM: [{tag: 'h1', attrs: {level: 1}},
{tag: 'h2', attrs: {level: 2}},
{tag: 'h3', attrs: {level: 3}},
{tag: 'h4', attrs: {level: 4}},
{tag: 'h5', attrs: {level: 5}},
{tag: 'h6', attrs: {level: 6}}],
toDOM (node) { return ['h' + node.attrs.level, 0] },
},
},
}
// LISTS
const listSchemaContent = {
nodes: {
// A bullet list node spec, represented in the DOM as `<ul>`.
bulletList: {
content: 'listItem+',
group: 'block',
parseDOM: [{tag: 'ul'}],
toDOM () { return ['ul', 0] },
},
// A list item (`<li>`) spec.
listItem: {
content: 'paragraph+',
parseDOM: [{tag: 'li'}],
toDOM () { return ['li', 0] },
defining: true,
},
},
}
const linkSchemaContent = { // eslint-disable-line no-unused-vars
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) { let {href, title} = node.attrs; return ['a', {href, title}, 0] },
},
},
}
const basicSchema = new Schema(basicSchemaContent)
const headersSchema = new Schema({
nodes: basicSchema.spec.nodes.append(headersSchemaContent.nodes),
marks: basicSchema.spec.marks,
})
const listSchema = new Schema({
nodes: headersSchema.spec.nodes.append(listSchemaContent.nodes),
marks: headersSchema.spec.marks,
})
const fullSchema = listSchema
export { basicSchema, headersSchema, listSchema, fullSchema }