fix(content-blog): generate feed by reading build output (#6454)

This commit is contained in:
Joshua Chen 2022-01-26 23:54:15 +08:00 committed by GitHub
parent ebd5340205
commit 76a8d5f38a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 364 additions and 249 deletions

View file

@ -1,133 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {mdxToHtml} from '../mdxUtils';
describe('mdxToHtml', () => {
test('work with simple markdown', () => {
const mdxString = `
# title
title text **bold**
## subtitle
subtitle text *italic*
> Quote
`;
expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(
`"<h1>title</h1><p>title text <strong>bold</strong></p><h2>subtitle</h2><p>subtitle text <em>italic</em></p><blockquote><p>Quote</p></blockquote>"`,
);
});
test('work with MDX imports', () => {
const mdxString = `
# title
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
text
`;
expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(
`"<h1>title</h1><p>text</p>"`,
);
});
test('work with MDX exports', () => {
const mdxString = `
# title
export const someExport = 42
export const MyLocalComponent = () => "result"
export const toc = [
{id: "title",label: "title"}
]
text
`;
expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(
`"<h1>title</h1><p>text</p>"`,
);
});
test('work with MDX Tabs', () => {
const mdxString = `
# title
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs>
<TabItem value="apple" label="Apple">
This is an apple 🍎
</TabItem>
<TabItem value="orange" label="Orange">
This is an orange 🍊
</TabItem>
</Tabs>
text
`;
// TODO this is not an ideal behavior!
// There is a warning "Component TabItem was not imported, exported, or provided by MDXProvider as global scope"
// Theme + MDX config should provide a list of React components to put in MDX scope
expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(
`"<h1>title</h1><div><div value=\\"apple\\" label=\\"Apple\\">This is an apple 🍎</div><div value=\\"orange\\" label=\\"Orange\\">This is an orange 🍊</div></div><p>text</p>"`,
);
});
test('work with MDX Tabs with ```mdx-code-block', () => {
const mdxString = `
# title
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
\`\`\`mdx-code-block
<Tabs>
<TabItem value="apple" label="Apple">
This is an apple 🍎
</TabItem>
<TabItem value="orange" label="Orange">
This is an orange 🍊
</TabItem>
</Tabs>
\`\`\`
text
`;
// TODO bad behavior!
// ```mdx-code-block should be unwrapped and inner MDX content should be evaluated
expect(mdxToHtml(mdxString)).toMatchInlineSnapshot(`
"<h1>title</h1><pre><code class=\\"language-mdx-code-block\\">&lt;Tabs&gt;
&lt;TabItem value=&quot;apple&quot; label=&quot;Apple&quot;&gt;
This is an apple 🍎
&lt;/TabItem&gt;
&lt;TabItem value=&quot;orange&quot; label=&quot;Orange&quot;&gt;
This is an orange 🍊
&lt;/TabItem&gt;
&lt;/Tabs&gt;
</code></pre><p>text</p>"
`);
});
});

View file

@ -23,7 +23,6 @@ import {simpleHash, docuHash} from './hashUtils';
import {DEFAULT_PLUGIN_ID} from './constants';
export * from './constants';
export * from './mdxUtils';
export * from './urlUtils';
export * from './tags';
export * from './markdownParser';
@ -210,6 +209,39 @@ export function getPluginI18nPath({
);
}
/**
* @param permalink The URL that the HTML file corresponds to, without base URL
* @param outDir Full path to the output directory
* @param trailingSlash The site config option. If provided, only one path will be read.
* @returns This returns a buffer, which you have to decode string yourself if
* needed. (Not always necessary since the output isn't for human consumption
* anyways, and most HTML manipulation libs accept buffers)
*/
export async function readOutputHTMLFile(
permalink: string,
outDir: string,
trailingSlash: boolean | undefined,
): Promise<Buffer> {
const withTrailingSlashPath = path.join(outDir, permalink, 'index.html');
const withoutTrailingSlashPath = path.join(outDir, `${permalink}.html`);
if (trailingSlash) {
return fs.readFile(withTrailingSlashPath);
} else if (trailingSlash === false) {
return fs.readFile(withoutTrailingSlashPath);
} else {
const HTMLPath = await findAsyncSequential(
[withTrailingSlashPath, withoutTrailingSlashPath],
fs.pathExists,
);
if (!HTMLPath) {
throw new Error(
`Expected output HTML file to be found at ${withTrailingSlashPath}`,
);
}
return fs.readFile(HTMLPath);
}
}
export async function mapAsyncSequential<T, R>(
array: T[],
action: (t: T) => Promise<R>,

View file

@ -1,32 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import MDX from '@mdx-js/runtime';
import removeImports from 'remark-mdx-remove-imports';
import removeExports from 'remark-mdx-remove-exports';
/**
* Transform mdx text to plain html text
* Initially created to convert MDX blog posts to HTML for the RSS feed
* without import/export nodes
*
* TODO not ideal implementation, won't work well with MDX elements!
* TODO theme+global site config should be able to declare MDX comps in scope for rendering the RSS feeds
* see also https://github.com/facebook/docusaurus/issues/4625
*/
export function mdxToHtml(
mdxStr: string,
// TODO allow providing components/scope here, see https://github.com/mdx-js/mdx/tree/v1.6.13/packages/runtime
): string {
return ReactDOMServer.renderToString(
React.createElement(MDX, {remarkPlugins: [removeImports, removeExports]}, [
mdxStr,
]),
);
}