#javascript #node.js
Вопрос:
Я не очень хорошо разбираюсь в NodeJS, но мне удалось собрать базовый серверный скрипт, чтобы получить файлы уценки из папки и написать файл JSON со всем содержимым frontmatter. Проблема в том, что в результирующем JSON есть r
или rnr
для некоторых разрывов строк, а не для других, что вызывает проблемы в моем материале.
Например:
{
"section": "Medicalr",
}
отличается от :
{
"section": "Medical",
}
в результате в моей документации создаются дубликаты «Глав».
Я пытался:
- проверка наличия лишних пробелов
- вручную удалив все
r
в JSON, что временно устраняет проблему
Я использую :
- Узел v14.15.2
- macOS 1.2.3
- VSCode 1.55.2
- CRA 4
- nodemon 2.0.6 для запуска сервера и отслеживания изменений
Это сервер узла:
const path = require('path');
const fs = require('fs');
const dirPath = path.join(__dirname, '../library/');
let postList = [];
const getPosts = () => {
fs.readdir(dirPath, (err, files) => {
if (err) {
return console.log('Failed to list contents of directory: ' err);
}
let fileList = [];
files.forEach((file, i) => {
let obj = {};
let post;
fs.readFile(`${dirPath}/${file}`, 'utf8', (err, contents) => {
const getMetadataIndices = (acc, elem, i) => {
if (/^---/.test(elem)) {
acc.push(i);
}
return acc;
};
const parseMetadata = ({ lines, metadataIndices }) => {
if (metadataIndices.length > 0) {
let metadata = lines.slice(
metadataIndices[0] 1,
metadataIndices[1]
);
metadata.forEach((line) => {
obj[line.split(': ')[0]] = line.split(': ')[1];
});
return obj;
}
};
const parseContent = ({ lines, metadataIndices }) => {
if (metadataIndices.length > 0) {
lines = lines.slice(metadataIndices[1] 1, lines.length);
}
return lines.join('n');
};
const lines = contents.split('n');
const metadataIndices = lines.reduce(getMetadataIndices, []);
const metadata = parseMetadata({ lines, metadataIndices });
const content = parseContent({ lines, metadataIndices });
// H2 headings
const h2 = /^## (.*$)/gim;
const headings = content.matchAll(h2);
var headingsArrays = [...headings].map((m) => m.slice(1));
var mergedHeadings = [].concat.apply([], headingsArrays);
post = {
name: metadata.title ? metadata.title : 'No title given',
updated: metadata.updated ? metadata.updated : 'No update given',
content: content ? content : 'No content given',
path: metadata.path ? metadata.path : '404',
section: metadata.section ? metadata.section : 'Misc',
headings: mergedHeadings ? mergedHeadings : []
};
postList.push(post);
fileList.push(i);
if (fileList.length === files.length) {
const sortedList = postList.sort((a, b) => {
return a.id < b.id ? 1 : -1;
});
let data = JSON.stringify(sortedList);
fs.writeFileSync('src/posts.json', data);
}
});
});
});
return;
};
getPosts();
Я ценю любые советы, чтобы остановить r
запись в JSON. Спасибо.
Комментарии:
1. Сработает ли что-то подобное
lines.map(line => line.replace(/r$/, '')
? Это замена возвращаемого конца строки пустой строкой2. Спасибо, @evolutionxbox, это сработало. Я надеялся предотвратить
r
, а не удалить их после того, как они были добавлены, но это работает нормально. Можете ли вы дать на это ответ?3. Я бы предположил, что это не узел, добавляющий возвраты, вместо этого они существуют в самом файле?
4. @evolutionxbox вот чего я не понимаю — я вырезал все пробелы из переднего плана, скопировал и вставил также передний план, чтобы убедиться, что он точно такой же, перезапустил сервер, и все равно у одного объекта JSON был
r
, а у другого нет.5. Скорее всего, это проблема с окончанием строки. Что вы увидите, если включите «невидимые персонажи»?
Ответ №1:
Это предложение от @evolutionxbox выше работает:
const path = require('path');
const fs = require('fs');
const dirPath = path.join(__dirname, '../library/');
let postList = [];
const getPosts = () => {
fs.readdir(dirPath, (err, files) => {
if (err) {
return console.log('Failed to list contents of directory: ' err);
}
let fileList = [];
files.forEach((file, i) => {
let obj = {};
let post;
fs.readFile(`${dirPath}/${file}`, 'utf8', (err, contents) => {
const getMetadataIndices = (acc, elem, i) => {
if (/^---/.test(elem)) {
acc.push(i);
}
return acc;
};
const parseMetadata = ({ lines, metadataIndices }) => {
if (metadataIndices.length > 0) {
let metadata = lines
.slice(metadataIndices[0] 1, metadataIndices[1])
.map((line) => line.replace(/r$/, ''));
metadata.forEach((line) => {
obj[line.split(': ')[0]] = line.split(': ')[1];
});
return obj;
}
};
const parseContent = ({ lines, metadataIndices }) => {
if (metadataIndices.length > 0) {
lines = lines.slice(metadataIndices[1] 1, lines.length);
}
return lines.join('n');
};
const lines = contents
.split('n')
.map((line) => line.replace(/r$/, ''));
const metadataIndices = lines.reduce(getMetadataIndices, []);
const metadata = parseMetadata({ lines, metadataIndices });
const content = parseContent({ lines, metadataIndices });
// H2 headings
const h2 = /^## (.*$)/gim;
const headings = content.matchAll(h2);
var headingsArrays = [...headings].map((m) => m.slice(1));
var mergedHeadings = [].concat.apply([], headingsArrays);
post = {
name: metadata.title ? metadata.title : 'No title given',
updated: metadata.updated ? metadata.updated : 'No update given',
content: content ? content : 'No content given',
path: metadata.path ? metadata.path : '404',
section: metadata.section ? metadata.section : 'Misc',
headings: mergedHeadings ? mergedHeadings : []
};
postList.push(post);
fileList.push(i);
if (fileList.length === files.length) {
const sortedList = postList.sort((a, b) => {
return a.id < b.id ? 1 : -1;
});
let data = JSON.stringify(sortedList);
fs.writeFileSync('src/posts.json', data);
}
});
});
});
return;
};
getPosts();