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 systems.

113 lines (94 loc) 3.09 kB
import { Fragmenter } from '../model' import Component from './Component' import AnnotationComponent from './AnnotationComponent' import InlineNodeComponent from './InlineNodeComponent' /** Renders an anotated text. Used internally by {@link ui/TextPropertyComponent}. @class @component @extends ui/Component @prop {String[]} path The property to be rendered. */ class AnnotatedTextComponent extends Component { render($$) { let 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 } _onDocumentChange(update) { if (update.change && update.change.updated[this.getPath()]) { this.rerender() } } _renderContent($$) { let text = this.getText(); let annotations = this.getAnnotations() let el = $$(this._getTagName() || 'span') if (annotations && annotations.length > 0) { let fragmenter = new Fragmenter({ onText: this._renderTextNode.bind(this), onEnter: this._renderFragment.bind(this, $$), onExit: 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) { let doc = this.getDocument() let componentRegistry = this.getComponentRegistry() let 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 { let ComponentClass = componentRegistry.get(node.type) || AnnotationComponent if (node.constructor.isInline && // also no extra wrapping if the node is already an inline node !ComponentClass.prototype._isInlineNodeComponent && // opt-out for custom implementations !ComponentClass.isCustom) { ComponentClass = InlineNodeComponent } let el = $$(ComponentClass, { doc: doc, node: node }) return el } } _finishFragment(fragment, context, parentContext) { parentContext.append(context) } } export default AnnotatedTextComponent