From 84499baab9995860a62cb5bf2fe01ec6b86b4187 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Wed, 26 Feb 2020 00:58:28 +0300 Subject: [PATCH 1/2] fix(v2): linkify blog posts --- .../website/blog/with reference.md | 5 ++ .../generateBlogFeed.test.ts.snap | 47 ++++++++++++++-- .../__snapshots__/linkify.test.ts.snap | 9 +++ .../src/__tests__/linkify.test.ts | 56 +++++++++++++++++++ .../src/blogUtils.ts | 47 +++++++++++++++- .../src/index.ts | 9 ++- .../src/markdownLoader.ts | 13 ++--- 7 files changed, 172 insertions(+), 14 deletions(-) create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/linkify.test.ts.snap create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md new file mode 100644 index 000000000000..7779964b6023 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md @@ -0,0 +1,5 @@ +--- +title: This post links to another one! +--- + +[Linked post](2018-12-14-Happy-First-Birthday-Slash.md) \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap index f2bb73f5c36e..12562f157196 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap @@ -1,18 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`blogFeed atom can show feed without posts 1`] = `null`; +exports[`blogFeed atom can show feed without posts 1`] = ` +" + + https://docusaurus.io/blog + Hello Blog + 2015-10-25T23:29:00.000Z + https://github.com/jpmonette/feed + + Hello Blog + https://docusaurus.io/image/favicon.ico + Copyright +" +`; exports[`blogFeed atom shows feed item for each post 1`] = ` " https://docusaurus.io/blog Hello Blog - 2019-01-01T00:00:00.000Z + 2020-02-25T20:40:40.817Z https://github.com/jpmonette/feed Hello Blog https://docusaurus.io/image/favicon.ico Copyright + + <![CDATA[This post links to another one!]]> + This post links to another one! + + 2020-02-25T20:40:40.817Z + + <![CDATA[date-matter]]> date-matter @@ -30,7 +49,20 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` " `; -exports[`blogFeed rss can show feed without posts 1`] = `null`; +exports[`blogFeed rss can show feed without posts 1`] = ` +" + + + Hello Blog + https://docusaurus.io/blog + Hello Blog + Sun, 25 Oct 2015 23:29:00 GMT + http://blogs.law.harvard.edu/tech/rss + https://github.com/jpmonette/feed + Copyright + +" +`; exports[`blogFeed rss shows feed item for each post 1`] = ` " @@ -39,10 +71,17 @@ exports[`blogFeed rss shows feed item for each post 1`] = ` Hello Blog https://docusaurus.io/blog Hello Blog - Tue, 01 Jan 2019 00:00:00 GMT + Tue, 25 Feb 2020 20:40:40 GMT http://blogs.law.harvard.edu/tech/rss https://github.com/jpmonette/feed Copyright + + <![CDATA[This post links to another one!]]> + https://docusaurus.io/blog/2020/02/25/with reference + https://docusaurus.io/blog/2020/02/25/with reference + Tue, 25 Feb 2020 20:40:40 GMT + + <![CDATA[date-matter]]> https://docusaurus.io/blog/2019/01/01/date-matter diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/linkify.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/linkify.test.ts.snap new file mode 100644 index 000000000000..eb124f41c131 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/linkify.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`transform to correct link 1`] = ` +"--- +title: This post links to another one! +--- + +[Linked post](/blog/2018/12/14/Happy-First-Birthday-Slash)" +`; diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts new file mode 100644 index 000000000000..f73e9526428e --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import fs from 'fs-extra'; +import path from 'path'; +import {linkify} from '../blogUtils'; +import {BlogPost} from '../types'; + +const sitePath = path.join(__dirname, '__fixtures__', 'website'); +const blogPath = path.join(sitePath, 'blog'); +const pluginDir = 'blog'; +const blogPosts: BlogPost[] = [ + { + id: 'Happy 1st Birthday Slash!', + metadata: { + permalink: '/blog/2018/12/14/Happy-First-Birthday-Slash', + source: path.join( + '@site', + pluginDir, + '2018-12-14-Happy-First-Birthday-Slash.md', + ), + title: 'Happy 1st Birthday Slash!', + description: `pattern name`, + date: new Date('2018-12-14'), + tags: [], + prevItem: { + permalink: '/blog/2019/01/01/date-matter', + title: 'date-matter', + }, + truncated: false, + }, + }, +]; + +const transform = filepath => { + const content = fs.readFileSync(filepath, 'utf-8'); + const transformedContent = linkify(content, sitePath, blogPath, blogPosts); + return [content, transformedContent]; +}; + +test('transform to correct link', () => { + const post = path.join(blogPath, 'with reference.md'); + const [content, transformedContent] = transform(post); + expect(transformedContent).toMatchSnapshot(); + expect(transformedContent).toContain( + '](/blog/2018/12/14/Happy-First-Birthday-Slash', + ); + expect(transformedContent).not.toContain( + '](2018-12-14-Happy-First-Birthday-Slash.md)', + ); + expect(content).not.toEqual(transformedContent); +}); diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index f067a36cde05..92c4a62e0388 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -88,7 +88,7 @@ export async function generateBlogPosts( const {include, routeBasePath, truncateMarker} = options; if (!fs.existsSync(blogDir)) { - return null; + return []; } const {baseUrl = ''} = siteConfig; @@ -152,3 +152,48 @@ export async function generateBlogPosts( return blogPosts; } + +export function linkify( + fileContent: string, + siteDir: string, + blogPath: string, + blogPosts: BlogPost[], +) { + 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 aliasedPostSource = `@site/${path.relative( + siteDir, + path.resolve(blogPath, mdLink), + )}`; + let blogPostPermalink = null; + + blogPosts.forEach(blogPost => { + if (blogPost.metadata.source === aliasedPostSource) { + blogPostPermalink = blogPost.metadata.permalink; + } + }); + + if (blogPostPermalink) { + modifiedLine = modifiedLine.replace(mdLink, blogPostPermalink); + } + + mdMatch = mdRegex.exec(modifiedLine); + } + + return modifiedLine; + }); + + return lines.join('\n'); +} diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index fa36f4314fff..0772a6a79b8a 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -18,6 +18,7 @@ import { TagsModule, BlogPaginated, FeedType, + BlogPost, } from './types'; import { LoadContext, @@ -75,6 +76,7 @@ export default function pluginContentBlog( generatedFilesDir, 'docusaurus-plugin-content-blog', ); + let blogPosts: BlogPost[] = []; return { name: 'docusaurus-plugin-content-blog', @@ -89,8 +91,8 @@ export default function pluginContentBlog( async loadContent() { const {postsPerPage, routeBasePath} = options; - const blogPosts = await generateBlogPosts(contentPath, context, options); - if (!blogPosts) { + blogPosts = await generateBlogPosts(contentPath, context, options); + if (!blogPosts.length) { return null; } @@ -391,7 +393,10 @@ export default function pluginContentBlog( { loader: path.resolve(__dirname, './markdownLoader.js'), options: { + siteDir, + contentPath, truncateMarker, + blogPosts, }, }, ].filter(Boolean) as Loader[], diff --git a/packages/docusaurus-plugin-content-blog/src/markdownLoader.ts b/packages/docusaurus-plugin-content-blog/src/markdownLoader.ts index 2411291690a6..baf152147535 100644 --- a/packages/docusaurus-plugin-content-blog/src/markdownLoader.ts +++ b/packages/docusaurus-plugin-content-blog/src/markdownLoader.ts @@ -5,21 +5,20 @@ * LICENSE file in the root directory of this source tree. */ -const {parseQuery, getOptions} = require('loader-utils'); import {loader} from 'webpack'; -import {truncate} from './blogUtils'; +import {truncate, linkify} from './blogUtils'; +const {parseQuery, getOptions} = require('loader-utils'); export = function(fileString: string) { const callback = this.async(); - - const {truncateMarker}: {truncateMarker: RegExp} = getOptions(this); - - let finalContent = fileString; + const {truncateMarker, siteDir, contentPath, blogPosts} = getOptions(this); + // Linkify posts + let finalContent = linkify(fileString, siteDir, contentPath, blogPosts); // Truncate content if requested (e.g: file.md?truncated=true). const {truncated} = this.resourceQuery && parseQuery(this.resourceQuery); if (truncated) { - finalContent = truncate(fileString, truncateMarker); + finalContent = truncate(finalContent, truncateMarker); } return callback && callback(null, finalContent); From 9bef9ed1835e5d1b743927ec846bb2bb29952507 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Wed, 26 Feb 2020 04:08:33 +0300 Subject: [PATCH 2/2] Fix tests --- .../2018-12-14-Happy-First-Birthday-Slash.md | 5 +++++ .../post.md} | 0 .../generateBlogFeed.test.ts.snap | 18 ++---------------- .../src/__tests__/linkify.test.ts | 6 +++--- 4 files changed, 10 insertions(+), 19 deletions(-) create mode 100644 packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md rename packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/{blog/with reference.md => blog-with-ref/post.md} (100%) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md new file mode 100644 index 000000000000..c04bd7b802a0 --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md @@ -0,0 +1,5 @@ +--- +title: Happy 1st Birthday Slash! +--- + +pattern name diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/post.md similarity index 100% rename from packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/with reference.md rename to packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog-with-ref/post.md diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap index 12562f157196..6cff884a482d 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap @@ -19,19 +19,12 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` https://docusaurus.io/blog Hello Blog - 2020-02-25T20:40:40.817Z + 2019-01-01T00:00:00.000Z https://github.com/jpmonette/feed Hello Blog https://docusaurus.io/image/favicon.ico Copyright - - <![CDATA[This post links to another one!]]> - This post links to another one! - - 2020-02-25T20:40:40.817Z - - <![CDATA[date-matter]]> date-matter @@ -71,17 +64,10 @@ exports[`blogFeed rss shows feed item for each post 1`] = ` Hello Blog https://docusaurus.io/blog Hello Blog - Tue, 25 Feb 2020 20:40:40 GMT + Tue, 01 Jan 2019 00:00:00 GMT http://blogs.law.harvard.edu/tech/rss https://github.com/jpmonette/feed Copyright - - <![CDATA[This post links to another one!]]> - https://docusaurus.io/blog/2020/02/25/with reference - https://docusaurus.io/blog/2020/02/25/with reference - Tue, 25 Feb 2020 20:40:40 GMT - - <![CDATA[date-matter]]> https://docusaurus.io/blog/2019/01/01/date-matter diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts index f73e9526428e..af6535f81d3e 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/linkify.test.ts @@ -11,8 +11,8 @@ import {linkify} from '../blogUtils'; import {BlogPost} from '../types'; const sitePath = path.join(__dirname, '__fixtures__', 'website'); -const blogPath = path.join(sitePath, 'blog'); -const pluginDir = 'blog'; +const blogPath = path.join(sitePath, 'blog-with-ref'); +const pluginDir = 'blog-with-ref'; const blogPosts: BlogPost[] = [ { id: 'Happy 1st Birthday Slash!', @@ -43,7 +43,7 @@ const transform = filepath => { }; test('transform to correct link', () => { - const post = path.join(blogPath, 'with reference.md'); + const post = path.join(blogPath, 'post.md'); const [content, transformedContent] = transform(post); expect(transformedContent).toMatchSnapshot(); expect(transformedContent).toContain(