mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-18 11:36:53 +02:00
fix(v2): remove Markdown syntax from excerpt (#2701)
* fix(v2): remove Markdown syntax from excerpt * Update snapshots * Use Remark * Switch to own solution
This commit is contained in:
parent
c7baa125e6
commit
da0f865831
4 changed files with 112 additions and 20 deletions
|
@ -303,7 +303,7 @@ describe('versioned website', () => {
|
||||||
permalink: '/docs/next/foo/bar',
|
permalink: '/docs/next/foo/bar',
|
||||||
source: path.join('@site', routeBasePath, 'foo', 'bar.md'),
|
source: path.join('@site', routeBasePath, 'foo', 'bar.md'),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
description: 'This is `next` version of bar.',
|
description: 'This is next version of bar.',
|
||||||
version: 'next',
|
version: 'next',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
next: {
|
next: {
|
||||||
|
@ -316,7 +316,7 @@ describe('versioned website', () => {
|
||||||
permalink: '/docs/next/hello',
|
permalink: '/docs/next/hello',
|
||||||
source: path.join('@site', routeBasePath, 'hello.md'),
|
source: path.join('@site', routeBasePath, 'hello.md'),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello `next` !',
|
description: 'Hello next !',
|
||||||
version: 'next',
|
version: 'next',
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
previous: {
|
previous: {
|
||||||
|
@ -334,7 +334,7 @@ describe('versioned website', () => {
|
||||||
'hello.md',
|
'hello.md',
|
||||||
),
|
),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello `1.0.1` !',
|
description: 'Hello 1.0.1 !',
|
||||||
version: '1.0.1',
|
version: '1.0.1',
|
||||||
sidebar: 'version-1.0.1/docs',
|
sidebar: 'version-1.0.1/docs',
|
||||||
previous: {
|
previous: {
|
||||||
|
@ -354,7 +354,7 @@ describe('versioned website', () => {
|
||||||
),
|
),
|
||||||
title: 'baz',
|
title: 'baz',
|
||||||
description:
|
description:
|
||||||
'Baz `1.0.0` ! This will be deleted in next subsequent versions.',
|
'Baz 1.0.0 ! This will be deleted in next subsequent versions.',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
sidebar: 'version-1.0.0/docs',
|
sidebar: 'version-1.0.0/docs',
|
||||||
next: {
|
next: {
|
||||||
|
|
|
@ -84,7 +84,7 @@ describe('simple site', () => {
|
||||||
title: 'baz',
|
title: 'baz',
|
||||||
editUrl:
|
editUrl:
|
||||||
'https://github.com/facebook/docusaurus/edit/master/website/docs/foo/baz.md',
|
'https://github.com/facebook/docusaurus/edit/master/website/docs/foo/baz.md',
|
||||||
description: '## Images',
|
description: 'Images',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/next/foo/bar',
|
permalink: '/docs/next/foo/bar',
|
||||||
source: path.join('@site', routeBasePath, sourceA),
|
source: path.join('@site', routeBasePath, sourceA),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
description: 'This is `next` version of bar.',
|
description: 'This is next version of bar.',
|
||||||
version: 'next',
|
version: 'next',
|
||||||
});
|
});
|
||||||
expect(dataB).toEqual({
|
expect(dataB).toEqual({
|
||||||
|
@ -236,7 +236,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/next/hello',
|
permalink: '/docs/next/hello',
|
||||||
source: path.join('@site', routeBasePath, sourceB),
|
source: path.join('@site', routeBasePath, sourceB),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello `next` !',
|
description: 'Hello next !',
|
||||||
version: 'next',
|
version: 'next',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -286,7 +286,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/1.0.0/foo/bar',
|
permalink: '/docs/1.0.0/foo/bar',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceA),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceA),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
description: 'Bar `1.0.0` !',
|
description: 'Bar 1.0.0 !',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
});
|
});
|
||||||
expect(dataB).toEqual({
|
expect(dataB).toEqual({
|
||||||
|
@ -294,7 +294,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/1.0.0/hello',
|
permalink: '/docs/1.0.0/hello',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceB),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceB),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello `1.0.0` !',
|
description: 'Hello 1.0.0 !',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
});
|
});
|
||||||
expect(dataC).toEqual({
|
expect(dataC).toEqual({
|
||||||
|
@ -302,7 +302,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/foo/bar',
|
permalink: '/docs/foo/bar',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceC),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceC),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
description: 'Bar `1.0.1` !',
|
description: 'Bar 1.0.1 !',
|
||||||
version: '1.0.1',
|
version: '1.0.1',
|
||||||
});
|
});
|
||||||
expect(dataD).toEqual({
|
expect(dataD).toEqual({
|
||||||
|
@ -310,7 +310,7 @@ describe('versioned site', () => {
|
||||||
permalink: '/docs/hello',
|
permalink: '/docs/hello',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceD),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceD),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello `1.0.1` !',
|
description: 'Hello 1.0.1 !',
|
||||||
version: '1.0.1',
|
version: '1.0.1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
posixPath,
|
posixPath,
|
||||||
objectWithKeySorted,
|
objectWithKeySorted,
|
||||||
aliasedSitePath,
|
aliasedSitePath,
|
||||||
|
createExcerpt,
|
||||||
} from '../index';
|
} from '../index';
|
||||||
|
|
||||||
describe('load utils', () => {
|
describe('load utils', () => {
|
||||||
|
@ -292,4 +293,60 @@ describe('load utils', () => {
|
||||||
`"Url must be a string. Received undefined"`,
|
`"Url must be a string. Received undefined"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('createExcerpt', () => {
|
||||||
|
const asserts = [
|
||||||
|
// Regular content
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.
|
||||||
|
|
||||||
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
||||||
|
`,
|
||||||
|
output:
|
||||||
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.',
|
||||||
|
},
|
||||||
|
// Content with imports declarations and Markdown markup, as well as Emoji
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
import Component from '@site/src/components/Component';
|
||||||
|
import Component from '@site/src/components/Component'
|
||||||
|
|
||||||
|
Lorem **ipsum** dolor sit \`amet\`, consectetur _adipiscing_ elit. [**Vestibulum**](https://wiktionary.org/wiki/vestibulum) ex urna, ~molestie~ et sagittis ut, varius ac justo :wink:.
|
||||||
|
|
||||||
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
||||||
|
`,
|
||||||
|
output:
|
||||||
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.',
|
||||||
|
},
|
||||||
|
// Content beginning with admonitions
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
import Component from '@site/src/components/Component'
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
||||||
|
`,
|
||||||
|
output: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||||
|
},
|
||||||
|
// Content beginning with heading
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
## Lorem ipsum dolor sit amet
|
||||||
|
|
||||||
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
||||||
|
`,
|
||||||
|
output: 'Lorem ipsum dolor sit amet',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
asserts.forEach((testCase) => {
|
||||||
|
expect(createExcerpt(testCase.input)).toEqual(testCase.output);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -185,6 +185,49 @@ export function getSubFolder(file: string, refDir: string): string | null {
|
||||||
// Regex for an import statement.
|
// Regex for an import statement.
|
||||||
const importRegexString = '^(.*import){1}(.+){0,1}\\s[\'"](.+)[\'"];?';
|
const importRegexString = '^(.*import){1}(.+){0,1}\\s[\'"](.+)[\'"];?';
|
||||||
|
|
||||||
|
export function createExcerpt(fileString: string): string | undefined {
|
||||||
|
let fileContent = fileString.trimLeft();
|
||||||
|
|
||||||
|
if (RegExp(importRegexString).test(fileContent)) {
|
||||||
|
fileContent = fileContent
|
||||||
|
.replace(RegExp(importRegexString, 'gm'), '')
|
||||||
|
.trimLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileLines = fileContent.split('\n');
|
||||||
|
|
||||||
|
for (let fileLine of fileLines) {
|
||||||
|
const cleanedLine = fileLine
|
||||||
|
// Remove HTML tags.
|
||||||
|
.replace(/<[^>]*>/g, '')
|
||||||
|
// Remove ATX-style headers.
|
||||||
|
.replace(/^\#{1,6}\s*([^#]*)\s*(\#{1,6})?/gm, '$1')
|
||||||
|
// Remove emphasis and strikethroughs.
|
||||||
|
.replace(/([\*_~]{1,3})(\S.*?\S{0,1})\1/g, '$2')
|
||||||
|
// Remove inline links.
|
||||||
|
.replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
|
||||||
|
// Remove inline code.
|
||||||
|
.replace(/`(.+?)`/g, '$1')
|
||||||
|
// Remove images.
|
||||||
|
.replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, '')
|
||||||
|
// Remove blockquotes.
|
||||||
|
.replace(/^\s{0,3}>\s?/g, '')
|
||||||
|
// Remove footnotes.
|
||||||
|
.replace(/\[\^.+?\](\: .*?$)?/g, '')
|
||||||
|
// Remove admonition definition.
|
||||||
|
.replace(/(:{3}.*)/, '')
|
||||||
|
// Remove Emoji names within colons include preceding whitespace.
|
||||||
|
.replace(/\s?(:(::|[^:\n])+:)/g, '')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
if (cleanedLine) {
|
||||||
|
return cleanedLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function parse(
|
export function parse(
|
||||||
fileString: string,
|
fileString: string,
|
||||||
): {
|
): {
|
||||||
|
@ -196,18 +239,10 @@ export function parse(
|
||||||
} {
|
} {
|
||||||
const options: {} = {
|
const options: {} = {
|
||||||
excerpt: (file: matter.GrayMatterFile<string>): void => {
|
excerpt: (file: matter.GrayMatterFile<string>): void => {
|
||||||
let fileContent = file.content.trimLeft();
|
|
||||||
|
|
||||||
// Hacky way of stripping out import statements from the excerpt
|
// Hacky way of stripping out import statements from the excerpt
|
||||||
// TODO: Find a better way to do so, possibly by compiling the Markdown content,
|
// TODO: Find a better way to do so, possibly by compiling the Markdown content,
|
||||||
// stripping out HTML tags and obtaining the first line.
|
// stripping out HTML tags and obtaining the first line.
|
||||||
if (RegExp(importRegexString).test(fileContent)) {
|
file.excerpt = createExcerpt(file.content);
|
||||||
fileContent = fileContent
|
|
||||||
.replace(RegExp(importRegexString, 'gm'), '')
|
|
||||||
.trimLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
file.excerpt = fileContent.split('\n', 1).shift();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue