diff --git a/packages/docusaurus/lib/theme/BlogPage/index.js b/packages/docusaurus-plugin-content-blog/components/BlogPage/index.js
similarity index 74%
rename from packages/docusaurus/lib/theme/BlogPage/index.js
rename to packages/docusaurus-plugin-content-blog/components/BlogPage/index.js
index d024db3463..16d2ab08d3 100644
--- a/packages/docusaurus/lib/theme/BlogPage/index.js
+++ b/packages/docusaurus-plugin-content-blog/components/BlogPage/index.js
@@ -6,11 +6,10 @@
*/
import React, {useContext} from 'react';
-import Link from '@docusaurus/Link';
import Head from '@docusaurus/Head';
import Layout from '@theme/Layout'; // eslint-disable-line
-
import DocusaurusContext from '@docusaurus/context';
+import Post from '../Post';
function BlogPage(props) {
const context = useContext(DocusaurusContext);
@@ -30,15 +29,13 @@ function BlogPage(props) {
{language && }
-
- {posts.map(metadata => (
-
- {metadata.permalink}
-
- ))}
-
- {BlogPosts.map((BlogPost, index) => (
-
+ {BlogPosts.map((PostContent, index) => (
+
+
+
))}
diff --git a/packages/docusaurus-plugin-content-blog/components/BlogPost/index.js b/packages/docusaurus-plugin-content-blog/components/BlogPost/index.js
new file mode 100644
index 0000000000..109afd4711
--- /dev/null
+++ b/packages/docusaurus-plugin-content-blog/components/BlogPost/index.js
@@ -0,0 +1,43 @@
+/**
+ * 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 React, {useContext} from 'react';
+import Head from '@docusaurus/Head';
+import Layout from '@theme/Layout'; // eslint-disable-line
+
+import DocusaurusContext from '@docusaurus/context';
+import Post from '../Post';
+import styles from './styles.module.css';
+
+function BlogPost(props) {
+ const {metadata: contextMetadata = {}, siteConfig = {}} = useContext(
+ DocusaurusContext,
+ );
+ const {baseUrl, favicon} = siteConfig;
+ const {language, title} = contextMetadata;
+ const {modules, metadata} = props;
+ const BlogPostContents = modules[0];
+
+ return (
+
+
+ {title && {title} }
+ {favicon && }
+ {language && }
+
+ {BlogPostContents && (
+
+ )}
+
+ );
+}
+
+export default BlogPost;
diff --git a/packages/docusaurus-plugin-content-blog/components/BlogPost/styles.module.css b/packages/docusaurus-plugin-content-blog/components/BlogPost/styles.module.css
new file mode 100644
index 0000000000..41181ea246
--- /dev/null
+++ b/packages/docusaurus-plugin-content-blog/components/BlogPost/styles.module.css
@@ -0,0 +1,15 @@
+/**
+ * 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.
+ */
+
+.blogPostContainer {
+ border-bottom: 1px solid #e0e0e0;
+ border-radius: 3px;
+ padding-bottom: 20px;
+ margin: 50px auto;
+ text-align: left;
+ max-width: 1100px;
+}
diff --git a/packages/docusaurus/lib/theme/BlogPost/index.js b/packages/docusaurus-plugin-content-blog/components/Post/index.js
similarity index 67%
rename from packages/docusaurus/lib/theme/BlogPost/index.js
rename to packages/docusaurus-plugin-content-blog/components/Post/index.js
index 635294363e..5fc08b0c62 100644
--- a/packages/docusaurus/lib/theme/BlogPost/index.js
+++ b/packages/docusaurus-plugin-content-blog/components/Post/index.js
@@ -7,21 +7,16 @@
import React from 'react';
import Link from '@docusaurus/Link';
-import Head from '@docusaurus/Head';
-import classnames from 'classnames';
-import Layout from '@theme/Layout'; // eslint-disable-line
-
-import DocusaurusContext from '@docusaurus/context';
+import classnames from 'classnames'; // eslint-disable-line
import styles from './styles.module.css';
-class BlogPost extends React.Component {
- renderPostHeader() {
- const {metadata} = this.props;
+function Post(props) {
+ const {metadata, children, truncated} = props;
+ const renderPostHeader = () => {
if (!metadata) {
return null;
}
-
const {
date,
author,
@@ -82,29 +77,21 @@ class BlogPost extends React.Component {
);
- }
+ };
- render() {
- const {metadata = {}, siteConfig = {}} = this.context;
- const {baseUrl, favicon} = siteConfig;
- const {language, title} = metadata;
- const {modules} = this.props;
- const BlogPostContents = modules[0];
-
- return (
-
-
- {title && {title} }
- {favicon && }
- {language && }
-
- {this.renderPostHeader()}
-
-
- );
- }
+ return (
+
+ {renderPostHeader()}
+ {children}
+ {truncated && (
+
+
+ Read More
+
+
+ )}
+
+ );
}
-BlogPost.contextType = DocusaurusContext;
-
-export default BlogPost;
+export default Post;
diff --git a/packages/docusaurus/lib/theme/BlogPost/styles.module.css b/packages/docusaurus-plugin-content-blog/components/Post/styles.module.css
similarity index 52%
rename from packages/docusaurus/lib/theme/BlogPost/styles.module.css
rename to packages/docusaurus-plugin-content-blog/components/Post/styles.module.css
index eac69f06fa..1114b8b419 100644
--- a/packages/docusaurus/lib/theme/BlogPost/styles.module.css
+++ b/packages/docusaurus-plugin-content-blog/components/Post/styles.module.css
@@ -45,3 +45,38 @@
height: 50px;
width: 50px;
}
+
+.readMoreContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.readMoreLink {
+ border: 1px solid #2e8555;
+ border-radius: 3px;
+ color: #2e8555;
+ display: inline-block;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 1.2em;
+ padding: 10px;
+ text-decoration: none!important;
+ text-transform: uppercase;
+ transition: background .3s,color .3s;
+}
+
+.readMoreLink:hover {
+ background-color: #00a388;
+ color: #fff;
+}
+
+.postContainer {
+ border-bottom: 1px solid #e0e0e0;
+ border-radius: 3px;
+ padding-bottom: 20px;
+ margin: 50px auto;
+ text-align: left;
+ width: 600px;
+ max-width: 1100px;
+}
diff --git a/packages/docusaurus-plugin-content-blog/index.js b/packages/docusaurus-plugin-content-blog/index.js
index c2127e1630..2531bc7caf 100644
--- a/packages/docusaurus-plugin-content-blog/index.js
+++ b/packages/docusaurus-plugin-content-blog/index.js
@@ -8,7 +8,7 @@
const globby = require('globby');
const path = require('path');
const fs = require('fs-extra');
-const {parse, idx, normalizeUrl} = require('@docusaurus/utils');
+const {parse, idx, normalizeUrl, generate} = require('@docusaurus/utils');
function fileToUrl(fileName) {
return fileName
@@ -25,10 +25,12 @@ const DEFAULT_OPTIONS = {
routeBasePath: 'blog', // URL Route.
include: ['*.md, *.mdx'], // Extensions to include.
pageCount: 10, // How many entries per page.
- blogPageComponent: '@theme/BlogPage',
- blogPostComponent: '@theme/BlogPost',
+ blogPageComponent: path.resolve(__dirname, './components/BlogPage'),
+ blogPostComponent: path.resolve(__dirname, './components/BlogPost'),
};
+const TRUNCATE_MARKER = //;
+
class DocusaurusPluginContentBlog {
constructor(opts, context) {
this.options = {...DEFAULT_OPTIONS, ...opts};
@@ -43,7 +45,7 @@ class DocusaurusPluginContentBlog {
// Fetches blog contents and returns metadata for the contents.
async loadContent() {
const {pageCount, include, routeBasePath} = this.options;
- const {env, siteConfig} = this.context;
+ const {env, generatedFilesDir, siteConfig} = this.context;
const blogDir = this.contentPath;
const {baseUrl} = siteConfig;
@@ -71,7 +73,20 @@ class DocusaurusPluginContentBlog {
);
const fileString = await fs.readFile(source, 'utf-8');
- const {metadata: rawMetadata} = parse(fileString);
+ const {metadata: rawMetadata, content} = parse(fileString);
+
+ let truncatedSource;
+ const isTruncated = TRUNCATE_MARKER.test(content);
+ if (isTruncated) {
+ const pluginContentDir = path.join(generatedFilesDir, this.getName());
+ await generate(
+ pluginContentDir,
+ blogFileName,
+ content.split(TRUNCATE_MARKER)[0],
+ );
+ truncatedSource = path.join(pluginContentDir, blogFileName);
+ }
+
const metadata = {
permalink: normalizeUrl([
baseUrl,
@@ -79,6 +94,7 @@ class DocusaurusPluginContentBlog {
fileToUrl(blogFileName),
]),
source,
+ truncatedSource,
...rawMetadata,
date,
language: defaultLangTag,
@@ -119,7 +135,9 @@ class DocusaurusPluginContentBlog {
path: permalink,
component: blogPageComponent,
metadata: metadataItem,
- modules: metadataItem.posts.map(post => post.source),
+ modules: metadataItem.posts.map(
+ post => post.truncatedSource || post.source,
+ ),
});
return;
}
diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json
index 2aa53ae4b1..5b12fbc341 100644
--- a/packages/docusaurus-plugin-content-blog/package.json
+++ b/packages/docusaurus-plugin-content-blog/package.json
@@ -3,10 +3,15 @@
"version": "1.0.0",
"description": "Blog content plugin for Docusaurus",
"main": "index.js",
+ "files": [
+ "components"
+ ],
"license": "MIT",
"dependencies": {
"@docusaurus/utils": "^1.0.0",
+ "classnames": "^2.2.6",
"fs-extra": "^7.0.1",
- "globby": "^9.1.0"
+ "globby": "^9.1.0",
+ "react": "^16.8.5"
}
}
diff --git a/packages/docusaurus-utils/index.js b/packages/docusaurus-utils/index.js
index 9879b0dc27..aa98e70d51 100644
--- a/packages/docusaurus-utils/index.js
+++ b/packages/docusaurus-utils/index.js
@@ -14,6 +14,7 @@ const genCache = new Map();
async function generate(generatedFilesDir, file, content) {
const cached = genCache.get(file);
if (cached !== content) {
+ await fs.ensureDir(generatedFilesDir);
await fs.writeFile(path.join(generatedFilesDir, file), content);
genCache.set(file, content);
}
diff --git a/packages/docusaurus/lib/load/index.js b/packages/docusaurus/lib/load/index.js
index 37b5585e64..5f8d9a14c7 100644
--- a/packages/docusaurus/lib/load/index.js
+++ b/packages/docusaurus/lib/load/index.js
@@ -73,7 +73,7 @@ module.exports = async function load(siteDir) {
// Process plugins.
const pluginConfigs = siteConfig.plugins || [];
- const context = {env, siteDir, siteConfig};
+ const context = {env, siteDir, generatedFilesDir, siteConfig};
const {plugins, pluginRouteConfigs} = await loadPlugins({
pluginConfigs,
context,
diff --git a/packages/docusaurus/lib/load/theme.js b/packages/docusaurus/lib/load/theme.js
index 14d8ffa155..819cd9737a 100644
--- a/packages/docusaurus/lib/load/theme.js
+++ b/packages/docusaurus/lib/load/theme.js
@@ -16,8 +16,6 @@ module.exports = function loadConfig(siteDir) {
const themeComponents = [
'Doc',
- 'BlogPost',
- 'BlogPage',
'Pages',
'Loading',
'NotFound',
@@ -26,7 +24,9 @@ module.exports = function loadConfig(siteDir) {
];
themeComponents.forEach(component => {
- if (!require.resolve(path.join(themePath, component))) {
+ try {
+ require.resolve(path.join(themePath, component));
+ } catch (e) {
throw new Error(
`Failed to load ${themePath}/${component}. It does not exist.`,
);
diff --git a/yarn.lock b/yarn.lock
index 426d005e0d..8927926861 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10736,7 +10736,7 @@ react-youtube@^7.9.0:
prop-types "^15.5.3"
youtube-player "^5.5.1"
-react@^16.5.0, react@^16.8.4:
+react@^16.5.0, react@^16.8.4, react@^16.8.5:
version "16.8.5"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.5.tgz#49be3b655489d74504ad994016407e8a0445de66"
integrity sha512-daCb9TD6FZGvJ3sg8da1tRAtIuw29PbKZW++NN4wqkbEvxL+bZpaaYb4xuftW/SpXmgacf1skXl/ddX6CdOlDw==