读取所有 .md 文件,将它们转换为 html 并发送它们
Posted
技术标签:
【中文标题】读取所有 .md 文件,将它们转换为 html 并发送它们【英文标题】:Read all .md files, convert them to html and send them 【发布时间】:2021-01-07 22:40:16 【问题描述】:我使用fs
读取.md格式的文件,我想把它转换成html文件。
这是我目前的代码:
fs = require('fs');
fs.readFile(__dirname + '/posts/react-v16.13.0.md', 'utf8', function (err, data)
if (err)
return console.log(err);
console.log(data);
);
该文件位于该文件夹中并具有该名称。
此函数将 .md 文件的内容放入控制台。
为了将其转换为 html,我添加了以下内容:
const showdown = require('showdown');
converter = new showdown.Converter();
...
fs = require('fs');
fs.readFile(__dirname + '/posts/react-v16.13.0.md', 'utf8', function (
err,
data
)
if (err)
return console.log(err);
text = data;
html = converter.makeHtml(text);
console.log(html);
);
它将文件作为html放在日志中,这很好。
我的问题是如果/posts/
文件夹中有多个文件,如何读取和发送这些文件?
我想使用 POST 方法将它们发送到前端。
是否可以从文件夹中读取所有文件,转换并发送它们?
【问题讨论】:
可以使用fs.readdir()
获取文件列表。 nodejs.org/api/fs.html#fs_fs_readdir_path_options_callback
@AKX 我尝试了类似fs.readdir(__dirname + '/posts', 'utf8', function (err, data) ...
但我得到他的错误:/.../Projects/md/server/node_modules/showdown/dist/showdown.js:2459 text = text.replace(/¨/g, '¨T');
这可能会对您有所帮助。 ***.com/a/10049704/1524756
“所有文件......发送它们”是什么意思。将它们全部连接到一个 html blob 并将其作为响应/请求正文发送?
你弄丢了我,对不起,:脸红:
【参考方案1】:
从问题下方的评论线程看来,您想要执行以下操作:
将所有 Markdown 文件从给定目录转换为 HTML 在一个请求中全部发送 可在单页应用中使用这是一种满足所有这些要求的方法。每篇文章的 HTML 都插入到 template
元素中,其内容可以在 SPA 脚本中进行克隆和操作。
server.js
// with `.promises`, we can use `async/await`
const fs = require("fs").promises;
// ...
const getHtmlByFilename = async filename =>
const md = await fs.readFile(
path.join(__dirname, "posts", filename),
"utf-8"
);
return converter.makeHtml(md);
;
app.get("/", async (request, response) =>
const filenames = await fs.readdir(path.join(__dirname, "posts"));
// we can also use Promise.all
// to map over the filenames in parallel
const htmls = await Promise.all(
filenames.map(async filename =>
const html = await getHtmlByFilename(filename);
return filename, html ;
)
);
response.send(
htmlBoilerplate(
htmls
.map(
( filename, html ) =>
`<template id="$filename">$html</template>`
)
.join("\n"),
"<h1>SPA</h1>",
'<script src="/public/spa.js"></script>'
)
);
);
public/spa.js
[...document.querySelectorAll("template")].forEach(template =>
const clone = template.content.cloneNode(true);
const filename = template.id;
const details = document.createElement("details");
const summary = document.createElement("summary");
summary.textContent = filename;
details.appendChild(summary);
details.appendChild(clone);
document.querySelector(".markdown-body").appendChild(details);
);
glitch.me 演示
Source | Live
限制
转换是即时完成的。如果您的流量很大,您可能需要实现一些缓存,或者可能只是单独保存 HTML 版本,并在相应的 Markdown 被编辑时触发更新。 当前代码可能不是 XSS 安全的 - 这假定帖子的内容/文件名是可信的,或者您在需要时进行了适当的清理。【讨论】:
【参考方案2】:const readdir, readFile = require('fs');
const showdown = require('showdown');
const axios = require('axios');
let fileHtmlList = [];
const converter = new showdown.Converter();
readdir(`$__dirname/posts`, 'utf8', (fsDirError, fileNameList) =>
if(!fsDirError)
fileNameList.forEach((fileName) =>
readFile(`$__dirname/posts/$fileName`, 'utf8', (fsReadError, fileContent) =>
if(!fsReadError)
fileHtmlList.push(
fileName: `$__dirname/posts/$fileName`,
htmlContent: converter.makeHtml(fileContent)
);
else
return console.error(fsReadError);
);
);
else
return console.error(fsDirError);
);
/* I'm guessing this part from your description, if the content needs to be rendered then the code needs change */
let sendFrontEnd = async (data) =>
try
const response = await axios.post(`urlToSend`, data);
console.log(response);
catch (error)
console.error(error);
;
fileHtmlList.forEach((item) =>
sendFrontEnd(item.htmlContent);
);
【讨论】:
【参考方案3】:我建议使用 readdir 和 readFile 的同步变体
const basePath = __dirname + '/posts/';
const htmls = [];
fs.readdirSync(basePath).forEach(file =>
const text = fs.readFileSync(basePath + file, 'utf8');
htmls.push(
file,
html: converter.makeHtml(text)
);
);
// upload htmls with axios/fetch/ ....
【讨论】:
为什么?这将成为瓶颈。 我以为他想通过一个帖子请求发送所有文件,这意味着他没有那么多文件......也许我误解了【参考方案4】:试试这个js库
<!-- Lightweight client-side loader that feature-detects and load polyfills only when necessary -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- Load the element definition -->
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
<div class="markdown-body">
<zero-md src="README.md"> </zero-md>
</div>
我强烈建议在 html 文件中使用零降价,因为
从您的 readme.md 文件自动更新。 如果您使用将自述文件转换为 html,则每次更新自述文件(或代码更多)时都必须手动转换。我的源代码中的完整 html
<!DOCTYPE html>
<html>
<head>
<title>API Get link Zing Mp3</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.markdown-body
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
@media (max-width: 767px)
.markdown-body
padding: 15px;
</style>
<!-- Lightweight client-side loader that feature-detects and load polyfills only when necessary -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<!-- Load the element definition -->
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
<!-- Simply set the `src` attribute to your MD file and win -->
</head>
<body>
<div class="markdown-body">
<zero-md src="README.md">
</zero-md>
</div>
</body>
</html>
如果你使用 nodejs,你可以在你的 readme.md 文件中添加一个路由器
app.get('/README.md', function (req, res)
res.sendFile(path.join(__dirname, "README.md"));
)
【讨论】:
以上是关于读取所有 .md 文件,将它们转换为 html 并发送它们的主要内容,如果未能解决你的问题,请参考以下文章