nodejs动态生成word文档

背景

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

功能如下

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

github

假设新人文档如下

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


## 注意事项1
 + 条目1
 + 条目2
 <% if (admin) { %>+ 条目3<% } %>

<% if (admin) { %>

欢迎您,管理员<%= userName %>

<% } else { %>

欢迎您,普通员工<%= userName %>

<% } %> ![图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 `
    
    
    
        
        
        
    
    
        
${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编码
}

修改renderMarkdownToWord方法
nodejs动态生成word文档_第1张图片

到此本文内容差不多了

技术选型

模板引擎

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

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

生成word

生成word采用 html-docx-js

github

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

你可能感兴趣的:(nodejs动态生成word文档)