美文网首页
五分钟速成!用nodejs将doc文件转成html

五分钟速成!用nodejs将doc文件转成html

作者: 景阳冈大虫在此 | 来源:发表于2019-12-03 15:11 被阅读0次

经常有一些将doc文件转换成HTML的需求,比如说明、协议之类的。虽然有https://word2cleanhtml.com/ 这种神器,像下图这样

https://word2cleanhtml.com/

可以直接将doc内容粘贴到剪贴板上,即可得到对应的html。但是,复制粘贴也是个体力活,如果一天突然要做10个这样的文档,可能真的要抓狂了。基于此目的,一起来做个脚本一键傻瓜式生成HTML吧。

首先,我们脚本的主角是mammoth ,这个东西可以读取doc文档,并把内容给转换出来。
准备工作就是安装示例文档里的两个依赖

npm install mammoth
npm install underscore

文档里给的转换html的示例是这样的。

var mammoth = require("mammoth");
 
mammoth.convertToHtml({path: "path/to/document.docx"})
    .then(function(result){
        var html = result.value; // The generated HTML
        var messages = result.messages; // Any messages, such as warnings during conversion
    })
    .done();

可以试一试,会发现做出来的html效果会生成strong、p、tr、td这种标签,套上head、body、css之后页面就非常完整了,可是一些特殊的效果,比如说下划线u就没有。
怎么让他们出现呢?可以直接在文档里搜下划线的英文Underline,找到这条说明


underline说明

原来在转换的过程中,下划线被忽略了,文档里也给了解决方法。可以显式地设置下划线转换成的标签去让下划线生效,像这样。

var options = {
    styleMap: ['u => u'],
};

然后,我发现,生成的页面没有带class样式。其实在doc文档里面,有些行是居中效果的,如何做到居中效果在页面里也生效呢?
我们在template里写一个.center样式,然后options里试一试这个功能。

function transformElement(element) {
    if (element.children) {
        var children = _.map(element.children, transformElement);
        element = { ...element, children: children };
    }
    if (element.type === 'paragraph') {
        element = transformParagraph(element);
    }
    return element;
}

function transformParagraph(element) {
    if (element.alignment === 'center' && !element.styleId) {
        return { ...element, styleName: 'center' }; // 给标签增加style-name
    } else {
        return element;
    }
}

var options = {
    styleMap: ['u => u', "p[style-name='center'] => p.center"], // 在这里,将这个规则转换成样式名
    transformDocument: transformElement,
};

以下是完整的生成脚本。

var mammoth = require('mammoth');
const fs = require('fs');
const _ = require('underscore');
const template = require('./template');

const filesPath = './测试的文档.docx';
function transformElement(element) {
    if (element.children) {
        var children = _.map(element.children, transformElement);
        element = { ...element, children: children };
    }
    if (element.type === 'paragraph') {
        element = transformParagraph(element);
    }
    return element;
}

function transformParagraph(element) {
    if (element.alignment === 'center' && !element.styleId) {
        return { ...element, styleName: 'center' };
    } else {
        return element;
    }
}

var options = {
    styleMap: ['u => u', "p[style-name='center'] => p.center"],
    transformDocument: transformElement,
};
mammoth
    .convertToHtml({ path: filesPath }, options)
    .then(function(result) {
        var html = result.value; // The generated HTML
        var messages = result.messages; // Any messages, such as warnings during conversion
        fs.writeFile('file/' + filesPath.match(/^(?:.\/)(.*)(?:\.docx)$/)[1] + '.html', template(html), res => {
            console.log('文件写入成功:');
        });
    })
    .done();
