UNPKG

substance

Version:

Substance is a JavaScript library for web-based content editing. It provides building blocks for realizing custom text editors and web-based publishing system. It is developed to power our online editing platform [Substance](http://substance.io).

121 lines (104 loc) 3.83 kB
import { DefaultDOMElement as DOM, prettyPrintXML } from '../dom' import { camelCase } from '../util' import DocumentSchema from './DocumentSchema' import NextDocument from './NextDocument' import _createValidator from './_createValidator' import _createDefinition from './_createDefinition' import _createXmlConverterFactory from './_createXmlConverterFactory' export default class NextDocumentSchema { constructor (version, rootType, issuer, nodes, actions) { this.name = rootType[0].toUpperCase() + camelCase(rootType).slice(1) this.rootType = rootType this.version = version this.issuer = issuer this.nodes = nodes this.publicId = this._getPublicId(version) this.dtd = this._getDtd(version) // keep the schema definition here so that we can use it later on for XML validation and im-/export this._actions = actions // generating validators, importers and exporters lazily this._definitions = new Map() this._validators = new Map() const _definition = this._getDefinition(this.version) this._xmlConverterFactory = _createXmlConverterFactory(rootType, _definition) // legacy this._documentSchema = new DocumentSchema({ // TODO: we should allow to override NextDocument // e.g. to provide a getTitle() implementation, etc. DocumentClass: NextDocument, nodes: Array.from(nodes.values()), definition: _definition }) } createDocumentInstance () { return new NextDocument(this._documentSchema, this) } importDocumentFromXml (doc, xmlStr, context) { const xmlDom = DOM.parseXML(xmlStr) const xmlSchemaId = xmlDom.getDoctype().publicId // identify version let version for (let v = this.version; v > 0; v--) { if (xmlSchemaId === this._getPublicId(v)) { version = v break } } if (!version) throw new Error(`Unknown xml schema ${xmlSchemaId}`) const validator = this._getValidator(version) const result = validator.validate(xmlDom) if (!result.ok) { console.error(result.errors) throw new Error('Invalid xml.') } if (version !== this.version) { console.error('TODO: implement migrations') } const importer = this._xmlConverterFactory.createImporter(doc, context) importer.importIntoDocument(xmlDom) } exportDocumentToXml (doc, context = {}, options = {}) { const exporter = this._xmlConverterFactory.createExporter(context) const dom = exporter.convertNode(doc.root) let xmlStr if (options.prettyPrint) { xmlStr = prettyPrintXML(dom) } else { xmlStr = dom.serialize() } return [ '<?xml version="1.0" encoding="UTF-8"?>', `<!DOCTYPE ${this.rootType} PUBLIC "${this.publicId}" "${this.dtd}">`, xmlStr ].join('\n') } getNodeSchema (type) { return this._documentSchema.getNodeSchema(type) } getNodeClass (type) { return this._documentSchema.getNodeClass(type) } getDefaultTextType () { console.error('DEPRECATED: avoid using schema.getDefaultTextType(). Instead a "container" type should provide this in its schema.') return null } _getPublicId (version) { // TODO: until we introduce minor versions we just use '0' for minor return `-//${this.issuer.toUpperCase()}//DTD ${this.name} v${version}.0//EN` } _getDtd (version) { return `${this.name}-${version}.dtd` } _getValidator (version) { if (!this._validators.has(version)) { this._validators.set(version, _createValidator(this.rootType, this._getDefinition(version))) } return this._validators.get(version) } _getDefinition (version) { if (!this._definitions.has(version)) { this._definitions.set(version, _createDefinition(version, this._actions)) } return this._definitions.get(version) } }