From ba73b48decb4ad6978158ed42db041c04827ca21 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Wed, 13 May 2020 14:40:42 -0600 Subject: [PATCH 1/3] chart & tooltip plugins --- package.json | 2 +- .../views/markdown_editor/markdown_editor.js | 20 ++- .../markdown_editor/plugins/markdown_chart.js | 156 ++++++++++++++++++ .../plugins/markdown_tooltip.js | 101 ++++++++++++ .../markdown_editor/markdown_actions.ts | 31 ++-- .../markdown_editor/markdown_editor.tsx | 57 ++++++- .../markdown_editor_toolbar.tsx | 20 ++- .../markdown_editor/markdown_types.ts | 43 +++++ yarn.lock | 56 +++---- 9 files changed, 429 insertions(+), 57 deletions(-) create mode 100644 src-docs/src/views/markdown_editor/plugins/markdown_chart.js create mode 100644 src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js create mode 100644 src/components/markdown_editor/markdown_types.ts diff --git a/package.json b/package.json index a9ab96d34ab..63fd08ddecc 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "remark-emoji": "^2.1.0", "remark-highlight.js": "^5.2.0", "remark-parse": "^7.0.2", - "remark-rehype": "^5.0.0", + "remark-rehype": "^6.0.0", "resize-observer-polyfill": "^1.5.0", "tabbable": "^3.0.0", "unified": "^8.4.2", diff --git a/src-docs/src/views/markdown_editor/markdown_editor.js b/src-docs/src/views/markdown_editor/markdown_editor.js index 284cff072ee..f725cd89328 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor.js +++ b/src-docs/src/views/markdown_editor/markdown_editor.js @@ -1,12 +1,26 @@ /* eslint-disable prettier/prettier */ import React, { useState } from 'react'; -import { EuiMarkdownEditor } from '../../../../src/components/markdown_editor'; +import { defaultParsingPlugins, defaultProcessingPlugins, EuiMarkdownEditor } from '../../../../src/components/markdown_editor'; +import * as MarkdownChart from './plugins/markdown_chart'; +import * as MarkdownTooltip from './plugins/markdown_tooltip'; -// eslint-disable-next-line const markdownExample = require('!!raw-loader!./markdown-example.md'); +const exampleParsingList = [ + ...defaultParsingPlugins, + MarkdownChart.parser, + MarkdownTooltip.parser, +]; + +const exampleProcessingList = [...defaultProcessingPlugins]; // pretend mutation doesn't happen immediately next 😅 +exampleProcessingList[0][1].handlers.chartDemoPlugin = MarkdownChart.handler; +exampleProcessingList[1][1].components.chartDemoPlugin = MarkdownChart.renderer; + +exampleProcessingList[0][1].handlers.tooltipPlugin = MarkdownTooltip.handler; +exampleProcessingList[1][1].components.tooltipPlugin = MarkdownTooltip.renderer; + export default () => { const [value, setValue] = useState(markdownExample); - return ; + return ; }; diff --git a/src-docs/src/views/markdown_editor/plugins/markdown_chart.js b/src-docs/src/views/markdown_editor/plugins/markdown_chart.js new file mode 100644 index 00000000000..fff5e04c6cc --- /dev/null +++ b/src-docs/src/views/markdown_editor/plugins/markdown_chart.js @@ -0,0 +1,156 @@ +import React from 'react'; +import { + Chart, + Settings, + Axis, + BarSeries, + DataGenerator, +} from '@elastic/charts'; +import { EUI_CHARTS_THEME_LIGHT } from '../../../../../src/themes/charts/themes'; +import { + euiPaletteColorBlind, + euiPaletteComplimentary, + euiPaletteCool, + euiPaletteForStatus, + euiPaletteForTemperature, + euiPaletteGray, + euiPaletteNegative, + euiPalettePositive, + euiPaletteWarm, +} from '../../../../../src/services/color'; + +const paletteData = { + euiPaletteColorBlind, + euiPaletteForStatus, + euiPaletteForTemperature, + euiPaletteComplimentary, + euiPaletteNegative, + euiPalettePositive, + euiPaletteCool, + euiPaletteWarm, + euiPaletteGray, +}; +const paletteNames = Object.keys(paletteData); + +const dg = new DataGenerator(); +const data = dg.generateGroupedSeries(20, 5); + +const chartDemoPlugin = { + name: 'chartDemoPlugin', + button: { + label: 'Chart', + iconType: 'visArea', + }, + formatting: { + prefix: '!{chart', + suffix: '}', + trimFirst: true, + }, +}; + +function ChartParser() { + const Parser = this.Parser; + const tokenizers = Parser.prototype.inlineTokenizers; + const methods = Parser.prototype.inlineMethods; + + function tokenizeChart(eat, value, silent) { + if (value.startsWith('!{chart') === false) return false; + + const nextChar = value[7]; + + if (nextChar !== ' ' && nextChar !== '}') return false; // this isn't actually a chart + + if (silent) { + return true; + } + + // is there a configuration? + const hasConfiguration = nextChar === ' '; + + let match = '!{chart'; + let configuration = {}; + + if (hasConfiguration) { + match += ' '; + let configurationString = ''; + + let openObjects = 0; + + for (let i = 8; i < value.length; i++) { + const char = value[i]; + if (char === '{') { + openObjects++; + configurationString += char; + } else if (char === '}') { + openObjects--; + if (openObjects === -1) { + break; + } + configurationString += char; + } else { + configurationString += char; + } + } + + match += configurationString; + try { + configuration = JSON.parse(configurationString); + // eslint-disable-next-line no-empty + } catch (e) {} + } + + match += '}'; + return eat(match)({ + type: 'chartDemoPlugin', + configuration, + }); + } + tokenizeChart.notInBlock = true; + tokenizeChart.notInList = true; + tokenizeChart.notInLink = true; + + tokenizeChart.locator = function locateChart(value, fromIndex) { + return value.indexOf('!{chart', fromIndex - 1); + }; + + tokenizers.chart = tokenizeChart; + methods.push('chart'); +} + +const chartMarkdownHandler = (h, node) => { + return h(node.position, 'chartDemoPlugin', node.configuration, []); +}; +const chartMarkdownRenderer = ({ height = 200, palette = 5 }) => { + const customColors = { + colors: { + vizColors: paletteData[paletteNames[palette]](5), + }, + }; + return ( + + + + + + + ); +}; + +export { + chartDemoPlugin as plugin, + ChartParser as parser, + chartMarkdownHandler as handler, + chartMarkdownRenderer as renderer, +}; diff --git a/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js new file mode 100644 index 00000000000..7ce5464c476 --- /dev/null +++ b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js @@ -0,0 +1,101 @@ +import React from 'react'; +import all from 'mdast-util-to-hast/lib/all'; +import { EuiToolTip } from '../../../../../src'; + +const tooltipPlugin = { + name: 'tooltipPlugin', + button: { + label: 'Tooltip', + iconType: 'flag', + }, + formatting: { + prefix: '!{tooltip', + suffix: '}', + trimFirst: true, + }, +}; + +function TooltipParser() { + const Parser = this.Parser; + const tokenizers = Parser.prototype.inlineTokenizers; + const methods = Parser.prototype.inlineMethods; + + function tokenizeTooltip(eat, value, silent) { + if (value.startsWith('!{tooltip') === false) return false; + + const nextChar = value[9]; + + if (nextChar !== '[') return false; // this isn't actually a tooltip + + let index = 9; + function readArg() { + if (value[index] !== '[') throw 'Expected left bracket'; + index++; + + let body = ''; + let openBrackets = 0; + + for (index; index < value.length; index++) { + const char = value[index]; + + if (char === ']' && openBrackets === 0) { + index++; + return body; + } else if (char === ']') { + openBrackets--; + } else if (char === '[') { + openBrackets++; + } + + body += char; + } + + return ''; + } + const tooltipText = readArg(); + const tooltipBody = readArg(); + + if (!tooltipText || !tooltipBody) return false; + + if (silent) { + return true; + } + + const now = eat.now(); + now.column += 11 + tooltipText.length; + now.offset += 11 + tooltipText.length; + const children = this.tokenizeInline(tooltipBody, now); + + return eat(`!{tooltip[${tooltipText}][${tooltipBody}]}`)({ + type: 'tooltipPlugin', + configuration: { content: tooltipText }, + children, + }); + } + tokenizeTooltip.notInLink = true; + + tokenizeTooltip.locator = function locateTooltip(value, fromIndex) { + return value.indexOf('!{tooltip', fromIndex - 1); + }; + + tokenizers.tooltip = tokenizeTooltip; + methods.push('tooltip'); +} + +const tooltipMarkdownHandler = (h, node) => { + return h(node.position, 'tooltipPlugin', node.configuration, all(h, node)); +}; +const tooltipMarkdownRenderer = ({ content, children }) => { + return ( + + {children} + + ); +}; + +export { + tooltipPlugin as plugin, + TooltipParser as parser, + tooltipMarkdownHandler as handler, + tooltipMarkdownRenderer as renderer, +}; diff --git a/src/components/markdown_editor/markdown_actions.ts b/src/components/markdown_editor/markdown_actions.ts index efad572d6f5..a5e5ba70f24 100644 --- a/src/components/markdown_editor/markdown_actions.ts +++ b/src/components/markdown_editor/markdown_actions.ts @@ -17,19 +17,10 @@ * under the License. */ -interface StyleArgsToUpdate { - prefix?: string; - suffix?: string; - blockPrefix?: string; - blockSuffix?: string; - multiline?: boolean; - replaceNext?: string; - prefixSpace?: boolean; - scanFor?: string; - surroundWithNewlines?: boolean; - orderedList?: boolean; - trimFirst?: boolean; -} +import { + EuiMarkdownEditorUiPlugin, + EuiMarkdownFormatting, +} from './markdown_types'; /** * Class for applying styles to a text editor. Accepts the HTML ID for the textarea @@ -39,17 +30,21 @@ interface StyleArgsToUpdate { * @param {string} editorID */ class MarkdownActions { - editorID: string; - styles: Record; - - constructor(editorID: string) { - this.editorID = editorID; + styles: Record; + constructor(public editorID: string, uiPlugins: EuiMarkdownEditorUiPlugin[]) { /** * This object is in the format: * [nameOfAction]: {[styles to apply]} */ this.styles = { + ...uiPlugins.reduce( + (mappedPlugins, { name, formatting }) => { + mappedPlugins[name] = formatting; + return mappedPlugins; + }, + {} + ), mdBold: { prefix: '**', suffix: '**', diff --git a/src/components/markdown_editor/markdown_editor.tsx b/src/components/markdown_editor/markdown_editor.tsx index 0bcf5e6a9f8..e77b4fedcf8 100644 --- a/src/components/markdown_editor/markdown_editor.tsx +++ b/src/components/markdown_editor/markdown_editor.tsx @@ -46,6 +46,7 @@ import { htmlIdGenerator } from '../../services/accessibility'; import { EuiLink } from '../link'; import { EuiCodeBlock } from '../code'; import { MARKDOWN_MODE, MODE_EDITING, MODE_VIEWING } from './markdown_modes'; +import { EuiMarkdownEditorUiPlugin } from './markdown_types'; function storeMarkdownTree() { return function(tree: any, file: any) { @@ -61,7 +62,13 @@ export const defaultParsingPlugins: PluggableList = [ ]; export const defaultProcessingPlugins: PluggableList = [ - [remark2rehype, { allowDangerousHTML: true }], + [ + remark2rehype, + { + allowDangerousHtml: true, + handlers: {}, + }, + ], [ rehype2react, { @@ -100,6 +107,8 @@ export type EuiMarkdownEditorProps = HTMLAttributes & /** array of unified plugins to convert the AST into a ReactNode */ processingPluginList?: PluggableList; + + uiPlugins?: EuiMarkdownEditorUiPlugin[]; }; export const EuiMarkdownEditor: FunctionComponent = ({ @@ -110,14 +119,19 @@ export const EuiMarkdownEditor: FunctionComponent = ({ height = 150, parsingPluginList = defaultParsingPlugins, processingPluginList = defaultProcessingPlugins, + uiPlugins = [], ...rest }) => { const [viewMode, setViewMode] = useState(MODE_EDITING); const editorId = useMemo(() => _editorId || htmlIdGenerator()(), [_editorId]); - const markdownActions = useMemo(() => new MarkdownActions(editorId), [ - editorId, - ]); + const markdownActions = useMemo( + () => new MarkdownActions(editorId, uiPlugins), + + // uiPlugins _is_ accounted for + // eslint-disable-next-line react-hooks/exhaustive-deps + [editorId, uiPlugins.map(({ name }) => name).join(',')] + ); const classes = classNames('euiMarkdownEditor', className); @@ -129,6 +143,40 @@ export const EuiMarkdownEditor: FunctionComponent = ({ [parsingPluginList, processingPluginList] ); + // const Compiler = (tree, file) => { + // return JSON.stringify(tree, null, 2); + // } + // + // function stringify (options) { + // this.Compiler = Compiler; + // } + // + // console.log(unified().use(parsingPluginList).use([remark2rehype, { allowDangerousHTML: true }]).use(rehypestringify).processSync(value)); + // console.log( + // JSON.parse( + // unified() + // .use(parsingPluginList) + // .use(remark2rehype, { + // allowDangerousHTML: true, + // handlers: { + // chart(h, node) { + // console.log(h); + // console.log(node); + // return h(node.position, 'strong', {className: 'test'}, unistBuilder('test', 'HEY')); + // } + // }, + // unknownHandler(h, node) { + // console.log(h); + // console.log(node); + // h(node.position, 'code', 'THIS IS A TEST'); + // } + // }) + // .use(stringify) + // .processSync(value) + // .contents + // ) + // ); + const isPreviewing = viewMode === MODE_VIEWING; return ( @@ -139,6 +187,7 @@ export const EuiMarkdownEditor: FunctionComponent = ({ setViewMode(isPreviewing ? MODE_EDITING : MODE_VIEWING) } viewMode={viewMode} + uiPlugins={uiPlugins} /> {isPreviewing ? ( diff --git a/src/components/markdown_editor/markdown_editor_toolbar.tsx b/src/components/markdown_editor/markdown_editor_toolbar.tsx index 25abfd8de52..9f81a2d2e58 100644 --- a/src/components/markdown_editor/markdown_editor_toolbar.tsx +++ b/src/components/markdown_editor/markdown_editor_toolbar.tsx @@ -24,12 +24,14 @@ import { EuiFlexItem, EuiFlexGroup } from '../flex'; import { EuiI18n } from '../i18n'; import { EuiToolTip } from '../tool_tip'; import { MARKDOWN_MODE, MODE_VIEWING } from './markdown_modes'; +import { EuiMarkdownEditorUiPlugin } from './markdown_types'; export type EuiMarkdownEditorToolbarProps = HTMLAttributes & CommonProps & { markdownActions?: any; viewMode?: MARKDOWN_MODE; onClickPreview?: any; + uiPlugins: EuiMarkdownEditorUiPlugin[]; }; export class EuiMarkdownEditorToolbar extends Component< @@ -91,7 +93,7 @@ export class EuiMarkdownEditorToolbar extends Component< }; render() { - const { viewMode, onClickPreview } = this.props; + const { viewMode, onClickPreview, uiPlugins } = this.props; const isPreviewing = viewMode === MODE_VIEWING; @@ -139,6 +141,22 @@ export class EuiMarkdownEditorToolbar extends Component< /> ))} + {uiPlugins.length > 0 ? ( + <> + + {uiPlugins.map(({ name, button }) => ( + + this.handleMdButtonClick(name)} + iconType={button.iconType} + aria-label={button.label} + isDisabled={isPreviewing} + /> + + ))} + + ) : null} diff --git a/src/components/markdown_editor/markdown_types.ts b/src/components/markdown_editor/markdown_types.ts new file mode 100644 index 00000000000..529d4f2fbd4 --- /dev/null +++ b/src/components/markdown_editor/markdown_types.ts @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IconType } from '../icon'; + +export interface EuiMarkdownEditorUiPlugin { + name: string; + button: { + label: string; + iconType: IconType; + }; + formatting: EuiMarkdownFormatting; +} + +export interface EuiMarkdownFormatting { + prefix?: string; + suffix?: string; + blockPrefix?: string; + blockSuffix?: string; + multiline?: boolean; + replaceNext?: string; + prefixSpace?: boolean; + scanFor?: string; + surroundWithNewlines?: boolean; + orderedList?: boolean; + trimFirst?: boolean; +} diff --git a/yarn.lock b/yarn.lock index 6bd35224bbd..3f0f13734bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10057,29 +10057,27 @@ mdast-util-compact@^1.0.0: dependencies: unist-util-visit "^1.1.0" -mdast-util-definitions@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.5.tgz#3fe622a4171c774ebd06f11e9f8af7ec53ea5c74" - integrity sha512-CJXEdoLfiISCDc2JB6QLb79pYfI6+GcIH+W2ox9nMc7od0Pz+bovcHsiq29xAQY6ayqe/9CsK2VzkSJdg1pFYA== +mdast-util-definitions@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-2.0.1.tgz#2c931d8665a96670639f17f98e32c3afcfee25f3" + integrity sha512-Co+DQ6oZlUzvUR7JCpP249PcexxygiaKk9axJh+eRzHDZJk2julbIdKB4PXHVxdBuLzvJ1Izb+YDpj2deGMOuA== dependencies: - unist-util-visit "^1.0.0" + unist-util-visit "^2.0.0" -mdast-util-to-hast@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-6.0.2.tgz#24a8791b7c624118637d70f03a9d29116e4311cf" - integrity sha512-GjcOimC9qHI0yNFAQdBesrZXzUkRdFleQlcoU8+TVNfDW6oLUazUx8MgUoTaUyCJzBOnE5AOgqhpURrSlf0QwQ== +mdast-util-to-hast@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-8.2.0.tgz#adf9f824defcd382e53dd7bace4282a45602ac67" + integrity sha512-WjH/KXtqU66XyTJQ7tg7sjvTw1OQcVV0hKdFh3BgHPwZ96fSBCQ/NitEHsN70Mmnggt+5eUUC7pCnK+2qGQnCA== dependencies: collapse-white-space "^1.0.0" detab "^2.0.0" - mdast-util-definitions "^1.2.0" - mdurl "^1.0.1" - trim "0.0.1" + mdast-util-definitions "^2.0.0" + mdurl "^1.0.0" trim-lines "^1.0.0" - unist-builder "^1.0.1" - unist-util-generated "^1.1.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" unist-util-position "^3.0.0" - unist-util-visit "^1.1.0" - xtend "^4.0.1" + unist-util-visit "^2.0.0" mdn-data@2.0.4: version "2.0.4" @@ -10091,7 +10089,7 @@ mdn-data@~1.1.0: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== -mdurl@^1.0.1: +mdurl@^1.0.0, mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= @@ -13930,12 +13928,12 @@ remark-parse@^7.0.2: vfile-location "^2.0.0" xtend "^4.0.1" -remark-rehype@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-5.0.0.tgz#dcf85b481bfaadf262ddde9b4ecefbb7f2673e70" - integrity sha512-tgo+AeOotuh9FnGMkEPbE6C3OfdARqqSxT0H/KNGAiTwJLiDoRSm6x/ytqPZTyYSiQ/exbi/kx7k6uUvqYL1wQ== +remark-rehype@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-6.0.0.tgz#dcd340ebee412709a81b15a69f4ae474a38aa72a" + integrity sha512-dt7cHCD2NbbmXoSnnNolk+MnWzylsOIEU07pyhZSM71Xy08xX07+yuCh+4rddyrB/a1hebygeteVEJieyCeDzg== dependencies: - mdast-util-to-hast "^6.0.0" + mdast-util-to-hast "^8.0.0" remark-stringify@^4.0.0: version "4.0.0" @@ -16382,12 +16380,10 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" -unist-builder@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-1.0.4.tgz#e1808aed30bd72adc3607f25afecebef4dd59e17" - integrity sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg== - dependencies: - object-assign "^4.1.0" +unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" + integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== unist-util-find-all-after@^1.0.1: version "1.0.5" @@ -16396,7 +16392,7 @@ unist-util-find-all-after@^1.0.1: dependencies: unist-util-is "^3.0.0" -unist-util-generated@^1.1.0: +unist-util-generated@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.5.tgz#1e903e68467931ebfaea386dae9ea253628acd42" integrity sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw== @@ -16457,7 +16453,7 @@ unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.3.0: dependencies: unist-util-visit-parents "^2.0.0" -unist-util-visit@^2.0.2: +unist-util-visit@^2.0.0, unist-util-visit@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.2.tgz#3843782a517de3d2357b4c193b24af2d9366afb7" integrity sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ== From 53fed9b0e0366932c7a61fbad5d95499b7cafa8e Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Fri, 15 May 2020 08:29:18 -0600 Subject: [PATCH 2/3] Change tooltip markdown plugin markdown format --- .../plugins/markdown_tooltip.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js index 7ce5464c476..c90e1192d42 100644 --- a/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js +++ b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js @@ -9,8 +9,8 @@ const tooltipPlugin = { iconType: 'flag', }, formatting: { - prefix: '!{tooltip', - suffix: '}', + prefix: '!{tooltip[', + suffix: ']()}', trimFirst: true, }, }; @@ -28,8 +28,8 @@ function TooltipParser() { if (nextChar !== '[') return false; // this isn't actually a tooltip let index = 9; - function readArg() { - if (value[index] !== '[') throw 'Expected left bracket'; + function readArg(open, close) { + if (value[index] !== open) throw 'Expected left bracket'; index++; let body = ''; @@ -38,12 +38,12 @@ function TooltipParser() { for (index; index < value.length; index++) { const char = value[index]; - if (char === ']' && openBrackets === 0) { + if (char === close && openBrackets === 0) { index++; return body; - } else if (char === ']') { + } else if (char === close) { openBrackets--; - } else if (char === '[') { + } else if (char === open) { openBrackets++; } @@ -52,10 +52,10 @@ function TooltipParser() { return ''; } - const tooltipText = readArg(); - const tooltipBody = readArg(); + const tooltipAnchor = readArg('[', ']'); + const tooltipText = readArg('(', ')'); - if (!tooltipText || !tooltipBody) return false; + if (!tooltipText || !tooltipAnchor) return false; if (silent) { return true; @@ -64,9 +64,9 @@ function TooltipParser() { const now = eat.now(); now.column += 11 + tooltipText.length; now.offset += 11 + tooltipText.length; - const children = this.tokenizeInline(tooltipBody, now); + const children = this.tokenizeInline(tooltipAnchor, now); - return eat(`!{tooltip[${tooltipText}][${tooltipBody}]}`)({ + return eat(`!{tooltip[${tooltipAnchor}](${tooltipText})}`)({ type: 'tooltipPlugin', configuration: { content: tooltipText }, children, From 94fcd90bfd58b56c8f1b87382137520a1463e7ef Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Fri, 15 May 2020 14:58:05 -0600 Subject: [PATCH 3/3] Fixed error with empty tooltip tag --- src-docs/src/views/markdown_editor/plugins/markdown_chart.js | 4 ++-- .../src/views/markdown_editor/plugins/markdown_tooltip.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src-docs/src/views/markdown_editor/plugins/markdown_chart.js b/src-docs/src/views/markdown_editor/plugins/markdown_chart.js index fff5e04c6cc..6587b56efae 100644 --- a/src-docs/src/views/markdown_editor/plugins/markdown_chart.js +++ b/src-docs/src/views/markdown_editor/plugins/markdown_chart.js @@ -110,11 +110,11 @@ function ChartParser() { tokenizeChart.notInLink = true; tokenizeChart.locator = function locateChart(value, fromIndex) { - return value.indexOf('!{chart', fromIndex - 1); + return value.indexOf('!{chart', fromIndex); }; tokenizers.chart = tokenizeChart; - methods.push('chart'); + methods.splice(methods.indexOf('text'), 0, 'chart'); } const chartMarkdownHandler = (h, node) => { diff --git a/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js index c90e1192d42..d98d60befae 100644 --- a/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js +++ b/src-docs/src/views/markdown_editor/plugins/markdown_tooltip.js @@ -75,11 +75,11 @@ function TooltipParser() { tokenizeTooltip.notInLink = true; tokenizeTooltip.locator = function locateTooltip(value, fromIndex) { - return value.indexOf('!{tooltip', fromIndex - 1); + return value.indexOf('!{tooltip', fromIndex); }; tokenizers.tooltip = tokenizeTooltip; - methods.push('tooltip'); + methods.splice(methods.indexOf('text'), 0, 'tooltip'); } const tooltipMarkdownHandler = (h, node) => {