aboutsummaryrefslogtreecommitdiff
path: root/lib/document-to-html.js
blob: 64672eea08e9fcb6c650a25b95ada83fbf513364 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
var q = require("q");
var async = require("async");

var htmlPaths = require("./html-paths");
var HtmlGenerator = require("./html-generator").HtmlGenerator;

exports.DocumentConverter = DocumentConverter;


function DocumentConverter(options) {
    options = options || {};
    var defaultParagraphStyle = options.defaultParagraphStyle || htmlPaths.topLevelElement("p");
    
    var paragraphStyleMap = options.paragraphStyleMap || {};
    var runStyleMap = options.runStyleMap || {};
    
    function convertToHtml(document) {
        var html = new HtmlGenerator();
        
        return q.nfcall(elementToHtml, document, html).then(function() {
            html.closeAll();
            
            return {
                html: html.asString()
            };
        });
    }
    
    function convertElements(elements, html, callback) {
        async.eachSeries(elements, function(element, callback) {
            return elementToHtml(element, html, callback);
        }, callback);
    }

    function elementToHtml(element, html, callback) {
        var handler = elementConverters[element.type];
        if (handler) {
            handler(element, html, callback);
        } else {
            callback();
        }
    }
    
    function convertParagraph(element, html, callback) {
        html.satisfyPath(styleForParagraph(element));
        convertElements(element.children, html, callback);
    }
    
    function styleForParagraph(element) {
        return paragraphStyleMap[element.styleName] || defaultParagraphStyle;
    }
    
    function convertRun(run, html, callback) {
        var runHtml = new HtmlGenerator();
        if (run.styleName) {
            var style = runStyleMap[run.styleName];
            if (style) {
                runHtml.satisfyPath(style);
            }
        }
        if (run.isBold) {
            runHtml.open(htmlPaths.element("strong"));
        }
        if (run.isItalic) {
            runHtml.open(htmlPaths.element("em"));
        }
        convertElements(run.children, runHtml, function(err) {
            if (err) {
                callback(err);
            } else {
                runHtml.closeAll();
                html.append(runHtml);
                callback();
            }
        });
    }

    var elementConverters = {
        "document": function(document, html, callback) {
            convertElements(document.children, html, callback);
        },
        "paragraph": convertParagraph,
        "run": convertRun,
        "text": function(element, html, callback) {
            html.text(element.value);
            callback();
        },
        "hyperlink": function(element, html, callback) {
            html.open(htmlPaths.element("a", {href: element.href}));
            convertElements(element.children, html, function(err) {
                if (err) {
                    callback(err);
                } else {
                    html.close();
                    callback();
                }
            });
        },
        "image": function(element, html, callback) {
            element.read("base64").then(function(imageBuffer) {
                // TODO: set alt attribute to wp:inline/wp:docPr/@descr
                var src = "data:image/png;base64," + imageBuffer;
                var attributes = {src: src};
                if (element.altText) {
                    attributes.alt = element.altText;
                }
                html.selfClosing(htmlPaths.element("img", attributes));
                callback();
            }).fail(callback);
        }
    };
    return {
        convertToHtml: convertToHtml
    }
}