mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-24 13:38:02 +02:00
refactor(v2): merge linkify function used in blog and docs and align properties (#4402)
* refactor(v2): merge linkify function used in blog and docs * refactor(v2): rename docsDirPath and docsDirPathLocalized ad update types * refactor(v2): rename blogPostsBySource and update types * improve replaceMarkdownLinks api Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
bfe52cdae3
commit
2f53b1a895
17 changed files with 240 additions and 237 deletions
|
@ -7,7 +7,7 @@
|
|||
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import {linkify, LinkifyParams, getPostsBySource} from '../blogUtils';
|
||||
import {linkify, LinkifyParams, getSourceToPermalink} from '../blogUtils';
|
||||
import {BlogBrokenMarkdownLink, BlogContentPaths, BlogPost} from '../types';
|
||||
|
||||
const siteDir = path.join(__dirname, '__fixtures__', 'website');
|
||||
|
@ -43,10 +43,10 @@ const transform = (filePath: string, options?: Partial<LinkifyParams>) => {
|
|||
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
||||
const transformedContent = linkify({
|
||||
filePath,
|
||||
fileContent,
|
||||
fileString: fileContent,
|
||||
siteDir,
|
||||
contentPaths,
|
||||
blogPostsBySource: getPostsBySource(blogPosts),
|
||||
sourceToPermalink: getSourceToPermalink(blogPosts),
|
||||
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
||||
throw new Error(
|
||||
`Broken markdown link found: ${JSON.stringify(brokenMarkdownLink)}`,
|
||||
|
@ -82,12 +82,12 @@ test('report broken markdown links', () => {
|
|||
expect(onBrokenMarkdownLink).toHaveBeenCalledTimes(2);
|
||||
expect(onBrokenMarkdownLink).toHaveBeenNthCalledWith(1, {
|
||||
filePath: path.resolve(folderPath, filePath),
|
||||
folderPath,
|
||||
contentPaths,
|
||||
link: 'postNotExist1.md',
|
||||
} as BlogBrokenMarkdownLink);
|
||||
expect(onBrokenMarkdownLink).toHaveBeenNthCalledWith(2, {
|
||||
filePath: path.resolve(folderPath, filePath),
|
||||
folderPath,
|
||||
contentPaths,
|
||||
link: './postNotExist2.mdx',
|
||||
} as BlogBrokenMarkdownLink);
|
||||
});
|
||||
|
|
|
@ -9,16 +9,14 @@ import fs from 'fs-extra';
|
|||
import globby from 'globby';
|
||||
import chalk from 'chalk';
|
||||
import path from 'path';
|
||||
import {resolve} from 'url';
|
||||
import readingTime from 'reading-time';
|
||||
import {Feed} from 'feed';
|
||||
import {keyBy} from 'lodash';
|
||||
import {keyBy, mapValues} from 'lodash';
|
||||
import {
|
||||
PluginOptions,
|
||||
BlogPost,
|
||||
DateLink,
|
||||
BlogContentPaths,
|
||||
BlogBrokenMarkdownLink,
|
||||
BlogMarkdownLoaderOptions,
|
||||
} from './types';
|
||||
import {
|
||||
|
@ -31,15 +29,19 @@ import {
|
|||
getDateTimeFormat,
|
||||
} from '@docusaurus/utils';
|
||||
import {LoadContext} from '@docusaurus/types';
|
||||
import {replaceMarkdownLinks} from '@docusaurus/utils/lib/markdownLinks';
|
||||
|
||||
export function truncate(fileString: string, truncateMarker: RegExp): string {
|
||||
return fileString.split(truncateMarker, 1).shift()!;
|
||||
}
|
||||
|
||||
export function getPostsBySource(
|
||||
export function getSourceToPermalink(
|
||||
blogPosts: BlogPost[],
|
||||
): Record<string, BlogPost> {
|
||||
return keyBy(blogPosts, (item) => item.metadata.source);
|
||||
): Record<string, string> {
|
||||
return mapValues(
|
||||
keyBy(blogPosts, (item) => item.metadata.source),
|
||||
(v) => v.metadata.permalink,
|
||||
);
|
||||
}
|
||||
|
||||
// YYYY-MM-DD-{name}.mdx?
|
||||
|
@ -250,73 +252,31 @@ export async function generateBlogPosts(
|
|||
|
||||
export type LinkifyParams = {
|
||||
filePath: string;
|
||||
fileContent: string;
|
||||
fileString: string;
|
||||
} & Pick<
|
||||
BlogMarkdownLoaderOptions,
|
||||
'blogPostsBySource' | 'siteDir' | 'contentPaths' | 'onBrokenMarkdownLink'
|
||||
'sourceToPermalink' | 'siteDir' | 'contentPaths' | 'onBrokenMarkdownLink'
|
||||
>;
|
||||
|
||||
export function linkify({
|
||||
filePath,
|
||||
contentPaths,
|
||||
fileContent,
|
||||
fileString,
|
||||
siteDir,
|
||||
blogPostsBySource,
|
||||
sourceToPermalink,
|
||||
onBrokenMarkdownLink,
|
||||
}: LinkifyParams): string {
|
||||
// TODO temporary, should consider the file being in localized folder!
|
||||
const folderPath = contentPaths.contentPath;
|
||||
|
||||
let fencedBlock = false;
|
||||
const lines = fileContent.split('\n').map((line) => {
|
||||
if (line.trim().startsWith('```')) {
|
||||
fencedBlock = !fencedBlock;
|
||||
}
|
||||
|
||||
if (fencedBlock) {
|
||||
return line;
|
||||
}
|
||||
|
||||
let modifiedLine = line;
|
||||
const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https)([^'")\]\s>]+\.mdx?)/g;
|
||||
let mdMatch = mdRegex.exec(modifiedLine);
|
||||
|
||||
while (mdMatch !== null) {
|
||||
const mdLink = mdMatch[1];
|
||||
|
||||
const aliasedSource = (source: string) =>
|
||||
aliasedSitePath(source, siteDir);
|
||||
|
||||
const blogPost: BlogPost | undefined =
|
||||
blogPostsBySource[aliasedSource(resolve(filePath, mdLink))] ||
|
||||
blogPostsBySource[
|
||||
aliasedSource(`${contentPaths.contentPathLocalized}/${mdLink}`)
|
||||
] ||
|
||||
blogPostsBySource[
|
||||
aliasedSource(`${contentPaths.contentPath}/${mdLink}`)
|
||||
];
|
||||
|
||||
if (blogPost) {
|
||||
modifiedLine = modifiedLine.replace(
|
||||
mdLink,
|
||||
blogPost.metadata.permalink,
|
||||
);
|
||||
} else {
|
||||
const brokenMarkdownLink: BlogBrokenMarkdownLink = {
|
||||
folderPath,
|
||||
filePath,
|
||||
link: mdLink,
|
||||
};
|
||||
onBrokenMarkdownLink(brokenMarkdownLink);
|
||||
}
|
||||
|
||||
mdMatch = mdRegex.exec(modifiedLine);
|
||||
}
|
||||
|
||||
return modifiedLine;
|
||||
const {newContent, brokenMarkdownLinks} = replaceMarkdownLinks({
|
||||
siteDir,
|
||||
fileString,
|
||||
filePath,
|
||||
contentPaths,
|
||||
sourceToPermalink,
|
||||
});
|
||||
|
||||
return lines.join('\n');
|
||||
brokenMarkdownLinks.forEach((l) => onBrokenMarkdownLink(l));
|
||||
|
||||
return newContent;
|
||||
}
|
||||
|
||||
// Order matters: we look in priority in localized folder
|
||||
|
|
|
@ -50,7 +50,7 @@ import {
|
|||
generateBlogFeed,
|
||||
generateBlogPosts,
|
||||
getContentPathList,
|
||||
getPostsBySource,
|
||||
getSourceToPermalink,
|
||||
} from './blogUtils';
|
||||
|
||||
export default function pluginContentBlog(
|
||||
|
@ -416,7 +416,7 @@ export default function pluginContentBlog(
|
|||
siteDir,
|
||||
contentPaths,
|
||||
truncateMarker,
|
||||
blogPostsBySource: getPostsBySource(blogPosts),
|
||||
sourceToPermalink: getSourceToPermalink(blogPosts),
|
||||
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
||||
if (onBrokenMarkdownLinks === 'ignore') {
|
||||
return;
|
||||
|
|
|
@ -12,13 +12,13 @@ import {BlogMarkdownLoaderOptions} from './types';
|
|||
|
||||
const markdownLoader: loader.Loader = function (source) {
|
||||
const filePath = this.resourcePath;
|
||||
const fileContent = source as string;
|
||||
const fileString = source as string;
|
||||
const callback = this.async();
|
||||
const markdownLoaderOptions = getOptions(this) as BlogMarkdownLoaderOptions;
|
||||
|
||||
// Linkify blog posts
|
||||
let finalContent = linkify({
|
||||
fileContent,
|
||||
fileString,
|
||||
filePath,
|
||||
...markdownLoaderOptions,
|
||||
});
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export type BlogContentPaths = {
|
||||
contentPath: string;
|
||||
contentPathLocalized: string;
|
||||
};
|
||||
import {
|
||||
BrokenMarkdownLink,
|
||||
ContentPaths,
|
||||
} from '@docusaurus/utils/lib/markdownLinks';
|
||||
|
||||
export type BlogContentPaths = ContentPaths;
|
||||
|
||||
export interface BlogContent {
|
||||
blogPosts: BlogPost[];
|
||||
|
@ -142,15 +144,11 @@ export interface TagModule {
|
|||
permalink: string;
|
||||
}
|
||||
|
||||
export type BlogBrokenMarkdownLink = {
|
||||
folderPath: string;
|
||||
filePath: string;
|
||||
link: string;
|
||||
};
|
||||
export type BlogBrokenMarkdownLink = BrokenMarkdownLink<BlogContentPaths>;
|
||||
export type BlogMarkdownLoaderOptions = {
|
||||
siteDir: string;
|
||||
contentPaths: BlogContentPaths;
|
||||
truncateMarker: RegExp;
|
||||
blogPostsBySource: Record<string, BlogPost>;
|
||||
sourceToPermalink: Record<string, string>;
|
||||
onBrokenMarkdownLink: (brokenMarkdownLink: BlogBrokenMarkdownLink) => void;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue