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 (102 loc) 3.39 kB
import Fragmenter from '../model/Fragmenter' import Component from '../dom/Component' /** Renders an anotated text. Used internally by `TextPropertyComponent`. @prop {String[]} path The property to be rendered. */ export default class AnnotatedTextComponent extends Component { render ($$) { const el = this._renderContent($$) .addClass('sc-annotated-text') .css({ whiteSpace: 'pre-wrap' }) return el } getPath () { return this.props.path } getText () { return this.getDocument().get(this.props.path) || '' } isEmpty () { return !(this.getText()) } getAnnotations () { return this.getDocument().getIndex('annotations').get(this.props.path) } getDocument () { return this.props.doc || this.context.doc } _getTagName () { return this.props.tagName } _renderContent ($$) { const text = this.getText() const annotations = this.getAnnotations() const el = $$(this._getTagName() || 'span') if (annotations && annotations.length > 0) { const fragmenter = new Fragmenter() fragmenter.onText = this._renderTextNode.bind(this) fragmenter.onOpen = this._renderFragment.bind(this, $$) fragmenter.onClose = this._finishFragment.bind(this) fragmenter.start(el, text, annotations) } else { el.append(text) } return el } _renderTextNode (context, text) { if (text && text.length > 0) { context.append(text) } } _renderFragment ($$, fragment) { const node = fragment.node // TODO: fix support for container annotations // if (node.type === 'container-annotation-fragment') { // return $$(AnnotationComponent, { doc: doc, node: node }) // .addClass("se-annotation-fragment") // .addClass(node.anno.getTypeNames().join(' ').replace(/_/g, "-")); // } else if (node.type === 'container-annotation-anchor') { // return $$(AnnotationComponent, { doc: doc, node: node }) // .addClass("se-anchor") // .addClass(node.anno.getTypeNames().join(' ').replace(/_/g, "-")) // .addClass(node.isStart?"start-anchor":"end-anchor") // } else { // ... // } const ComponentClass = this._getFragmentComponentClass(node) const props = this._getFragmentProps(node) const el = $$(ComponentClass, props) return el } _getFragmentComponentClass (node, noDefault) { let ComponentClass = this.getComponent(node.type, 'not-strict') if (node.isInlineNode() && // also no extra wrapping if the node is already an inline node !ComponentClass.prototype._isInlineNodeComponent && // opt-out for custom implementations !ComponentClass.isCustom) { ComponentClass = this.getComponent('inline-node') } if (!ComponentClass && !noDefault) { if (node._isAnnotation) { ComponentClass = this._getUnsupportedAnnotationComponentClass() } else { ComponentClass = this._getUnsupportedInlineNodeComponentClass() } } return ComponentClass } _getUnsupportedAnnotationComponentClass () { return this.getComponent('annotation') } _getUnsupportedInlineNodeComponentClass () { return this.getComponent('annotation') } _getFragmentProps (node) { return { node } } _finishFragment (fragment, context, parentContext) { parentContext.append(context) } }