import { Schema } from 'prosemirror-model' const brDOM = ['br'] const calcYchangeDomAttrs = (attrs, domAttrs = {}) => { domAttrs = Object.assign({}, domAttrs) if (attrs.ychange !== null) { domAttrs.ychange_user = attrs.ychange.user domAttrs.ychange_state = attrs.ychange.state } return domAttrs } // :: Object // [Specs](#model.NodeSpec) for the nodes defined in this schema. export const nodes = { // :: NodeSpec The top level document node. doc: { content: 'block+' }, // :: NodeSpec A plain paragraph textblock. Represented in the DOM // as a `

` element. paragraph: { attrs: { ychange: { default: null } }, content: 'inline*', group: 'block', parseDOM: [{ tag: 'p' }], toDOM (node) { return ['p', calcYchangeDomAttrs(node.attrs), 0] } }, // :: NodeSpec A blockquote (`

`) wrapping one or more blocks. blockquote: { attrs: { ychange: { default: null } }, content: 'block+', group: 'block', defining: true, parseDOM: [{ tag: 'blockquote' }], toDOM (node) { return ['blockquote', calcYchangeDomAttrs(node.attrs), 0] } }, // :: NodeSpec A horizontal rule (`
`). horizontal_rule: { attrs: { ychange: { default: null } }, group: 'block', parseDOM: [{ tag: 'hr' }], toDOM (node) { return ['hr', calcYchangeDomAttrs(node.attrs)] } }, // :: NodeSpec A heading textblock, with a `level` attribute that // should hold the number 1 to 6. Parsed and serialized as `

` to // `

` elements. heading: { attrs: { level: { default: 1 }, ychange: { default: null } }, content: 'inline*', 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, calcYchangeDomAttrs(node.attrs), 0] } }, // :: NodeSpec A code listing. Disallows marks or non-text inline // nodes by default. Represented as a `
` element with a
  // `` element inside of it.
  code_block: {
    attrs: { ychange: { default: null } },
    content: 'text*',
    marks: '',
    group: 'block',
    code: true,
    defining: true,
    parseDOM: [{ tag: 'pre', preserveWhitespace: 'full' }],
    toDOM (node) { return ['pre', calcYchangeDomAttrs(node.attrs), ['code', 0]] }
  },

  // :: NodeSpec The text node.
  text: {
    group: 'inline'
  },

  // :: NodeSpec An inline image (``) node. Supports `src`,
  // `alt`, and `href` attributes. The latter two default to the empty
  // string.
  image: {
    inline: true,
    attrs: {
      ychange: { default: null },
      src: {},
      alt: { default: null },
      title: { default: null }
    },
    group: 'inline',
    draggable: true,
    parseDOM: [{ tag: 'img[src]',
      getAttrs (dom) {
        return {
          src: dom.getAttribute('src'),
          title: dom.getAttribute('title'),
          alt: dom.getAttribute('alt')
        }
      } }],
    toDOM (node) {
      const domAttrs = {
        src: node.attrs.src,
        title: node.attrs.title,
        alt: node.attrs.alt
      }
      return ['img', calcYchangeDomAttrs(node.attrs, domAttrs)]
    }
  },

  // :: NodeSpec A hard line break, represented in the DOM as `
`. hard_break: { inline: true, group: 'inline', selectable: false, parseDOM: [{ tag: 'br' }], toDOM () { return brDOM } } } const emDOM = ['em', 0]; const strongDOM = ['strong', 0]; const codeDOM = ['code', 0] // :: Object [Specs](#model.MarkSpec) for the marks in the schema. export const marks = { // :: MarkSpec A link. Has `href` and `title` attributes. `title` // defaults to the empty string. Rendered and parsed as an `` // element. 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, 0] } }, // :: MarkSpec An emphasis mark. Rendered as an `` element. // Has parse rules that also match `` and `font-style: italic`. em: { parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }], toDOM () { return emDOM } }, // :: MarkSpec A strong mark. Rendered as ``, parse rules // also match `` and `font-weight: bold`. strong: { parseDOM: [{ tag: 'strong' }, // This works around a Google Docs misbehavior where // pasted content will be inexplicably wrapped in `` // 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 strongDOM } }, // :: MarkSpec Code font mark. Represented as a `` element. code: { parseDOM: [{ tag: 'code' }], toDOM () { return codeDOM } }, ychange: { attrs: { user: { default: null }, state: { default: null } }, inclusive: false, parseDOM: [{ tag: 'ychange' }], toDOM (node) { return ['ychange', { ychange_user: node.attrs.user, ychange_state: node.attrs.state }, 0] } } } // :: Schema // This schema rougly 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). export const schema = new Schema({ nodes, marks })