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:
Armano 2021-03-12 15:11:08 +01:00 committed by GitHub
parent bfe52cdae3
commit 2f53b1a895
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 240 additions and 237 deletions

View file

@ -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);
});

View file

@ -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

View file

@ -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;

View file

@ -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,
});

View file

@ -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;
};