feat: link in shortcode (#707)
This commit is contained in:
committed by
GitHub
parent
6be11c749e
commit
0fae2ce73d
@ -9,7 +9,10 @@ import { markdownToSlate } from '../useMarkdownToSlate';
|
||||
import type { SerializationTestData } from '../../tests-util/serializationTests.util';
|
||||
import type { UseMarkdownToSlateOptions } from '../useMarkdownToSlate';
|
||||
|
||||
jest.unmock('remark-gfm');
|
||||
jest.unmock('mdast-util-gfm-footnote');
|
||||
jest.unmock('mdast-util-gfm-table');
|
||||
jest.unmock('mdast-util-gfm-task-list-item');
|
||||
jest.unmock('micromark-extension-gfm');
|
||||
jest.unmock('remark-mdx');
|
||||
jest.unmock('remark-parse');
|
||||
jest.unmock('unified');
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ELEMENT_PARAGRAPH } from '@udecode/plate';
|
||||
import { useEffect, useState } from 'react';
|
||||
import gfm from 'remark-gfm';
|
||||
import mdx from 'remark-mdx';
|
||||
import markdown from 'remark-parse';
|
||||
import { unified } from 'unified';
|
||||
|
||||
import { getShortcodes } from '../../../../lib/registry';
|
||||
import gfm from '../serialization/gfm';
|
||||
import toSlatePlugin from '../serialization/slate/toSlatePlugin';
|
||||
|
||||
import type { ShortcodeConfig } from '../../../../interface';
|
||||
|
@ -0,0 +1,61 @@
|
||||
import { gfmFootnoteFromMarkdown, gfmFootnoteToMarkdown } from 'mdast-util-gfm-footnote';
|
||||
import {
|
||||
gfmStrikethroughFromMarkdown,
|
||||
gfmStrikethroughToMarkdown,
|
||||
} from 'mdast-util-gfm-strikethrough';
|
||||
import { gfmTableFromMarkdown, gfmTableToMarkdown } from 'mdast-util-gfm-table';
|
||||
import {
|
||||
gfmTaskListItemFromMarkdown,
|
||||
gfmTaskListItemToMarkdown,
|
||||
} from 'mdast-util-gfm-task-list-item';
|
||||
import { gfmFootnote } from 'micromark-extension-gfm-footnote';
|
||||
import { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough';
|
||||
import { gfmTable } from 'micromark-extension-gfm-table';
|
||||
import { gfmTaskListItem } from 'micromark-extension-gfm-task-list-item';
|
||||
import { combineExtensions } from 'micromark-util-combine-extensions';
|
||||
|
||||
import type { Root } from 'mdast';
|
||||
import type { Plugin, Processor } from 'unified';
|
||||
|
||||
function gfmFromMarkdown() {
|
||||
return [
|
||||
gfmFootnoteFromMarkdown(),
|
||||
gfmStrikethroughFromMarkdown,
|
||||
gfmTableFromMarkdown,
|
||||
gfmTaskListItemFromMarkdown,
|
||||
];
|
||||
}
|
||||
|
||||
function gfmToMarkdown() {
|
||||
return {
|
||||
extensions: [
|
||||
gfmFootnoteToMarkdown(),
|
||||
gfmStrikethroughToMarkdown,
|
||||
gfmTableToMarkdown({}),
|
||||
gfmTaskListItemToMarkdown,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function gfm() {
|
||||
return combineExtensions([gfmFootnote(), gfmStrikethrough({}), gfmTable, gfmTaskListItem]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin to support GFM (footnotes, strikethrough, tables, tasklists).
|
||||
*/
|
||||
const remarkGfm: Plugin<void[], Root> = function (this: Processor) {
|
||||
const data = this.data();
|
||||
|
||||
add('micromarkExtensions', gfm());
|
||||
add('fromMarkdownExtensions', gfmFromMarkdown());
|
||||
add('toMarkdownExtensions', gfmToMarkdown());
|
||||
|
||||
function add(field: string, value: unknown) {
|
||||
const list = (data[field] ? data[field] : (data[field] = [])) as unknown[];
|
||||
|
||||
list.push(value);
|
||||
}
|
||||
};
|
||||
|
||||
export default remarkGfm;
|
@ -0,0 +1,166 @@
|
||||
import { autoLinkToSlate } from '../autoLinkUrls';
|
||||
|
||||
import type { MdastNode } from '../ast-types';
|
||||
|
||||
describe('processShortcodeConfig', () => {
|
||||
describe('autoLinkToSlate', () => {
|
||||
it('converts url to anchor node', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: 'https://www.youtube.com/watch?v=p6h-rYSVX90' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('does not convert url in shortcode node', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['https://www.youtube.com/watch?v=p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{ type: 'text', value: 'https://www.youtube.com/watch?v=p6h-rYSVX90' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['https://www.youtube.com/watch?v=p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts url with text before', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: 'Text before https://www.youtube.com/watch?v=p6h-rYSVX90' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts url with text after', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: 'https://www.youtube.com/watch?v=p6h-rYSVX90 and text after' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and text after',
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts url with text before and after', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before https://www.youtube.com/watch?v=p6h-rYSVX90 and text after',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and text after',
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts multiple urls', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value:
|
||||
'Text before https://www.youtube.com/watch?v=p6h-rYSVX90 and https://www.youtube.com/watch?v=p6h-rYSVX90 text after',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and ',
|
||||
},
|
||||
{
|
||||
type: 'a',
|
||||
url: 'https://www.youtube.com/watch?v=p6h-rYSVX90',
|
||||
children: [{ text: 'https://www.youtube.com/watch?v=p6h-rYSVX90' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' text after',
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('does not convert plain text', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Some text about something going on somewhere',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Some text about something going on somewhere',
|
||||
},
|
||||
];
|
||||
|
||||
expect(autoLinkToSlate(nodes)).toEqual(slate);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,7 +1,265 @@
|
||||
import { processShortcodeConfigToMdx } from '../processShortcodeConfig';
|
||||
import {
|
||||
processShortcodeConfigToMdx,
|
||||
processShortcodeConfigsToSlate,
|
||||
} from '../processShortcodeConfig';
|
||||
import { testShortcodeConfigs } from '../../../tests-util/serializationTests.util';
|
||||
|
||||
import type { MdastNode } from '../ast-types';
|
||||
|
||||
describe('processShortcodeConfig', () => {
|
||||
describe('processShortcodeConfigsToSlate', () => {
|
||||
it('converts shortcode', () => {
|
||||
const nodes: MdastNode[] = [{ type: 'text', value: '[youtube|p6h-rYSVX90]' }];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts shortcode with no args', () => {
|
||||
const nodes: MdastNode[] = [{ type: 'text', value: '[youtube]' }];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: [],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts shortcode with multiple args', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: '[youtube|p6h-rYSVX90|somethingElse|andOneMore]' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90', 'somethingElse', 'andOneMore'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts shortcode with text before', () => {
|
||||
const nodes: MdastNode[] = [{ type: 'text', value: 'Text before [youtube|p6h-rYSVX90]' }];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts shortcode with text after', () => {
|
||||
const nodes: MdastNode[] = [{ type: 'text', value: '[youtube|p6h-rYSVX90] and text after' }];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and text after',
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts shortcode with text before and after', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: 'Text before [youtube|p6h-rYSVX90] and text after' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and text after',
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts multiple shortcodes', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before [youtube|p6h-rYSVX90] and {{< twitter 917359331535966209 >}}',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'twitter',
|
||||
args: ['917359331535966209'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('converts multiple of the same shortcodes', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value:
|
||||
'Text before [youtube|p6h-rYSVX90], [youtube|p6h-rYSVX90], {{< twitter 917359331535966209 >}} and [youtube|p6h-rYSVX90]',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ', ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ', ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'twitter',
|
||||
args: ['917359331535966209'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' and ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('does not convert unrecognized shortcode', () => {
|
||||
const nodes: MdastNode[] = [{ type: 'text', value: '[someOtherShortcode|andstuff]' }];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: '[someOtherShortcode|andstuff]',
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('does not convert unrecognized shortcode surrounded by recognized shortcodes', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value:
|
||||
'Text before [youtube|p6h-rYSVX90], [someOtherShortcode|andstuff] and {{< twitter 917359331535966209 >}}',
|
||||
},
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Text before ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'youtube',
|
||||
args: ['p6h-rYSVX90'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ', [someOtherShortcode|andstuff] and ',
|
||||
},
|
||||
{
|
||||
type: 'shortcode',
|
||||
shortcode: 'twitter',
|
||||
args: ['917359331535966209'],
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
|
||||
it('does not convert plain text', () => {
|
||||
const nodes: MdastNode[] = [
|
||||
{ type: 'text', value: 'Some text about something going on somewhere' },
|
||||
];
|
||||
const slate: MdastNode[] = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'Some text about something going on somewhere',
|
||||
},
|
||||
];
|
||||
|
||||
expect(processShortcodeConfigsToSlate(testShortcodeConfigs, nodes)).toEqual(slate);
|
||||
});
|
||||
});
|
||||
|
||||
describe('processShortcodeConfigToMdx', () => {
|
||||
it('converts to mdx', () => {
|
||||
const markdown = '[youtube|p6h-rYSVX90]';
|
||||
@ -25,21 +283,21 @@ describe('processShortcodeConfig', () => {
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('shortcode with text before', () => {
|
||||
it('converts shortcode with text before', () => {
|
||||
const markdown = 'Text before [youtube|p6h-rYSVX90]';
|
||||
const mdx = 'Text before <Shortcode shortcode="youtube" args={[\'p6h-rYSVX90\']} />';
|
||||
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('shortcode with text after', () => {
|
||||
it('converts shortcode with text after', () => {
|
||||
const markdown = '[youtube|p6h-rYSVX90] and text after';
|
||||
const mdx = '<Shortcode shortcode="youtube" args={[\'p6h-rYSVX90\']} /> and text after';
|
||||
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('shortcode with text before and after', () => {
|
||||
it('converts shortcode with text before and after', () => {
|
||||
const markdown = 'Text before [youtube|p6h-rYSVX90] and text after';
|
||||
const mdx =
|
||||
'Text before <Shortcode shortcode="youtube" args={[\'p6h-rYSVX90\']} /> and text after';
|
||||
@ -47,7 +305,7 @@ describe('processShortcodeConfig', () => {
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('multiple shortcodes', () => {
|
||||
it('converts multiple shortcodes', () => {
|
||||
const markdown = 'Text before [youtube|p6h-rYSVX90] and {{< twitter 917359331535966209 >}}';
|
||||
const mdx =
|
||||
'Text before <Shortcode shortcode="youtube" args={[\'p6h-rYSVX90\']} /> and <Shortcode shortcode="twitter" args={[\'917359331535966209\']} />';
|
||||
@ -55,7 +313,7 @@ describe('processShortcodeConfig', () => {
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('multiple of the same shortcodes', () => {
|
||||
it('converts multiple of the same shortcodes', () => {
|
||||
const markdown =
|
||||
'Text before [youtube|p6h-rYSVX90], [youtube|p6h-rYSVX90], {{< twitter 917359331535966209 >}} and [youtube|p6h-rYSVX90]';
|
||||
const mdx =
|
||||
@ -64,14 +322,14 @@ describe('processShortcodeConfig', () => {
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('unrecognized shortcode', () => {
|
||||
it('does not convert unrecognized shortcode', () => {
|
||||
const markdown = '[someOtherShortcode|andstuff]';
|
||||
const mdx = '[someOtherShortcode|andstuff]';
|
||||
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('unrecognized shortcode surrounded by recognized shortcodes', () => {
|
||||
it('does not convert unrecognized shortcode surrounded by recognized shortcodes', () => {
|
||||
const markdown =
|
||||
'Text before [youtube|p6h-rYSVX90], [someOtherShortcode|andstuff] and {{< twitter 917359331535966209 >}}';
|
||||
const mdx =
|
||||
@ -80,7 +338,7 @@ describe('processShortcodeConfig', () => {
|
||||
expect(processShortcodeConfigToMdx(testShortcodeConfigs, markdown)).toBe(mdx);
|
||||
});
|
||||
|
||||
it('plain text', () => {
|
||||
it('does not convert plain text', () => {
|
||||
const markdown = 'Some text about something going on somewhere';
|
||||
const mdx = 'Some text about something going on somewhere';
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
import {
|
||||
deserializationOnlyTestData,
|
||||
runSerializationTests,
|
||||
testShortcodeConfigs as shortcodeConfigs,
|
||||
} from '../../../tests-util/serializationTests.util';
|
||||
import { slateCompiler } from '../toSlatePlugin';
|
||||
|
||||
import type { SerializationTestData } from '../../../tests-util/serializationTests.util';
|
||||
import type { MdastNode } from '../ast-types';
|
||||
|
||||
async function expectNodes(
|
||||
mdast: MdastNode,
|
||||
useMdx: boolean,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
children: any[],
|
||||
) {
|
||||
const compiler = slateCompiler({ useMdx, shortcodeConfigs });
|
||||
|
||||
expect(compiler(mdast)).toEqual(children);
|
||||
}
|
||||
|
||||
function testRunner(key: string, mode: 'markdown' | 'mdx' | 'both', data: SerializationTestData) {
|
||||
it(`deserializes ${key}`, async () => {
|
||||
await expectNodes(data.mdast, mode === 'mdx', data.slate);
|
||||
});
|
||||
}
|
||||
|
||||
describe('markdownToSlate', () => {
|
||||
runSerializationTests(testRunner);
|
||||
runSerializationTests(testRunner, deserializationOnlyTestData);
|
||||
});
|
@ -0,0 +1,45 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
|
||||
import { isNotEmpty } from '@staticcms/core/lib/util/string.util';
|
||||
import { NodeTypes } from './ast-types';
|
||||
|
||||
import type { BaseMdastNode, MdastNode } from './ast-types';
|
||||
|
||||
export function autoLinkToSlate(nodes: BaseMdastNode[]) {
|
||||
const output: MdastNode[] = [];
|
||||
|
||||
for (const node of nodes) {
|
||||
if (node.type === 'text' && node.value) {
|
||||
const regex =
|
||||
/([\w\W]*?)((?:http(?:s)?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_+.~#?&//=]*))([\w\W]*)/g;
|
||||
let matches: RegExpExecArray | null;
|
||||
let rest = node.value;
|
||||
while (isNotEmpty(rest) && (matches = regex.exec(rest)) !== null && matches.length === 4) {
|
||||
if (isNotEmpty(matches[1])) {
|
||||
output.push({
|
||||
type: 'text',
|
||||
value: matches[1],
|
||||
});
|
||||
}
|
||||
output.push({
|
||||
type: NodeTypes.link,
|
||||
url: matches[2],
|
||||
children: [{ text: matches[2] }],
|
||||
});
|
||||
rest = matches[3];
|
||||
regex.lastIndex = 0;
|
||||
}
|
||||
if (isNotEmpty(rest)) {
|
||||
output.push({
|
||||
type: 'text',
|
||||
value: rest,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
output.push(node);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
@ -2,7 +2,8 @@
|
||||
import { ELEMENT_PARAGRAPH } from '@udecode/plate';
|
||||
|
||||
import { LIST_TYPES, MarkNodeTypes, NodeTypes } from './ast-types';
|
||||
import { processShortcodeConfigToSlate } from './processShortcodeConfig';
|
||||
import { autoLinkToSlate } from './autoLinkUrls';
|
||||
import { processShortcodeConfigsToSlate } from './processShortcodeConfig';
|
||||
|
||||
import type { ShortcodeConfig } from '@staticcms/core/interface';
|
||||
import type { MdBlockElement } from '@staticcms/markdown';
|
||||
@ -350,11 +351,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
|
||||
return { text: '' };
|
||||
}
|
||||
|
||||
let nodes: MdastNode[] = [node];
|
||||
|
||||
for (const shortcode in shortcodeConfigs) {
|
||||
nodes = processShortcodeConfigToSlate(shortcode, shortcodeConfigs[shortcode], nodes);
|
||||
}
|
||||
const nodes = autoLinkToSlate(processShortcodeConfigsToSlate(shortcodeConfigs, [node]));
|
||||
|
||||
return nodes.map(node => (node.type === 'text' ? { text: node.value ?? '' } : node));
|
||||
|
||||
|
@ -19,7 +19,7 @@ function createShortcodeRegex(name: string, config: ShortcodeConfig) {
|
||||
)}?([\\w\\W]*?)${cleanRegex(config.closeTag)}`;
|
||||
}
|
||||
|
||||
export function processShortcodeConfigToSlate(
|
||||
function processShortcodeConfigToSlate(
|
||||
name: string,
|
||||
config: ShortcodeConfig,
|
||||
nodes: BaseMdastNode[],
|
||||
@ -68,6 +68,19 @@ export function processShortcodeConfigToSlate(
|
||||
return output;
|
||||
}
|
||||
|
||||
export function processShortcodeConfigsToSlate(
|
||||
configs: Record<string, ShortcodeConfig>,
|
||||
nodes: BaseMdastNode[],
|
||||
) {
|
||||
let finalNodes: MdastNode[] = nodes;
|
||||
|
||||
for (const shortcode in configs) {
|
||||
finalNodes = processShortcodeConfigToSlate(shortcode, configs[shortcode], finalNodes);
|
||||
}
|
||||
|
||||
return finalNodes;
|
||||
}
|
||||
|
||||
export function processShortcodeConfigToMdx(
|
||||
configs: Record<string, ShortcodeConfig>,
|
||||
markdown: string,
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user