feat(guide): Import guide in to the client app
This commit is contained in:
55
client/plugins/fcc-create-nav-data/create-navigation-node.js
Normal file
55
client/plugins/fcc-create-nav-data/create-navigation-node.js
Normal file
@ -0,0 +1,55 @@
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
const commonREs = require('../../utils/regEx');
|
||||
const readDir = require('../../utils/readDir');
|
||||
|
||||
const { isAStubRE } = commonREs;
|
||||
const pagesDir = path.resolve(__dirname, '../../src/pages/guide');
|
||||
|
||||
function withGuidePrefix(str) {
|
||||
return `/guide${str}`;
|
||||
}
|
||||
|
||||
exports.createNavigationNode = node => {
|
||||
const {
|
||||
fileAbsolutePath,
|
||||
frontmatter: { title },
|
||||
internal: { content },
|
||||
parent
|
||||
} = node;
|
||||
|
||||
const nodeDir = fileAbsolutePath.replace(/\/index\.md$/, '');
|
||||
const dashedName = nodeDir.split('/').slice(-1)[0];
|
||||
const [, path] = nodeDir.split(pagesDir);
|
||||
const parentPath = path
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
.join('/');
|
||||
|
||||
const categoryChildren = readDir(nodeDir);
|
||||
const navNode = {
|
||||
categoryChildren,
|
||||
hasChildren: !!categoryChildren.length,
|
||||
dashedName,
|
||||
isStubbed: isAStubRE.test(content),
|
||||
path: withGuidePrefix(path),
|
||||
parentPath: withGuidePrefix(parentPath),
|
||||
title
|
||||
};
|
||||
|
||||
const gatsbyRequired = {
|
||||
id: fileAbsolutePath + ' >>> NavigationNode',
|
||||
parent,
|
||||
children: [],
|
||||
internal: {
|
||||
type: 'NavigationNode',
|
||||
contentDigest: crypto
|
||||
.createHash('md5')
|
||||
.update(JSON.stringify(navNode))
|
||||
.digest('hex')
|
||||
}
|
||||
};
|
||||
|
||||
return { ...navNode, ...gatsbyRequired };
|
||||
};
|
@ -0,0 +1,77 @@
|
||||
const path = require('path');
|
||||
const { expect } = require('chai');
|
||||
|
||||
const { createNavigationNode } = require('./create-navigation-node');
|
||||
|
||||
describe('fcc-create-nav-data', () => {
|
||||
describe('create-vanigation-node', () => {
|
||||
const mockNode = {
|
||||
internal: {
|
||||
content:
|
||||
'---\ntitle: File Writing\n---\n## File Writing\n\nThis is a stub.' +
|
||||
" <a href='https://github.com/freecodecamp/guides/tree/master/src/" +
|
||||
"pages/php/functions/files/writing/index.md' target='_blank' " +
|
||||
"rel='nofollow'>Help our community expand it</a>.\n\n<a href=" +
|
||||
"'https://github.com/freecodecamp/guides/blob/master/README.md' " +
|
||||
"target='_blank' rel='nofollow'>This quick style guide will help " +
|
||||
'ensure your pull request gets accepted</a>.\n\n<!-- The article ' +
|
||||
'goes here, in GitHub-flavored Markdown. Feel free to add YouTube ' +
|
||||
'videos, images, and CodePen/JSBin embeds -->\n\n#### More ' +
|
||||
'Information:\n<!-- Please add any articles you think might be ' +
|
||||
'helpful to read before writing the article -->\n'
|
||||
},
|
||||
frontmatter: {
|
||||
title: 'File Writing'
|
||||
},
|
||||
fileAbsolutePath: path.resolve(
|
||||
__dirname,
|
||||
'../../src/pages/guide/php/functions/files/file-writing/index.md'
|
||||
)
|
||||
};
|
||||
|
||||
const result = createNavigationNode(mockNode);
|
||||
|
||||
it('should return an object', () => {
|
||||
expect(result).to.be.an('object');
|
||||
});
|
||||
|
||||
it('node.children should be an array', () => {
|
||||
expect(result.categoryChildren).to.be.an('array');
|
||||
});
|
||||
|
||||
it('node.dashedName should equal the containing folder name', () => {
|
||||
expect(result.dashedName).equal('file-writing');
|
||||
});
|
||||
|
||||
it('node.path should equal the file path from pagesDir, prefixed with `/guide`', () => {
|
||||
expect(result.path).to.equal('/guide/php/functions/files/file-writing');
|
||||
});
|
||||
|
||||
it('node.parentPath should equal the path of the parent page, prefixed with `/guide`', () => {
|
||||
expect(result.parentPath).to.equal('/guide/php/functions/files');
|
||||
});
|
||||
|
||||
it('node.title should equal srcNode.frontmatter.title', () => {
|
||||
expect(result.title).to.equal(mockNode.frontmatter.title);
|
||||
});
|
||||
|
||||
it('node.isStubbed should be a boolean', () => {
|
||||
expect(result.isStubbed).to.be.a('boolean');
|
||||
});
|
||||
|
||||
it('node.isStubbed should be true for a stubbed article', () => {
|
||||
expect(result.isStubbed).to.equal(true);
|
||||
});
|
||||
|
||||
it('node.isStubbed should be false for a non-stubbed article', () => {
|
||||
const notAStub = {
|
||||
...mockNode,
|
||||
internal: {
|
||||
content: 'this is not a stub article. Infact, it is very informative'
|
||||
}
|
||||
};
|
||||
const result = createNavigationNode(notAStub);
|
||||
expect(result.isStubbed).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
13
client/plugins/fcc-create-nav-data/gatsby-node.js
Normal file
13
client/plugins/fcc-create-nav-data/gatsby-node.js
Normal file
@ -0,0 +1,13 @@
|
||||
const { createNavigationNode } = require('./create-navigation-node');
|
||||
|
||||
exports.onCreateNode = ({ actions, node }) => {
|
||||
const { internal: {type, identity}} = node;
|
||||
if (type === 'MarkdownRemark' && identity === 'guideMarkdown') {
|
||||
if (node.fileAbsolutePath.includes('LICENSE.md')) {
|
||||
return null;
|
||||
}
|
||||
const { createNode } = actions;
|
||||
return Promise.resolve(createNavigationNode(node)).then(createNode);
|
||||
}
|
||||
return null;
|
||||
};
|
12
client/plugins/fcc-create-nav-data/package.json
Normal file
12
client/plugins/fcc-create-nav-data/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "fcc-create-nav-data",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"test": "mocha -R spec \"./{,!(node_modules)/**/}*.test.js\"",
|
||||
"test:watch": "mocha -R spec \"./{,!(node_modules)/**/}*.test.js\" --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"chai": "^4.1.2",
|
||||
"mocha": "^5.0.5"
|
||||
}
|
||||
}
|
170
client/plugins/fcc-create-nav-data/yarn.lock
Normal file
170
client/plugins/fcc-create-nav-data/yarn.lock
Normal file
@ -0,0 +1,170 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
assertion-error@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
|
||||
chai@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c"
|
||||
dependencies:
|
||||
assertion-error "^1.0.1"
|
||||
check-error "^1.0.1"
|
||||
deep-eql "^3.0.0"
|
||||
get-func-name "^2.0.0"
|
||||
pathval "^1.0.0"
|
||||
type-detect "^4.0.0"
|
||||
|
||||
check-error@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
||||
|
||||
commander@2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
deep-eql@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
|
||||
dependencies:
|
||||
type-detect "^4.0.0"
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
|
||||
escape-string-regexp@1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
||||
get-func-name@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
growl@1.10.3:
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f"
|
||||
|
||||
has-flag@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
|
||||
mkdirp@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mocha@^5.0.5:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.5.tgz#e228e3386b9387a4710007a641f127b00be44b52"
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.11.0"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.2"
|
||||
growl "1.10.3"
|
||||
he "1.1.1"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "4.4.0"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
|
||||
pathval@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
|
||||
|
||||
supports-color@4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"
|
||||
dependencies:
|
||||
has-flag "^2.0.0"
|
||||
|
||||
type-detect@^4.0.0:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
@ -11,17 +11,18 @@ that delivers challenge files to the plugin
|
||||
const { createNode } = actions;
|
||||
|
||||
const { source } = pluginOptions;
|
||||
return source().subscribe(
|
||||
challenges =>
|
||||
return source()
|
||||
.then(challenges =>
|
||||
challenges
|
||||
.filter(challenge => challenge.superBlock !== 'Certificates')
|
||||
.map(challenge => createChallengeNodes(challenge, reporter))
|
||||
.map(node => createNode(node)),
|
||||
e =>
|
||||
.map(node => createNode(node))
|
||||
)
|
||||
.catch(e =>
|
||||
reporter.panic(`fcc-sourec-challenges
|
||||
|
||||
${e.message}
|
||||
${e.message}
|
||||
|
||||
`)
|
||||
);
|
||||
`)
|
||||
);
|
||||
};
|
||||
|
30
client/plugins/gatsby-remark-fcc-forum-emoji/index.js
Normal file
30
client/plugins/gatsby-remark-fcc-forum-emoji/index.js
Normal file
@ -0,0 +1,30 @@
|
||||
const visit = require('unist-util-visit');
|
||||
|
||||
const emojiRE = /^:[a-z_]+:$/;
|
||||
|
||||
function markdownToHTML(node) {
|
||||
const { url, title, alt } = node;
|
||||
const html = `
|
||||
<img
|
||||
alt="${alt}"
|
||||
class="forum-image"
|
||||
src="${url}"
|
||||
title="${title}"
|
||||
>
|
||||
`;
|
||||
|
||||
return Object.assign(node, {
|
||||
type: 'html',
|
||||
value: html
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = ({ markdownAST }) => {
|
||||
visit(markdownAST, 'image', imageNode => {
|
||||
if (emojiRE.test(imageNode.title)) {
|
||||
return markdownToHTML(imageNode);
|
||||
}
|
||||
|
||||
return imageNode;
|
||||
});
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "gatsby-remark-fcc-forum-emoji",
|
||||
"description": "A plugin to help fix the styling of forum emoji in the Guide",
|
||||
"main": "index.js"
|
||||
}
|
16
client/plugins/gatsby-remark-node-identity/gatsby-node.js
Normal file
16
client/plugins/gatsby-remark-node-identity/gatsby-node.js
Normal file
@ -0,0 +1,16 @@
|
||||
exports.onCreateNode = ({ node, reporter }, { predicate, identity }) => {
|
||||
if (typeof predicate !== 'function') {
|
||||
reporter.panic(
|
||||
'Please supply a predicate function to `gatsby-plugin-identity`'
|
||||
);
|
||||
}
|
||||
if (typeof identity !== 'string' || identity.lenght === 0) {
|
||||
reporter.panic(
|
||||
'`gatsby-plugin-identity` requires an identify string to add to nodes ' +
|
||||
'that match the predicate'
|
||||
);
|
||||
}
|
||||
if (predicate(node)) {
|
||||
node.internal.identity = identity;
|
||||
}
|
||||
};
|
1
client/plugins/gatsby-remark-node-identity/package.json
Normal file
1
client/plugins/gatsby-remark-node-identity/package.json
Normal file
@ -0,0 +1 @@
|
||||
{"name": "gatsby-plugin-node-identity", "version": "0.1.0"}
|
Reference in New Issue
Block a user