Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/upcoming/7676.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added a way to exclude the line-breaks plugin from defaults in EuiMarkdownEditor.

1 change: 0 additions & 1 deletion src-docs/src/views/markdown_editor/markdown_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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!)}
`;

Expand Down
13 changes: 7 additions & 6 deletions src-docs/src/views/markdown_editor/markdown_editor_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const markdownEditorNoPluginsSnippet = `const {
parsingPlugins,
processingPlugins,
uiPlugins,
} = getDefaultEuiMarkdownPlugins({ exclude: ['tooltip'] });
} = getDefaultEuiMarkdownPlugins({ exclude: ['tooltip', 'line-breaks'] });

<EuiMarkdownEditor
value={value}
Expand Down Expand Up @@ -133,16 +133,17 @@ export const MarkdownEditorExample = {
title: 'Unregistering plugins',
text: (
<p>
The <strong>EuiMarkdownEditor</strong> comes with a default plugin for{' '}
<EuiCode>tooltip</EuiCode> support. However, this may be unfamiliar or
unnecessary in some contexts, and you can unregister this plugin by
excluding it from the
The <strong>EuiMarkdownEditor</strong> comes with default plugins such
as <EuiCode>tooltip</EuiCode> and <EuiCode>line-breaks</EuiCode>.{' '}
However, these may be unfamiliar or unnecessary in some contexts, and
you can unregister these plugins by excluding them from the
<EuiCode>parsingPlugins</EuiCode>,{' '}
<EuiCode>processingPlugins</EuiCode> and <EuiCode>uiPlugins</EuiCode>{' '}
options with a single <EuiCode>exclude</EuiCode> parameter passed to{' '}
<EuiCode>getDefaultEuiMarkdownPlugins()</EuiCode>. This will ensure
the syntax won&apos;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.
</p>
),
props: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ export type DefaultEuiMarkdownParsingPlugins = PluggableList;

export const getDefaultEuiMarkdownParsingPlugins = ({
exclude,
}: { exclude?: Array<'tooltip'> } = {}): DefaultEuiMarkdownParsingPlugins => {
}: {
exclude?: Array<'tooltip' | 'line-breaks'>;
} = {}): DefaultEuiMarkdownParsingPlugins => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Not a blocking comment, just me thinking out loud] I wonder if we should extend the exclude list more generally to allow excluding any of the default plugins. I might spike out an attempt at this if you're cool with that!

@cee-chen cee-chen Apr 12, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sakurai-youhei I'm so sorry I kind of just took over your PR 😂 d04966a

Let me know what you think of the changes! I think it makes sense to allow consumers to set configure plugins flexibly where possible.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cee-chen Thank you for giving me such a great opportunity to learn from your code. I shrunk and limited the scope to the specific exclusion because I didn't think I could handle the full scope. The flexibility makes sense to me, too.

const excludeSet = new Set(exclude);
const parsingPlugins: PluggableList = [
[markdown, {}],
[highlight, {}],
[emoji, { emoticon: false }],
[breaks, {}],
[
euiMarkdownLinkValidator,
{
Expand All @@ -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;
};

Expand Down

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ Thank you so much for adding a test file here and for so carefully following our QA steps!! Not all of them apply to every PR but I super appreciate the time you took to check it!

Original file line number Diff line number Diff line change
@@ -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<any[], Settings> | null,
React.ComponentType<any> | 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);
}
}
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];

Expand Down