feat(client): use custom components for guide articles
This commit is contained in:
@ -30,12 +30,15 @@ exports.onCreateNode = function onCreateNode({ node, actions, getNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.internal.type === 'MarkdownRemark') {
|
if (node.internal.type === 'MarkdownRemark') {
|
||||||
let slug = createFilePath({ node, getNode });
|
const slug = createFilePath({ node, getNode });
|
||||||
if (!slug.includes('LICENSE')) {
|
if (!slug.includes('LICENSE')) {
|
||||||
|
const {
|
||||||
|
frontmatter: { component = '' }
|
||||||
|
} = node;
|
||||||
createNodeField({ node, name: 'slug', value: slug });
|
createNodeField({ node, name: 'slug', value: slug });
|
||||||
|
createNodeField({ node, name: 'component', value: component });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.createPages = function createPages({ graphql, actions }) {
|
exports.createPages = function createPages({ graphql, actions }) {
|
||||||
@ -75,6 +78,7 @@ exports.createPages = function createPages({ graphql, actions }) {
|
|||||||
fields {
|
fields {
|
||||||
slug
|
slug
|
||||||
nodeIdentity
|
nodeIdentity
|
||||||
|
component
|
||||||
}
|
}
|
||||||
frontmatter {
|
frontmatter {
|
||||||
block
|
block
|
||||||
|
@ -1,58 +1,28 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { graphql } from 'gatsby';
|
import { graphql } from 'gatsby';
|
||||||
import Helmet from 'react-helmet';
|
|
||||||
|
|
||||||
import Breadcrumbs from './components/Breadcrumbs';
|
import ArticleLayout from './components/ArticleLayout';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
data: PropTypes.object,
|
data: PropTypes.object
|
||||||
location: PropTypes.object,
|
|
||||||
pageContext: PropTypes.shape({
|
|
||||||
meta: PropTypes.objectOf(PropTypes.string)
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GuideArticle = props => {
|
const GuideArticle = props => {
|
||||||
const {
|
const {
|
||||||
location: { pathname },
|
|
||||||
data: {
|
data: {
|
||||||
markdownRemark: {
|
markdownRemark: { html }
|
||||||
html,
|
}
|
||||||
fields: { slug },
|
|
||||||
frontmatter: { title }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pageContext: { meta }
|
|
||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<ArticleLayout {...props}>
|
||||||
<Helmet>
|
|
||||||
<title>{`${title} | freeCodeCamp Guide`}</title>
|
|
||||||
<link href={`https://www.freecodecamp.org${slug}`} rel='canonical' />
|
|
||||||
<meta
|
|
||||||
content={`https://www.freecodecamp.org${slug}`}
|
|
||||||
property='og:url'
|
|
||||||
/>
|
|
||||||
<meta content={title} property='og:title' />
|
|
||||||
<meta
|
|
||||||
content={meta.description ? meta.description : ''}
|
|
||||||
property='og:description'
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
content={meta.description ? meta.description : ''}
|
|
||||||
name='description'
|
|
||||||
/>
|
|
||||||
<meta content={meta.featureImage} property='og:image' />
|
|
||||||
</Helmet>
|
|
||||||
<Breadcrumbs path={pathname} />
|
|
||||||
<article
|
<article
|
||||||
className='article'
|
className='article'
|
||||||
dangerouslySetInnerHTML={{ __html: html }}
|
dangerouslySetInnerHTML={{ __html: html }}
|
||||||
id='article'
|
id='article'
|
||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</ArticleLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,12 +35,7 @@ export const pageQuery = graphql`
|
|||||||
query ArticleById($id: String!) {
|
query ArticleById($id: String!) {
|
||||||
markdownRemark(id: { eq: $id }) {
|
markdownRemark(id: { eq: $id }) {
|
||||||
html
|
html
|
||||||
fields {
|
...ArticleLayout
|
||||||
slug
|
|
||||||
}
|
|
||||||
frontmatter {
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
69
client/src/templates/Guide/components/ArticleLayout.js
Normal file
69
client/src/templates/Guide/components/ArticleLayout.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { graphql } from 'gatsby';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
|
||||||
|
import Breadcrumbs from './Breadcrumbs';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
children: PropTypes.any,
|
||||||
|
data: PropTypes.object,
|
||||||
|
location: PropTypes.object,
|
||||||
|
pageContext: PropTypes.shape({
|
||||||
|
meta: PropTypes.objectOf(PropTypes.string)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const ArticleLayout = props => {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
location: { pathname },
|
||||||
|
data: {
|
||||||
|
markdownRemark: {
|
||||||
|
fields: { slug },
|
||||||
|
frontmatter: { title }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pageContext: { meta }
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<Helmet>
|
||||||
|
<title>{`${title} | freeCodeCamp Guide`}</title>
|
||||||
|
<link href={`https://www.freecodecamp.org${slug}`} rel='canonical' />
|
||||||
|
<meta
|
||||||
|
content={`https://www.freecodecamp.org${slug}`}
|
||||||
|
property='og:url'
|
||||||
|
/>
|
||||||
|
<meta content={title} property='og:title' />
|
||||||
|
<meta
|
||||||
|
content={meta.description ? meta.description : ''}
|
||||||
|
property='og:description'
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
content={meta.description ? meta.description : ''}
|
||||||
|
name='description'
|
||||||
|
/>
|
||||||
|
<meta content={meta.featureImage} property='og:image' />
|
||||||
|
</Helmet>
|
||||||
|
<Breadcrumbs path={pathname} />
|
||||||
|
{children}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ArticleLayout.displayName = 'ArticleLayout';
|
||||||
|
ArticleLayout.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default ArticleLayout;
|
||||||
|
|
||||||
|
export const fragmentQuery = graphql`
|
||||||
|
fragment ArticleLayout on MarkdownRemark {
|
||||||
|
fields {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
frontmatter {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
@ -13,7 +13,7 @@ exports.createGuideArticlePages = createPage => ({
|
|||||||
node: {
|
node: {
|
||||||
htmlAst,
|
htmlAst,
|
||||||
excerpt,
|
excerpt,
|
||||||
fields: { slug },
|
fields: { slug, component },
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
@ -32,7 +32,13 @@ exports.createGuideArticlePages = createPage => ({
|
|||||||
|
|
||||||
return createPage({
|
return createPage({
|
||||||
path: `/guide${slug}`,
|
path: `/guide${slug}`,
|
||||||
component: guideArticle,
|
component: !component
|
||||||
|
? guideArticle
|
||||||
|
: path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../../src/templates/Guide/components/',
|
||||||
|
component
|
||||||
|
),
|
||||||
context: {
|
context: {
|
||||||
id,
|
id,
|
||||||
meta
|
meta
|
||||||
|
Reference in New Issue
Block a user