Skip to content

Commit

Permalink
fix(v2): linkify blog posts (#2326)
Browse files Browse the repository at this point in the history
* fix(v2): linkify blog posts

* Fix tests
  • Loading branch information
lex111 authored Feb 29, 2020
1 parent 84eeb51 commit 3616377
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Happy 1st Birthday Slash!
---

pattern name
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: This post links to another one!
---

[Linked post](2018-12-14-Happy-First-Birthday-Slash.md)
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
// 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`] = `
"<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
<feed xmlns=\\"http://www.w3.org/2005/Atom\\">
<id>https://docusaurus.io/blog</id>
<title>Hello Blog</title>
<updated>2015-10-25T23:29:00.000Z</updated>
<generator>https://github.com/jpmonette/feed</generator>
<link rel=\\"alternate\\" href=\\"https://docusaurus.io/blog\\"/>
<subtitle>Hello Blog</subtitle>
<icon>https://docusaurus.io/image/favicon.ico</icon>
<rights>Copyright</rights>
</feed>"
`;
exports[`blogFeed atom shows feed item for each post 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
Expand Down Expand Up @@ -37,7 +49,20 @@ exports[`blogFeed atom shows feed item for each post 1`] = `
</feed>"
`;
exports[`blogFeed rss can show feed without posts 1`] = `null`;
exports[`blogFeed rss can show feed without posts 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
<rss version=\\"2.0\\">
<channel>
<title>Hello Blog</title>
<link>https://docusaurus.io/blog</link>
<description>Hello Blog</description>
<lastBuildDate>Sun, 25 Oct 2015 23:29:00 GMT</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>https://github.com/jpmonette/feed</generator>
<copyright>Copyright</copyright>
</channel>
</rss>"
`;
exports[`blogFeed rss shows feed item for each post 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
Expand Down
Original file line number Diff line number Diff line change
@@ -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)"
`;
Original file line number Diff line number Diff line change
@@ -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-with-ref');
const pluginDir = 'blog-with-ref';
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, 'post.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);
});
47 changes: 46 additions & 1 deletion packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export async function generateBlogPosts(
const {include, routeBasePath, truncateMarker} = options;

if (!fs.existsSync(blogDir)) {
return null;
return [];
}

const {baseUrl = ''} = siteConfig;
Expand Down Expand Up @@ -156,3 +156,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');
}
9 changes: 7 additions & 2 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
TagsModule,
BlogPaginated,
FeedType,
BlogPost,
} from './types';
import {
LoadContext,
Expand Down Expand Up @@ -75,6 +76,7 @@ export default function pluginContentBlog(
generatedFilesDir,
'docusaurus-plugin-content-blog',
);
let blogPosts: BlogPost[] = [];

return {
name: 'docusaurus-plugin-content-blog',
Expand All @@ -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;
}

Expand Down Expand Up @@ -391,7 +393,10 @@ export default function pluginContentBlog(
{
loader: path.resolve(__dirname, './markdownLoader.js'),
options: {
siteDir,
contentPath,
truncateMarker,
blogPosts,
},
},
].filter(Boolean) as Loader[],
Expand Down
13 changes: 6 additions & 7 deletions packages/docusaurus-plugin-content-blog/src/markdownLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 3616377

Please sign in to comment.