【问题标题】:How to write a JSON file based on data from multiple markdown files如何根据来自多个降价文件的数据编写 JSON 文件
【发布时间】:2019-06-14 08:41:34
【问题描述】:

我需要使用我的 markdown 文件中的数据构建一个 API。

我有大约 100 个降价文件,文件顶部有这样的数据:

---
title: Lorem ipsum
category: component
primaryKeywords: curved horizon
secondaryKeywords: css block content seperator
---

所需的输出是单个 .json 文件,其中包含我的 .md 文件中的所有数据作为数组中的对象。

例子:

[
  {
    "title": "Lorem ipsum",
    "category": "component",
    "primaryKeywords": "curved horizon",
    "secondaryKeywords": "css block content seperator"
  },
  {
    "title": "Lorem ipsum",
    "category": "component",
    "primaryKeywords": "curved horizon",
    "secondaryKeywords": "css block content seperator"
  },
  {
    "title": "Lorem ipsum",
    "category": "component",
    "primaryKeywords": "curved horizon",
    "secondaryKeywords": "css block content seperator"
  }
]

JSON 文件应作为前端构建的一部分生成。我正在使用 gulp。

我尝试过这样做:

gulp.task('search-api', function (cb) {
  const fs = require('fs');
  const matter = require('gray-matter');
  const str = fs.readFileSync('./src/docs/01-Components/02-Layout/03-bow.md', 'utf8');
  console.log(matter(str));
});

我可以在控制台中显示来自 1 个文件的数据。但我需要帮助来显示来自./src/docs/ 中所有文件的数据,然后将其合并为 1 个结果并将其解析为 1 个 JSON 文件。

我该怎么做?感谢所有帮助和建议。

【问题讨论】:

    标签: javascript node.js json gulp markdown


    【解决方案1】:

    基本上你想做的是

    1. 创建一个 writeStream
    2. 添加“[”
    3. 添加对象

    4. 为每个文件循环:添加逗号“,”

    5. 添加另一个对象
      :loopend
    6. 添加另一个结束“]”

    为此,您可以使用walk 包。

    const fs = require('fs');
    const walk = require('walk');
    const matter = require('gray-matter');
    const dirname = "./src/docs";
    const path = require('path');
    const walker = walk.walk(dirname);
    let prefix = ""
    const stream = fs.createWriteStream("json.json", {flags:'a'});
    stream.write("[\n");
    walker.on("file",  (root, fileStats, next) => {
        const str = fs.readFileSync(path.join(root, fileStats.name), 'utf8');
        stream.write(prefix);
        stream.write(JSON.stringify(matter(str),null, 4));
        prefix=","
        next();
    });
    
    walker.on("errors", function (root, nodeStatsArray, next) {
        next();
    });
    
    walker.on("end", function () {
        stream.write("\n]");
        stream.end();
    });
    

    PS:我从头顶编写的这段代码给你一些暗示。如果有错误,请随时编辑。

    【讨论】:

    • 谢谢!我可以看到你在做什么。你的例子不起作用我得到:Error: ENOENT: no such file or directory, open '03-bow.md' 但我会看看我是否能找到解决方案。无论如何,这些步骤很好,我喜欢这种方法。
    • 你想path.join文件名。编辑了答案。 @BenderBoii 随意编辑 path.join(console.log 中 path.join 的内容以确认)
    • 仍然无法让这个例子工作。一些降价文件位于子文件夹中,这就是它引发错误的原因。 fs.js:115 throw err; ^ Error: ENOENT: no such file or directory, open 'src\docs\02-Installation-and-Usage.md' 该文件位于名为 03-Code Guidelines 的子文件夹中,因此该文件的正确路径是 src\docs\03-Code Guidelines\02-Installation-and-Usage.md 有关如何解决此问题的任何建议?
    • 编辑答案,使用root 变量。它包含文件夹路径。通过控制台记录路径再次测试它
    • 谢谢!通过删除 dirname 并仅使用 root 使其工作。
    【解决方案2】:

    我使用节点而不是 gulp 将其作为“练习”来完成:

    const fs = require('fs');
    const glob = require('glob');
    const os = require('os');
    
    const markdownFiles = glob.sync("./markdown/*.md");  // an array of files in the 'markdown' directory
    let finalArray = [];
    
    
    function buildJSONfile() {
    
      let contents;
    
      markdownFiles.forEach((nextFile) => {
    
        contents = fs.readFileSync(nextFile, "UTF8");
    
            // os.EOL = \r\n for windows, \n for POSIX
        let grayMatter = contents.match(new RegExp(`---${os.EOL}((.*${os.EOL})*?)---`));  // get just the content between the "---"s in array[1]
    
        //  add quotes around all the keys and values and add commas between key:value pairs
        let addedQuotes = grayMatter[1].replace(/^([^:]*)(:\s*)(.*)(\s*)/mg, '"$1"$2"$3",');  
    
        addedQuotes = addedQuotes.slice(0, addedQuotes.length - 1);  // remove the extra comma at the end of the last value
    
        let addedBrackets = `{${addedQuotes}}`;  // add brackets around the whole thing so that we can use JSON.parse
    
        let JSONobject = JSON.parse(addedBrackets);
    
        finalArray.push(JSONobject);
      });
    
          // write to a file : result.json
      fs.writeFileSync("./result.json", JSON.stringify(finalArray, null, '\t'), "UTF8");
    };
    
    buildJSONfile();  // comment out if using gulp
    

    使用node yourFileNameHere.js运行。
    您也可以将其放入 gulpfile.js 并通过 gulp buildJSONfile 运行。

    【讨论】:

    • 很酷。谢谢!不过我不能上班。我得到了:[10:50:46] TypeError: Cannot read property '1' of null at markdownFiles.forEach (D:\dna\gulpfile.js:555:33) at Array.forEach (<anonymous>) at Gulp.gulp.task (D:\dna\gulpfile.js:548:17) 有什么想法吗?
    • 我在glob.sync 语句中使用了一个名为markdown 的降价文件文件夹。将其更改为您的降价文件路径。
    • @Mark 我正在使用 nuxt。是否可以将您的代码与 webpack 一起使用?
    猜你喜欢
    • 2021-06-28
    • 2014-03-09
    • 2021-07-08
    • 2017-08-21
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多