The directory structure

Description: Transforms the lib compiled code SRC Transforms parser, which currently has only one markdown.js, In the future, there may be code that extends markdown.js to finally parse markdown files utils toolset executor.js child threads used when debugging the executor runtask.js that parses Markdown, Multi-threaded parsing markdown’s scheduler source-handler.js builds the file tree’s handler index.js entry file

First, know what a WebPack Loader needs to output; From the red box above, the loader calls callback and returns a string from Module. exports. The exported module is the object from which a module was imported in the final project, and the import articles from ‘.. /articles.DOCS’, how to implement a Webpack loader, see Writing a Loader for more details.

Implementation analysis

index.js

const fs = require('fs'); const path = require('path'); const R = require('ramda'); const sourceHandler = require('./utils/source-handler'); const scheduler = require('./utils/scheduler'); const defaultRoot = path.resolve(process.cwd(), 'articles'); const concat = obj => key => value => obj[key] = R.sortBy( R.compose((date) => new Date(date).getTime(), R.prop('date')) )(R.union(obj[key], [value])).reverse(); /* https://github/hihl/blog */ const markdown = sourceHandler.traverse(root, filePath => { const content = fs.readFileSync(filePath).toString(); pickedPromises.push(new Promise(resolve => { scheduler.queue({ filePath, content, callback(err, result) { const parsedMarkdown = JSON.parse(result); const category = parsedMarkdown.meta.category; const fileKey = '/' + filePath.split('/').slice(-4).join('/'); const date = filePath.split('/').slice(-4, -1).join('-'); const { title, summary } = parsedMarkdown.meta; mds[fileKey] = { key: fileKey, title, summary, content: parsedMarkdown.content, category, tags: parsedMarkdown.meta.tags, date }; const value = { key: fileKey, title, summary, date}; concat(categories)(category)(value); R.forEach(key => concat(tags)(key)(value), parsedMarkdown.meta.tags); resolve(); }}); })); });Copy the code

Traverse the sourceHandler.traverse will parse the files in the root directory and pass valid filePath to the callback method, which will read the file and add it to the scheduler as a task. The result is passed to the callback method callback, which does the final assembly, which exports the data required by the Module, including all date-sorted categories, tags, and articles

Parse the file tree

source-handler.js

function readDirs(filter, dir) { return R.filter(filter)(fs.readdirSync(dir)); } /** * Build file tree, And parses the md file * root directory structure for * * * | | - year year - * * | | - day date in the month - filename file name (full path) * / function readFilesTreeStructure(root, fn) { return R.pipe( R.map(year => R.pipe( R.pipe( R.map(month => R.pipe( R.pipe( R.map(day => R.pipe( R.map(filename =>  { const filePath = path.join(root, year, month, day, filename); fn(filePath); return filePath; }), R.objOf(day) )(readDirs(R.endsWith('.md'), path.join(root, year, month, day)))), R.reduce(R.mergeDeepLeft, {}) ), R.objOf(month) )(readDirs(R.and(R.lte(1), R.gte(maxDay(year, month))), path.join(root, year, month)))), R.reduce(R.mergeDeepLeft, {}) ), R.objOf(year) )(readDirs(R.and(R.lte(1), R.gte(12)), path.join(root, year)))), R.reduce(R.mergeDeepLeft, {}) )(readDirs(R.lt(0), root)); } exports.traverse = function(root, fn) { if (! root || ! isDirectory(root)) { return {}; } return readFilesTreeStructure(root, fn); };Copy the code

ReadFilesTreeStructure parses a json tree of files from the root directory and passes each valid file path to the callback method fn. It also filters out illegal year, month, and day directories and file suffixes. Let’s look at the code in detail. Before we do that again, let’s take a look at Ramda: R.t (0); r.t (0); r.t (0); r.t (0); r.t (0); Add (root, year); add (root, year); add (root, year); add (root, year); {[year]: {[year]: {[year]: {[year]: {[year]: {[year]: {[year]: {[year]: {[year]: {[year]: { {[year]:{[month]:{[day]:filename}}} {[year]:{[day]:filename}}}

Here’s some code that doesn’t use Ramda for comparison.

function readDirs(filter, dir) { return fs.readdirSync(dir).filter(filter); } function readFilesTreeStructure(root, fn) { return readDirs(o => o > 0, root) .map(year => { const months = readDirs(o => o >=1 && o <= 12, path.join(root, year)) .map(month => { const days = readDirs(o => o >=1 && o <= maxDay(year, month), path.join(root, year, month)) .map(day => { return readDirs(o => o.endsWith('.md'), path.join(root, year, month, day)) .map(filename => { const filePath = path.join(root, year, month, day, filename); fn(filePath); return filePath; }); }). Reduce ((result, value) = > {/ * * a merge code /}, {}); return { [month]: days }; }). Reduce ((result, value) = > {/ * * a merge code /}, {}); return { [year]: months }; }). Reduce ((result, value) = > {/ * * a merge code /}, {}); }Copy the code

Parse the markdown file contents

{[year]:{[month]:{[day]:filename}}} {fn(filePath), which is the callback method in index.js, Const Content = fs.readfilesync (filePath).toString(); The logic for parsing executors is very simple. Toss content into transforms/ markDown.js for parsing

const YFM = require('yaml-front-matter');

module.exports = function MT(markdown) {
  const ret = {};
  const raw = YFM.loadFront(markdown);
  ret.content = raw.__content;
  delete raw.__content;
  ret.meta = raw;
  return ret;
};Copy the code

The header of each Markdown file is a yamL configuration, including the title, label, classification and summary of the article. The yamL-front-matter library is used to parse the __content part of the article. This article does not do much parsing because it is simple. All handed over to react-Markdown.

summary

In this article, markdown code is used to parse markdown data. In this article, markdown code is used to parse markdown data. In our next post, we’ll cover how to add traffic statistics to your site using leanCloud. Source address: github.com/hihl/blog