Как написать файл JSON на основе данных из нескольких файлов уценки

Мне нужно создать 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.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.info(matter(str));
});

Я могу показать данные из 1 файла в консоли, делая это. Но мне нужна помощь, чтобы показать данные из всех файлов в ./src/docs/, а затем объединить их в 1 результат и проанализировать в 1 файл JSON.

Как я могу это сделать? Вся помощь и предложения приветствуются.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
960
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В основном то, что вы хотите сделать, это

  1. создать поток записи
  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' но я посмотрю, смогу ли я найти решение для этого. В любом случае шаги хороши, и мне нравится подход.

BenderBoii 14.06.2019 12:23

для этого вы хотите path.join имя файла. Отредактировал ответ. @BenderBoii Отредактируйте path.join по своему усмотрению (console.info содержимое path.join для подтверждения)

Aritra Chakraborty 14.06.2019 13:44

Все еще не могу заставить этот пример работать. Некоторые файлы уценки находятся во вложенных папках, и по этой причине возникает ошибка. 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 Есть предложения, как это исправить?

BenderBoii 18.06.2019 11:10

Отредактировал ответ, используйте переменную root. Он содержит путь к папке. Снова проверьте это с помощью консоли, регистрирующей путь

Aritra Chakraborty 18.06.2019 11:50

Спасибо! Заработало, удалив dirname и используя только root.

BenderBoii 18.06.2019 12:11

Я сделал это как «упражнение», используя узел, а не глоток:

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) Есть идеи?

BenderBoii 18.06.2019 10:54

Я использовал папку для файлов уценки под названием markdown в инструкции glob.sync. Измените это на свой путь к файлам уценки.

Mark 18.06.2019 14:12

@Mark, я использую nuxt. Можно ли использовать ваш код с webpack?

Niklas 19.07.2019 21:13

Другие вопросы по теме