From 5fa551dcb2054644caf69cde9b284eabf061a8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Sat, 6 Aug 2016 18:16:30 -0300 Subject: [PATCH] Add/Remove link --- package.json | 2 +- src/components/Widgets/MarkdownControl.js | 39 +++++++++++++++++++ .../MarkdownControlElements/StylesMenu.js | 26 ++++++++++++- .../MarkdownControlElements/localRenderers.js | 3 +- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 837264bb..07a6fb79 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,6 @@ "react-portal": "^2.2.1", "selection-position": "^1.0.0", "slate": "^0.11.0", - "slate-markdown-serializer": "^0.1.3" + "slate-markdown-serializer": "^0.1.5" } } diff --git a/src/components/Widgets/MarkdownControl.js b/src/components/Widgets/MarkdownControl.js index d3251a92..15f27905 100644 --- a/src/components/Widgets/MarkdownControl.js +++ b/src/components/Widgets/MarkdownControl.js @@ -38,6 +38,7 @@ class MarkdownControl extends React.Component { this.handleDocumentChange = this.handleDocumentChange.bind(this); this.handleMarkStyleClick = this.handleMarkStyleClick.bind(this); this.handleBlockStyleClick = this.handleBlockStyleClick.bind(this); + this.handleInlineClick = this.handleInlineClick.bind(this); this.handleBlockTypeClick = this.handleBlockTypeClick.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.calculateMenuPositions = this.calculateMenuPositions.bind(this); @@ -150,6 +151,42 @@ class MarkdownControl extends React.Component { this.setState({ state }); } + /** + * When clicking a link, if the selection has a link in it, remove the link. + * Otherwise, add a new link with an href and text. + * + * @param {Event} e + */ + + handleInlineClick(type, isActive) { + let { state } = this.state; + + if (type === 'link') { + if (!state.isExpanded) return; + + if (isActive) { + state = state + .transform() + .unwrapInline('link') + .apply(); + } + + else { + const href = window.prompt('Enter the URL of the link:', 'http://www.'); + state = state + .transform() + .wrapInline({ + type: 'link', + data: { href } + }) + .collapseToEnd() + .apply(); + } + } + this.setState({ state }); + } + + handleBlockTypeClick(type) { let { state } = this.state; @@ -208,7 +245,9 @@ class MarkdownControl extends React.Component { position={this.menuPositions.stylesMenu} marks={this.state.state.marks} blocks={this.state.state.blocks} + inlines={this.state.state.inlines} onClickMark={this.handleMarkStyleClick} + onClickInline={this.handleInlineClick} onClickBlock={this.handleBlockStyleClick} /> ); diff --git a/src/components/Widgets/MarkdownControlElements/StylesMenu.js b/src/components/Widgets/MarkdownControlElements/StylesMenu.js index 12e27a3b..017ecfd3 100644 --- a/src/components/Widgets/MarkdownControlElements/StylesMenu.js +++ b/src/components/Widgets/MarkdownControlElements/StylesMenu.js @@ -16,8 +16,10 @@ export default class StylesMenu extends Component { this.hasBlock = this.hasBlock.bind(this); this.renderMarkButton = this.renderMarkButton.bind(this); this.renderBlockButton = this.renderBlockButton.bind(this); + this.renderLinkButton = this.renderLinkButton.bind(this); this.updateMenuPosition = this.updateMenuPosition.bind(this); this.handleMarkClick = this.handleMarkClick.bind(this); + this.handleInlineClick = this.handleInlineClick.bind(this); this.handleBlockClick = this.handleBlockClick.bind(this); this.handleOpen = this.handleOpen.bind(this); } @@ -54,6 +56,10 @@ export default class StylesMenu extends Component { const { blocks } = this.props; return blocks.some(node => node.type == type); } + hasLinks(type) { + const { inlines } = this.props; + return inlines.some(inline => inline.type == 'link'); + } handleMarkClick(e, type) { e.preventDefault(); @@ -70,6 +76,21 @@ export default class StylesMenu extends Component { ); } + handleInlineClick(e, type, isActive) { + e.preventDefault(); + this.props.onClickInline(type, isActive); + } + + renderLinkButton() { + const isActive = this.hasLinks(); + const onMouseDown = e => this.handleInlineClick(e, 'link', isActive); + return ( + + + + ); + } + handleBlockClick(e, type) { e.preventDefault(); const isActive = this.hasBlock(type); @@ -103,6 +124,7 @@ export default class StylesMenu extends Component { {this.renderMarkButton('bold', 'bold')} {this.renderMarkButton('italic', 'italic')} {this.renderMarkButton('code', 'code')} + {this.renderLinkButton()} {this.renderBlockButton('heading1', 'h1')} {this.renderBlockButton('heading2', 'h2')} {this.renderBlockButton('block-quote', 'quote-left')} @@ -122,6 +144,8 @@ StylesMenu.propTypes = { }), marks: PropTypes.object.isRequired, blocks: PropTypes.object.isRequired, + inlines: PropTypes.object.isRequired, onClickBlock: PropTypes.func.isRequired, - onClickMark: PropTypes.func.isRequired + onClickMark: PropTypes.func.isRequired, + onClickInline: PropTypes.func.isRequired }; diff --git a/src/components/Widgets/MarkdownControlElements/localRenderers.js b/src/components/Widgets/MarkdownControlElements/localRenderers.js index 1ab11ab5..32974536 100644 --- a/src/components/Widgets/MarkdownControlElements/localRenderers.js +++ b/src/components/Widgets/MarkdownControlElements/localRenderers.js @@ -1,7 +1,6 @@ import React from 'react'; import Block from './Block'; import BlockStatic from './BlockStatic'; -import { Icon } from '../../UI'; /* eslint react/prop-types: 0, react/no-multi-comp: 0 */ @@ -24,7 +23,7 @@ export const NODES = { 'link': (props) => { const { data } = props.node; const href = data.get('href'); - return {props.children}; + return {props.children}; }, 'image': (props) => { const { node } = props;