公司的新人文档要根据角色来生成不一样的word文档,但是里面存在大量的重复内容,每次增加删除一个内容需要更新所有的文档,维护起来太麻烦,加上本人喜欢用markdown写文档,所以我就研究了一下如何通过模板生成markdown和word。
github
如果是管理员的话额外显示条目3,并且有欢迎您,管理员+名称,普通员工只显示普通员工+名称
## 注意事项1
+ 条目1
+ 条目2
<% if (admin) { %>+ 条目3<% } %>
<% if (admin) { %>
欢迎您,管理员<%= userName %>
<% } else { %>
欢迎您,普通员工<%= userName %>
<% } %>
![图1](./static/1.png)
/**
* @description 替换模板文件中的变量
* @param {*} tempPath 模板路劲
* @param {*} options 需要替换的变量
*/
function renderFile(tempPath, options) {
return new Promise((resolve, reject) => {
ejs.renderFile(tempPath, options, function (err, result) {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
}
/**
* @param {String} outputPath 输出文件的路径
*/
function renderOutput(outputPath, content) {
return new Promise((resolve, reject) => {
fs.writeFile(outputPath, content, (err) => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
通过传入不同的options我们可以发现已经可以实现动态内容,以及区分角色
markdown 到word需要2步,第一步是用marked
将markdown转成html,然后使用html-docx-js
将html转为docx
/**
*
* @param {*} markdownPath markdown的路径
* @param {*} outputPath 输出路径
*/
function renderMarkdownToWord(markdownPath, outputPath) {
return new Promise((resolve, reject) => {
fs.readFile(markdownPath, "utf8", function (err, file) {
if (err) {
reject(err);
return;
}
const result = getHtml(marked(file));
renderOutput(outputPath, html2Docx.asBlob(result));
});
});
}
/**
* @description 修改样式
* @param {*} template 渲染内容
*/
function getHtml(template) {
return `
${template}
`;
}
因为我们所有的图片都在 `output/img` 下,所以生成的markdown可以直接访问,但是word的路径是错误的,于是我就想生成word的时候直接将图片转为base64
/**
*
* @param {*} imgPath 图片路径
*/
function renderImgToBase64(imgPath) {
let bitmap = fs.readFileSync(imgPath);
return (
"data:image/png;base64," + Buffer.from(bitmap, "binary").toString("base64")
); // base64编码
}
到此本文内容差不多了
模板引擎很多其中pug
来到现在这家公司才接触的,但是本人看着语法不是很习惯还是习惯用Ejs
或者underscore
,本文用 Ejs
作为模板引擎
let people = ['geddy', 'neil', 'alex'];
let html = ejs.render('<%= people.join(", "); %>', {people: people}); // echo -> geddy, neil, alex
生成word采用 html-docx-js
本文所有的内容都已上传
github