From 7612d364679d1f1e192dea3a3cf467d0b1a97857 Mon Sep 17 00:00:00 2001 From: Youhei Sakurai Date: Fri, 12 Apr 2024 00:40:02 +0900 Subject: [PATCH 1/5] Add option to opt out of line-breaks plugin --- .../views/markdown_editor/markdown_editor.js | 1 - .../markdown_editor_example.js | 11 +-- .../markdown_editor_no_plugins.js | 14 +++- .../parsing_plugins.ts | 9 +- .../markdown_default_plugins/plugins.test.ts | 84 +++++++++++++++++++ .../markdown_default_plugins/plugins.ts | 2 +- .../processing_plugins.tsx | 2 +- .../markdown_default_plugins/ui_plugins.ts | 4 +- 8 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts diff --git a/src-docs/src/views/markdown_editor/markdown_editor.js b/src-docs/src/views/markdown_editor/markdown_editor.js index 3e6b98a12c0e..aa88476100c4 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor.js +++ b/src-docs/src/views/markdown_editor/markdown_editor.js @@ -21,7 +21,6 @@ The editor also ships with some built in plugins. For example it can handle chec - [ ] Or empty It can also handle emojis! :smile: - And it can render !{tooltip[tooltips like this](Look! I'm a very helpful tooltip content!)} `; diff --git a/src-docs/src/views/markdown_editor/markdown_editor_example.js b/src-docs/src/views/markdown_editor/markdown_editor_example.js index baa91ddf5116..8c6f242c4985 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor_example.js +++ b/src-docs/src/views/markdown_editor/markdown_editor_example.js @@ -133,16 +133,17 @@ export const MarkdownEditorExample = { title: 'Unregistering plugins', text: (

- The EuiMarkdownEditor comes with a default plugin for{' '} - tooltip support. However, this may be unfamiliar or - unnecessary in some contexts, and you can unregister this plugin by - excluding it from the + The EuiMarkdownEditor comes with default plugins such + as tooltip and line-breaks.{' '} + However, these may be unfamiliar or unnecessary in some contexts, and + you can unregister these plugins by excluding them from the parsingPlugins,{' '} processingPlugins and uiPlugins{' '} options with a single exclude parameter passed to{' '} getDefaultEuiMarkdownPlugins(). This will ensure the syntax won't be identified or rendered and no additional UI, - like the button and help syntax, will be displayed. + like the button and help syntax, will be displayed by the unregistered + plugins.

), props: { diff --git a/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js b/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js index 5b4dc9b2e644..217bae6f6db2 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js +++ b/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js @@ -7,15 +7,25 @@ import { const initialContent = `## This is how we do it :smile: -In this example, we unregistered the built in **tooltip** plugin. So the button in the toolbar and the help syntax won't be displayed. +In this example, we unregistered the built in **tooltip** and **line-breaks** plugins. +### tooltip + +The button in the toolbar and the help syntax won't be displayed. And the following syntax no longer works. !{tooltip[anchor text](Tooltip content)} + +### line-breaks + +More than two trailing spaces break consecutive lines, +but not otherwise. + +A blank line separates sections as usual. `; const { parsingPlugins, processingPlugins, uiPlugins } = - getDefaultEuiMarkdownPlugins({ exclude: ['tooltip'] }); + getDefaultEuiMarkdownPlugins({ exclude: ['tooltip', 'line-breaks'] }); export default () => { const [value, setValue] = useState(initialContent); diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts index b2a9e708b79f..cd00054caf3a 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts @@ -37,13 +37,14 @@ export type DefaultEuiMarkdownParsingPlugins = PluggableList; export const getDefaultEuiMarkdownParsingPlugins = ({ exclude, -}: { exclude?: Array<'tooltip'> } = {}): DefaultEuiMarkdownParsingPlugins => { +}: { + exclude?: Array<'tooltip' | 'line-breaks'>; +} = {}): DefaultEuiMarkdownParsingPlugins => { const excludeSet = new Set(exclude); const parsingPlugins: PluggableList = [ [markdown, {}], [highlight, {}], [emoji, { emoticon: false }], - [breaks, {}], [ euiMarkdownLinkValidator, { @@ -57,6 +58,10 @@ export const getDefaultEuiMarkdownParsingPlugins = ({ if (!excludeSet.has('tooltip')) parsingPlugins.push([MarkdownTooltip.parser, {}]); + if (!excludeSet.has('line-breaks')) { + parsingPlugins.push([breaks, {}]); + } + return parsingPlugins; }; diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts new file mode 100644 index 000000000000..cb075b1470be --- /dev/null +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import breaks from 'remark-breaks'; + +import * as MarkdownTooltip from '../markdown_tooltip'; +import { getDefaultEuiMarkdownPlugins } from './plugins'; + +import type { Pluggable, PluginTuple, Settings } from 'unified'; +import type { EuiMarkdownEditorUiPlugin } from '../../markdown_types'; + +const excludableDefaultPlugins: Array< + [ + 'tooltip' | 'line-breaks', + Pluggable | null, + React.ComponentType | null, + EuiMarkdownEditorUiPlugin | null + ] +> = [ + [ + 'tooltip', + MarkdownTooltip.parser, + MarkdownTooltip.renderer, + MarkdownTooltip.plugin, + ], + ['line-breaks', breaks, null, null], +]; + +describe('opt out of default plugins', () => { + it('exclude nothing', () => { + const { parsingPlugins, processingPlugins, uiPlugins } = + getDefaultEuiMarkdownPlugins({}); + + excludableDefaultPlugins.forEach( + ([, parsingPlugin, processingPlugin, uiPlugin]) => { + if (parsingPlugin !== null) { + expect( + parsingPlugins.find((p) => (p as PluginTuple)[0] === parsingPlugin) + ).not.toBeUndefined(); + } + + if (processingPlugin !== null) { + expect(Object.values(processingPlugins[1][1].components)).toContain( + processingPlugin + ); + } + + if (uiPlugin !== null) { + expect(uiPlugins).toContain(uiPlugin); + } + } + ); + }); + + test.each(excludableDefaultPlugins)( + 'exclude %s', + (plugin, parsingPlugin, processingPlugin, uiPlugin) => { + const { parsingPlugins, processingPlugins, uiPlugins } = + getDefaultEuiMarkdownPlugins({ exclude: [plugin] }); + + if (parsingPlugin !== null) { + expect( + parsingPlugins.find((p) => (p as PluginTuple)[0] === parsingPlugin) + ).toBeUndefined(); + } + + if (processingPlugin !== null) { + expect(Object.values(processingPlugins[1][1].components)).not.toContain( + processingPlugin + ); + } + + if (uiPlugin !== null) { + expect(uiPlugins).not.toContain(uiPlugin); + } + } + ); +}); diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts index 77c658f14c21..d9526e0dd407 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts @@ -20,7 +20,7 @@ import { } from './processing_plugins'; export const getDefaultEuiMarkdownPlugins = ( - config: undefined | { exclude?: Array<'tooltip'> } + config: undefined | { exclude?: Array<'tooltip' | 'line-breaks'> } ): { parsingPlugins: DefaultEuiMarkdownParsingPlugins; processingPlugins: DefaultEuiMarkdownProcessingPlugins; diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx b/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx index af79901d2686..3a6effd36f50 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx @@ -53,7 +53,7 @@ export type DefaultEuiMarkdownProcessingPlugins = [ export const getDefaultEuiMarkdownProcessingPlugins = ({ exclude, }: { - exclude?: Array<'tooltip'>; + exclude?: Array<'tooltip' | 'line-breaks'>; } = {}): DefaultEuiMarkdownProcessingPlugins => { const excludeSet = new Set(exclude); diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts index f5dc92cb9c8a..b3ea2cd81d26 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts @@ -13,7 +13,9 @@ export type DefaultEuiMarkdownUiPlugins = EuiMarkdownEditorUiPlugin[]; export const getDefaultEuiMarkdownUiPlugins = ({ exclude, -}: { exclude?: Array<'tooltip'> } = {}): DefaultEuiMarkdownUiPlugins => { +}: { + exclude?: Array<'tooltip' | 'line-breaks'>; +} = {}): DefaultEuiMarkdownUiPlugins => { const excludeSet = new Set(exclude); const uiPlugins = []; From 5f01ec179dec84c7873a89020cca0e5d93c67e1a Mon Sep 17 00:00:00 2001 From: Youhei Sakurai Date: Fri, 12 Apr 2024 01:20:36 +0900 Subject: [PATCH 2/5] Add changelog --- changelogs/upcoming/7676.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/upcoming/7676.md diff --git a/changelogs/upcoming/7676.md b/changelogs/upcoming/7676.md new file mode 100644 index 000000000000..cf6a1b9cd934 --- /dev/null +++ b/changelogs/upcoming/7676.md @@ -0,0 +1,2 @@ +- Added a way to exclude the line-breaks plugin from defaults in EuiMarkdownEditor. + From caf13ddb18ae61ba925477f786c5eaf200999119 Mon Sep 17 00:00:00 2001 From: Youhei Sakurai Date: Fri, 12 Apr 2024 01:30:54 +0900 Subject: [PATCH 3/5] Updated snippet --- src-docs/src/views/markdown_editor/markdown_editor_example.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-docs/src/views/markdown_editor/markdown_editor_example.js b/src-docs/src/views/markdown_editor/markdown_editor_example.js index 8c6f242c4985..7b2bc914624f 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor_example.js +++ b/src-docs/src/views/markdown_editor/markdown_editor_example.js @@ -60,7 +60,7 @@ const markdownEditorNoPluginsSnippet = `const { parsingPlugins, processingPlugins, uiPlugins, -} = getDefaultEuiMarkdownPlugins({ exclude: ['tooltip'] }); +} = getDefaultEuiMarkdownPlugins({ exclude: ['tooltip', 'line-breaks'] }); Date: Fri, 12 Apr 2024 14:57:10 -0700 Subject: [PATCH 4/5] Extend `exclude` API to allow for excluding even more plugins + convert `line-breaks` plugin to camel case for casing consistency + DRY out types and exclude iteration + simplify tests slightly - IMO with static maps, there's less need to confirm the correct behavior, just that something was pushed or not pushed --- .../parsing_plugins.ts | 43 ++++--- .../markdown_default_plugins/plugins.test.ts | 108 +++++++----------- .../markdown_default_plugins/plugins.ts | 13 ++- .../processing_plugins.tsx | 36 ++++-- .../markdown_default_plugins/ui_plugins.ts | 22 ++-- 5 files changed, 119 insertions(+), 103 deletions(-) diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts index cd00054caf3a..d0ebcb12d829 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.ts @@ -32,35 +32,40 @@ import { euiMarkdownLinkValidator, EuiMarkdownLinkValidatorOptions, } from '../markdown_link_validator'; +import type { ExcludableDefaultPlugins, DefaultPluginsConfig } from './plugins'; export type DefaultEuiMarkdownParsingPlugins = PluggableList; +const DEFAULT_PARSING_PLUGINS: Record< + ExcludableDefaultPlugins, + DefaultEuiMarkdownParsingPlugins[0] +> = { + emoji: [emoji, { emoticon: false }], + lineBreaks: [breaks, {}], + linkValidator: [ + euiMarkdownLinkValidator, + { + allowRelative: true, + allowProtocols: ['https:', 'http:', 'mailto:'], + } as EuiMarkdownLinkValidatorOptions, + ], + checkbox: [MarkdownCheckbox.parser, {}], + tooltip: [MarkdownTooltip.parser, {}], +}; + export const getDefaultEuiMarkdownParsingPlugins = ({ exclude, -}: { - exclude?: Array<'tooltip' | 'line-breaks'>; -} = {}): DefaultEuiMarkdownParsingPlugins => { - const excludeSet = new Set(exclude); +}: DefaultPluginsConfig = {}): DefaultEuiMarkdownParsingPlugins => { const parsingPlugins: PluggableList = [ [markdown, {}], [highlight, {}], - [emoji, { emoticon: false }], - [ - euiMarkdownLinkValidator, - { - allowRelative: true, - allowProtocols: ['https:', 'http:', 'mailto:'], - } as EuiMarkdownLinkValidatorOptions, - ], - [MarkdownCheckbox.parser, {}], ]; - if (!excludeSet.has('tooltip')) - parsingPlugins.push([MarkdownTooltip.parser, {}]); - - if (!excludeSet.has('line-breaks')) { - parsingPlugins.push([breaks, {}]); - } + Object.entries(DEFAULT_PARSING_PLUGINS).forEach(([pluginName, plugin]) => { + if (!exclude?.includes(pluginName as ExcludableDefaultPlugins)) { + parsingPlugins.push(plugin); + } + }); return parsingPlugins; }; diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts index cb075b1470be..211b95a6f769 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.test.ts @@ -6,79 +6,57 @@ * Side Public License, v 1. */ -import React from 'react'; -import breaks from 'remark-breaks'; - -import * as MarkdownTooltip from '../markdown_tooltip'; import { getDefaultEuiMarkdownPlugins } from './plugins'; -import type { Pluggable, PluginTuple, Settings } from 'unified'; -import type { EuiMarkdownEditorUiPlugin } from '../../markdown_types'; - -const excludableDefaultPlugins: Array< - [ - 'tooltip' | 'line-breaks', - Pluggable | null, - React.ComponentType | null, - EuiMarkdownEditorUiPlugin | null - ] -> = [ - [ - 'tooltip', - MarkdownTooltip.parser, - MarkdownTooltip.renderer, - MarkdownTooltip.plugin, - ], - ['line-breaks', breaks, null, null], -]; - -describe('opt out of default plugins', () => { - it('exclude nothing', () => { +describe('default plugins', () => { + test('no exclusions', () => { const { parsingPlugins, processingPlugins, uiPlugins } = - getDefaultEuiMarkdownPlugins({}); + getDefaultEuiMarkdownPlugins(); - excludableDefaultPlugins.forEach( - ([, parsingPlugin, processingPlugin, uiPlugin]) => { - if (parsingPlugin !== null) { - expect( - parsingPlugins.find((p) => (p as PluginTuple)[0] === parsingPlugin) - ).not.toBeUndefined(); - } + expect(parsingPlugins).toHaveLength(7); + expect(Object.keys(processingPlugins[1][1].components)).toHaveLength(8); + expect(uiPlugins).toHaveLength(1); - if (processingPlugin !== null) { - expect(Object.values(processingPlugins[1][1].components)).toContain( - processingPlugin - ); - } - - if (uiPlugin !== null) { - expect(uiPlugins).toContain(uiPlugin); - } - } - ); + expect(processingPlugins[1][1].components.tooltipPlugin).toBeDefined(); + expect(processingPlugins[1][1].components.checkboxPlugin).toBeDefined(); }); - test.each(excludableDefaultPlugins)( - 'exclude %s', - (plugin, parsingPlugin, processingPlugin, uiPlugin) => { - const { parsingPlugins, processingPlugins, uiPlugins } = - getDefaultEuiMarkdownPlugins({ exclude: [plugin] }); + test('exclude tooltips', () => { + const { parsingPlugins, processingPlugins, uiPlugins } = + getDefaultEuiMarkdownPlugins({ + exclude: ['tooltip'], + }); - if (parsingPlugin !== null) { - expect( - parsingPlugins.find((p) => (p as PluginTuple)[0] === parsingPlugin) - ).toBeUndefined(); - } + expect(parsingPlugins).toHaveLength(6); + expect(processingPlugins[1][1].components.tooltipPlugin).toBeUndefined(); + expect(uiPlugins).toHaveLength(0); + }); - if (processingPlugin !== null) { - expect(Object.values(processingPlugins[1][1].components)).not.toContain( - processingPlugin - ); - } + test('exclude checkboxes', () => { + const { parsingPlugins, processingPlugins, uiPlugins } = + getDefaultEuiMarkdownPlugins({ + exclude: ['checkbox'], + }); + + expect(parsingPlugins).toHaveLength(6); + expect(processingPlugins[1][1].components.checkboxPlugin).toBeUndefined(); + expect(uiPlugins).toHaveLength(1); + }); - if (uiPlugin !== null) { - expect(uiPlugins).not.toContain(uiPlugin); - } - } - ); + test('all exclusions', () => { + const { parsingPlugins, processingPlugins, uiPlugins } = + getDefaultEuiMarkdownPlugins({ + exclude: [ + 'tooltip', + 'checkbox', + 'lineBreaks', + 'linkValidator', + 'emoji', + ], + }); + + expect(parsingPlugins).toHaveLength(2); + expect(Object.keys(processingPlugins[1][1].components)).toHaveLength(6); + expect(uiPlugins).toHaveLength(0); + }); }); diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts index d9526e0dd407..9a8c3001d616 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/plugins.ts @@ -19,8 +19,19 @@ import { DefaultEuiMarkdownProcessingPlugins, } from './processing_plugins'; +export type ExcludableDefaultPlugins = + | 'emoji' + | 'lineBreaks' + | 'linkValidator' + | 'checkbox' + | 'tooltip'; + +export type DefaultPluginsConfig = + | undefined + | { exclude?: ExcludableDefaultPlugins[] }; + export const getDefaultEuiMarkdownPlugins = ( - config: undefined | { exclude?: Array<'tooltip' | 'line-breaks'> } + config?: DefaultPluginsConfig ): { parsingPlugins: DefaultEuiMarkdownParsingPlugins; processingPlugins: DefaultEuiMarkdownProcessingPlugins; diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx b/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx index 3a6effd36f50..04c575d826ae 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.tsx @@ -28,13 +28,16 @@ import { Options as Remark2RehypeOptions, Handler } from 'mdast-util-to-hast'; import all from 'mdast-util-to-hast/lib/all'; import rehype2react from 'rehype-react'; import remark2rehype from 'remark-rehype'; -import * as MarkdownTooltip from '../markdown_tooltip'; -import * as MarkdownCheckbox from '../markdown_checkbox'; -import { FENCED_CLASS } from '../remark/remark_prismjs'; + import { EuiLink } from '../../../link'; import { EuiCodeBlock, EuiCode } from '../../../code'; import { EuiHorizontalRule } from '../../../horizontal_rule'; +import { FENCED_CLASS } from '../remark/remark_prismjs'; +import * as MarkdownTooltip from '../markdown_tooltip'; +import * as MarkdownCheckbox from '../markdown_checkbox'; +import type { ExcludableDefaultPlugins, DefaultPluginsConfig } from './plugins'; + const unknownHandler: Handler = (h, node) => { return h(node, node.type, node, all(h, node)); }; @@ -50,12 +53,26 @@ export type DefaultEuiMarkdownProcessingPlugins = [ ...PluggableList // any additional are generic ]; +const DEFAULT_COMPONENT_RENDERERS: Partial< + Record> +> = { + checkbox: MarkdownCheckbox.renderer, + tooltip: MarkdownTooltip.renderer, +}; + export const getDefaultEuiMarkdownProcessingPlugins = ({ exclude, -}: { - exclude?: Array<'tooltip' | 'line-breaks'>; -} = {}): DefaultEuiMarkdownProcessingPlugins => { - const excludeSet = new Set(exclude); +}: DefaultPluginsConfig = {}): DefaultEuiMarkdownProcessingPlugins => { + const componentPluginsWithExclusions: Rehype2ReactOptions['components'] = {}; + + Object.entries(DEFAULT_COMPONENT_RENDERERS).forEach( + ([excludeName, renderer]) => { + if (!exclude?.includes(excludeName as ExcludableDefaultPlugins)) { + const pluginName = `${excludeName}Plugin`; + componentPluginsWithExclusions[pluginName] = renderer; + } + } + ); const plugins: DefaultEuiMarkdownProcessingPlugins = [ [ @@ -99,15 +116,12 @@ export const getDefaultEuiMarkdownProcessingPlugins = ({ ), hr: (props) => , - checkboxPlugin: MarkdownCheckbox.renderer, + ...componentPluginsWithExclusions, }, }, ], ]; - if (!excludeSet.has('tooltip')) - plugins[1][1].components.tooltipPlugin = MarkdownTooltip.renderer; - return plugins; }; diff --git a/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts b/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts index b3ea2cd81d26..131f3daed9aa 100644 --- a/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts +++ b/src/components/markdown_editor/plugins/markdown_default_plugins/ui_plugins.ts @@ -6,20 +6,28 @@ * Side Public License, v 1. */ -import * as MarkdownTooltip from '../markdown_tooltip'; import { EuiMarkdownEditorUiPlugin } from './../../markdown_types'; +import * as MarkdownTooltip from '../markdown_tooltip'; +import type { ExcludableDefaultPlugins, DefaultPluginsConfig } from './plugins'; export type DefaultEuiMarkdownUiPlugins = EuiMarkdownEditorUiPlugin[]; +const DEFAULT_UI_PLUGINS: Partial< + Record +> = { + tooltip: MarkdownTooltip.plugin, +}; + export const getDefaultEuiMarkdownUiPlugins = ({ exclude, -}: { - exclude?: Array<'tooltip' | 'line-breaks'>; -} = {}): DefaultEuiMarkdownUiPlugins => { - const excludeSet = new Set(exclude); - const uiPlugins = []; +}: DefaultPluginsConfig = {}): DefaultEuiMarkdownUiPlugins => { + const uiPlugins: EuiMarkdownEditorUiPlugin[] = []; - if (!excludeSet.has('tooltip')) uiPlugins.push(MarkdownTooltip.plugin); + Object.entries(DEFAULT_UI_PLUGINS).forEach(([pluginName, plugin]) => { + if (!exclude?.includes(pluginName as ExcludableDefaultPlugins)) { + uiPlugins.push(plugin); + } + }); return uiPlugins; }; From f297f6f5e027a16ceaca7eb2649604258e3bd26b Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Fri, 12 Apr 2024 16:54:04 -0700 Subject: [PATCH 5/5] Update docs & changelog --- changelogs/upcoming/7676.md | 7 +- .../markdown_editor_example.js | 23 ++-- .../markdown_editor_no_plugins.js | 111 ++++++++++++++---- 3 files changed, 109 insertions(+), 32 deletions(-) diff --git a/changelogs/upcoming/7676.md b/changelogs/upcoming/7676.md index cf6a1b9cd934..74353df485e9 100644 --- a/changelogs/upcoming/7676.md +++ b/changelogs/upcoming/7676.md @@ -1,2 +1,5 @@ -- Added a way to exclude the line-breaks plugin from defaults in EuiMarkdownEditor. - +- Updated `getDefaultEuiMarkdownPlugins()` to allow excluding the following plugins in addition to `tooltip`: + - `checkbox` + - `linkValidator` + - `lineBreaks` + - `emoji` diff --git a/src-docs/src/views/markdown_editor/markdown_editor_example.js b/src-docs/src/views/markdown_editor/markdown_editor_example.js index 7b2bc914624f..81f795fb07d9 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor_example.js +++ b/src-docs/src/views/markdown_editor/markdown_editor_example.js @@ -60,7 +60,15 @@ const markdownEditorNoPluginsSnippet = `const { parsingPlugins, processingPlugins, uiPlugins, -} = getDefaultEuiMarkdownPlugins({ exclude: ['tooltip', 'line-breaks'] }); +} = getDefaultEuiMarkdownPlugins({ + exclude: [ + 'tooltip', + 'checkbox', + 'linkValidator', + 'lineBreaks', + 'emoji', + ], +}); - The EuiMarkdownEditor comes with default plugins such - as tooltip and line-breaks.{' '} - However, these may be unfamiliar or unnecessary in some contexts, and - you can unregister these plugins by excluding them from the - parsingPlugins,{' '} + The EuiMarkdownEditor comes with several default + plugins, demo'd below. If these defaults are unnecessary for your + use-case or context, you can unregister these plugins by excluding + them from the parsingPlugins,{' '} processingPlugins and uiPlugins{' '} options with a single exclude parameter passed to{' '} getDefaultEuiMarkdownPlugins(). This will ensure - the syntax won't be identified or rendered and no additional UI, - like the button and help syntax, will be displayed by the unregistered + the syntax won't be identified or rendered, and no additional UI (like + toolbar buttons or help syntax) will be displayed by the unregistered plugins.

), diff --git a/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js b/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js index 217bae6f6db2..f77e9207cc04 100644 --- a/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js +++ b/src-docs/src/views/markdown_editor/markdown_editor_no_plugins.js @@ -1,45 +1,112 @@ -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import { EuiMarkdownEditor, getDefaultEuiMarkdownPlugins, + EuiFlexGroup, + EuiFlexItem, + EuiSwitch, } from '../../../../src/components'; -const initialContent = `## This is how we do it :smile: - -In this example, we unregistered the built in **tooltip** and **line-breaks** plugins. - +const initialContent = ` ### tooltip -The button in the toolbar and the help syntax won't be displayed. -And the following syntax no longer works. +When disabled, the button in the toolbar and the help syntax won't be displayed, and the following syntax will no longer works. !{tooltip[anchor text](Tooltip content)} -### line-breaks +### checkbox -More than two trailing spaces break consecutive lines, -but not otherwise. +When disabled, a EuiCheckbox will no longer render. -A blank line separates sections as usual. -`; +- [ ] TODO: Disable some default plugins + +### emoji + +When disabled, text will render instead of an emoji. + +:smile: + +### linkValidator + +When disabled, all links will render as links instead of as text. -const { parsingPlugins, processingPlugins, uiPlugins } = - getDefaultEuiMarkdownPlugins({ exclude: ['tooltip', 'line-breaks'] }); +[This is a sus link](file://) + +### lineBreaks + +When disabled, these sentence will be in the same line. +When enabled, these sentences will be separated by a line break. + +Two blank lines in a row will create a new paragraph as usual. +`; export default () => { const [value, setValue] = useState(initialContent); + const [tooltip, excludeTooltips] = useState(false); + const [checkbox, excludeCheckboxes] = useState(true); + const [emoji, excludeEmojis] = useState(true); + const [linkValidator, excludeLinkValidator] = useState(true); + const [lineBreaks, excludeLineBreaks] = useState(false); + + const { parsingPlugins, processingPlugins, uiPlugins } = useMemo(() => { + const excludedPlugins = []; + if (!tooltip) excludedPlugins.push('tooltip'); + if (!checkbox) excludedPlugins.push('checkbox'); + if (!emoji) excludedPlugins.push('emoji'); + if (!linkValidator) excludedPlugins.push('linkValidator'); + if (!lineBreaks) excludedPlugins.push('lineBreaks'); + + return getDefaultEuiMarkdownPlugins({ + exclude: excludedPlugins, + }); + }, [tooltip, checkbox, emoji, linkValidator, lineBreaks]); + return ( <> - + + + excludeTooltips(!tooltip)} + /> + excludeCheckboxes(!checkbox)} + /> + excludeEmojis(!emoji)} + /> + excludeLinkValidator(!linkValidator)} + /> + excludeLineBreaks(!lineBreaks)} + /> + + + + + ); };