Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(v2): linkify blog posts #2326

Merged
merged 3 commits into from
Feb 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -30,7 +42,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 @@ -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');
}
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