// template.js,包含样式的完整html生成方法
module.exports = function template(str) {
    let htmlTemple1 = getHtmlTemple1(str.match(/[^><]+(?=<\/p>)/gim)[0]);
    return `${htmlTemple1}${str}${htmlTemple2}`;
};
function getHtmlTemple1(title) {
    return `<!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <meta
                name="viewport"
                content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"
            />
            <link href="//www.ppdaicdn.com/favicon.ico" rel="shortcut icon" />
            <link href="./common/common.css"/>
            <link href="./common/protocol.css"/>
            <title>${title}</title>
            <meta http-equiv="Cache-Control" content="no-cache" />
            <meta http-equiv="Pragma" content="no-cache" />
            <meta http-equiv="expires" content="0" />
            <meta name="format-detection" content="telephone=no" />
            <meta name="apple-mobile-web-app-capable" content="yes" />
            <meta name="applicable-device" content="mobile" />
            <style>
            body {
                color: #384369;
                background: #fff;
                margin: 0;
                font-size: 3.7333vw;
                display: flex;
                flex-direction: column;
                overflow-x: hidden;
                margin:0 auto;
                padding:3vw;
            }
            p{
                border: none;
                margin: 0;
                padding: 0;
                line-height:6vw;
                margin-bottom:1vw
            }
            .container>p:first-child{
                width: 100%;
                text-align: center;
                font-size: 5.8667vw;
                font-weight: 700;
                margin-top: 5vw;
                margin-bottom: 7vw;
            }
            .container {
                display: flex;
                flex-direction: column;
                flex: 1;
                overflow-x: hidden;
                /* padding: 5.3333vw; */
                background: #fff;
                -webkit-overflow-scrolling: touch;
            }
            .center{
                text-align: center;
            }
            pre {
                font-size: 3.2vw;
                transform: scale(0.8);
                transform-origin: 0;
            }
    
            .title {
                width: 100%;
                text-align: center;
                font-size: 5.8667vw;
                font-weight: 700;
                margin-top: 5vw;
                margin-bottom: 7vw;
            }
    
            .service-wrap-title {
                color: #384369;
                font-size: 4.2667vw;
                display: inline-block;
                padding: 1.3333vw 0;
                font-weight: 600;
            }
    
            .service-wrap-ele {
                margin: 0;
                color: #384369;
                padding-bottom: 0;
            }
    
            .service-wrap-ele span {
                min-width: 12vw;
                display: inline-block;
                text-align: center;
                border-bottom: solid 1px;
                line-height: 0.9;
                padding: 0 6px;
            }
    
            table {
                color: #384369;
                border-right: 0.2667vw solid #384369;
                border-bottom: 0.2667vw solid #384369;
                border-color: #384369;
                border-collapse: collapse;
                border-spacing: 0;
                margin: 2vw 0;
                width: 100%;
                box-sizing:border-box;
            }
    
            table td {
                border-left: 0.2667vw solid #384369;
                border-top: 0.2667vw solid #384369;
                width: 53.3333vw;
                text-align: left;
                height: 9.3333vw;
            }
            
            th{
                text-align: center !important;
            }

            tr>td:first-child strong {
                text-align: center !important;
                width: 100%;
                display: block;
            }
        
            th,
            td {
            padding: 0 1.2vw;
            font-weight: normal;
            word-wrap: break-word;
            word-break: break-all;
            box-sizing: border-box;
            -webkit-box-sizing: border-box;
            }
        
            .bottom-btn-container {
                height: 13.3333vw;
                background: #fff;
                border-top: 0.1333vw solid #f0eded;
                display: flex;
                justify-content: space-between;
                padding: 0 5.3333vw;
                box-sizing: border-box;
            }
    
            .bottom-btn-container span {
                display: inline-block;
                line-height: 13.3333vw;
                font-size: 3.2vw;
                color: #6685ed;
            }
        </style>
        </head>
        <body><div class="container">`;
}

const htmlTemple2 = `</div></body></html>`;

这样一来,就算一天十个文档也是分分钟的事情了。

相关文章

网友评论

      本文标题:五分钟速成!用nodejs将doc文件转成html

      本文链接:https://www.haomeiwen.com/subject/zivcgctx.html