From d0c8ce0c08fd3f1d0c2b7e608eb7f434252dfa5b Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Wed, 20 Jul 2016 15:11:13 -0700 Subject: [PATCH] add the ability to render based on multiple marks (#138) closes #33 --- docs/reference/plugins/plugins.md | 6 ++--- lib/components/editor.js | 5 ++-- lib/components/leaf.js | 2 +- .../fixtures/custom-mark-multiple/index.js | 27 +++++++++++++++++++ .../fixtures/custom-mark-multiple/input.yaml | 17 ++++++++++++ .../fixtures/custom-mark-multiple/output.html | 10 +++++++ 6 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 test/rendering/fixtures/custom-mark-multiple/index.js create mode 100644 test/rendering/fixtures/custom-mark-multiple/input.yaml create mode 100644 test/rendering/fixtures/custom-mark-multiple/output.html diff --git a/docs/reference/plugins/plugins.md b/docs/reference/plugins/plugins.md index 704ee821e..d77ed9864 100644 --- a/docs/reference/plugins/plugins.md +++ b/docs/reference/plugins/plugins.md @@ -102,14 +102,14 @@ If no other plugin handles this event, it will be handled by the [Core plugin](. To customize the renderer output of the editor, plugins can define a set of "renderer" properties. ### `renderDecorations` -`Function renderDecorations(text: Text) => Characters || Void` +`Function renderDecorations(text: Text, state: State, editor: Editor) => Characters || Void` The `renderDecorations` handler allows you to add dynamic, content-aware [`Marks`](../models/mark.md) to ranges of text, without having them show up in the serialized state of the editor. This is useful for things like code highlighting, where the marks will change as the user types. `renderDecorations` is called for every `text` node in the document, and should return a set of updated [`Characters`](../models/character.md) for the text node in question. Every plugin's decoration logic is called, and the resulting characters are unioned, such that multiple plugins can apply decorations to the same pieces of text. ### `renderMark` -`Function renderMark(mark: Mark) => Object || Void` +`Function renderMark(mark: Mark, marks: Set, state: State, editor: Editor) => Object || Void` The `renderMark` handler allows you to define the styles that each mark should be rendered with. It takes a [`Mark`](../models/mark.md) object, and should return a dictionary of styles that will be applied via React's `style=` property. For example: @@ -121,7 +121,7 @@ The `renderMark` handler allows you to define the styles that each mark should b ``` ### `renderNode` -`Function renderNode(node: Block || Inline) => Component || Void` +`Function renderNode(node: Block || Inline, state: State, editor: Editor) => Component || Void` The `renderNode` handler allows you to define the component that will be used to render a node—both blocks and inlines. It takes a [`Node`](../models/node.md) object, and should return a React component. diff --git a/lib/components/editor.js b/lib/components/editor.js index 1fea70f0e..1ad8ae934 100644 --- a/lib/components/editor.js +++ b/lib/components/editor.js @@ -233,13 +233,14 @@ class Editor extends React.Component { * Render a `mark`, cascading through the plugins. * * @param {Mark} mark + * @param {Set} marks * @return {Object} style */ - renderMark = (mark) => { + renderMark = (mark, marks) => { for (const plugin of this.state.plugins) { if (!plugin.renderMark) continue - const style = plugin.renderMark(mark, this.state.state, this) + const style = plugin.renderMark(mark, marks, this.state.state, this) if (style) return style } } diff --git a/lib/components/leaf.js b/lib/components/leaf.js index 6996c0599..04bc417a5 100644 --- a/lib/components/leaf.js +++ b/lib/components/leaf.js @@ -129,7 +129,7 @@ class Leaf extends React.Component { const style = marks.reduce((memo, mark) => { return { ...memo, - ...renderMark(mark), + ...renderMark(mark, marks), } }, {}) diff --git a/test/rendering/fixtures/custom-mark-multiple/index.js b/test/rendering/fixtures/custom-mark-multiple/index.js new file mode 100644 index 000000000..03a5663bb --- /dev/null +++ b/test/rendering/fixtures/custom-mark-multiple/index.js @@ -0,0 +1,27 @@ + +import React from 'react' + +const BOLD = { + fontWeight: 'bold' +} + +const ITALIC = { + fontStyle: 'italic' +} + +const BOLD_ITALIC = { + fontFamily: 'bold-italic' +} + +export function renderMark(mark, marks) { + if ( + marks.size > 1 && + marks.some(m => m.type == 'bold') && + marks.some(m => m.type == 'italic') + ) { + return BOLD_ITALIC + } + + if (mark.type == 'bold') return BOLD + if (mark.type == 'italic') return ITALIC +} diff --git a/test/rendering/fixtures/custom-mark-multiple/input.yaml b/test/rendering/fixtures/custom-mark-multiple/input.yaml new file mode 100644 index 000000000..3cecf2980 --- /dev/null +++ b/test/rendering/fixtures/custom-mark-multiple/input.yaml @@ -0,0 +1,17 @@ + +nodes: + - kind: block + type: default + nodes: + - kind: text + ranges: + - text: one + marks: + - type: bold + - text: two + marks: + - type: italic + - text: three + marks: + - type: bold + - type: italic diff --git a/test/rendering/fixtures/custom-mark-multiple/output.html b/test/rendering/fixtures/custom-mark-multiple/output.html new file mode 100644 index 000000000..6b8f6dddf --- /dev/null +++ b/test/rendering/fixtures/custom-mark-multiple/output.html @@ -0,0 +1,10 @@ + +
+
+ + one + two + three + +
+