nodejs动态生成word文档

2021年10月3日 11点热度 0条评论 来源: vincentchenzq

背景

公司的新人文档要根据角色来生成不一样的word文档,但是里面存在大量的重复内容,每次增加删除一个内容需要更新所有的文档,维护起来太麻烦,加上本人喜欢用markdown写文档,所以我就研究了一下如何通过模板生成markdown和word。

功能如下

  • 重复内容维护在一个地方
  • 输出markdown
  • 输出word
  • 支持本地图片

github

假设新人文档如下

如果是管理员的话额外显示条目3,并且有欢迎您,管理员+名称,普通员工只显示普通员工+名称

<!-- template/welcome.md -->
## 注意事项1
 + 条目1
 + 条目2
 <% if (admin) { %>+ 条目3<% } %>

<% if (admin) { %>
<h2>欢迎您,管理员<%= userName %></h2>
<% } else { %>
<h3> 欢迎您,普通员工<%= userName %> </h3>
<% } %>    

![图1](./static/1.png)

输出到markdown

/** * @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我们可以发现已经可以实现动态内容,以及区分角色

输出到word

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 ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <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}}} </style> </head> <body> <div class="markdown-body"> ${ template} </div> </body> </html> `;
}

支持本地图片

因为我们所有的图片都在 `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编码
}

修改renderMarkdownToWord方法

到此本文内容差不多了

技术选型

模板引擎

模板引擎很多其中pug来到现在这家公司才接触的,但是本人看着语法不是很习惯还是习惯用Ejs 或者underscore,本文用 Ejs作为模板引擎

    let people = ['geddy', 'neil', 'alex'];
    let html = ejs.render('<%= people.join(", "); %>', { people: people}); // echo -> geddy, neil, alex

生成word

生成word采用 html-docx-js

github

本文所有的内容都已上传
github

    原文作者:vincentchenzq
    原文地址: https://blog.csdn.net/vincentchenzq/article/details/107578194
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。