aboutsummaryrefslogtreecommitdiff
path: root/lib/document-to-html.js
blob: da1a69f21043173babb0e4746331f89dd45e7875 (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
116
117
118
var q = require("q");

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 elementToHtml(document, html)
            .then(function() {
                html.closeAll();
                
                return {
                    html: html.asString()
                }; 
            });
    }
    
    function convertElements(elements, html) {
        return forEachPromise(elements, function(element) {
            return elementToHtml(element, html);
        });
    }

    function elementToHtml(element, html) {
        var handler = elementConverters[element.type];
        if (handler) {
            return q.when(handler(element, html));
        } else {
            return q.when();
        }
    }
    
    function convertParagraph(element, html) {
        html.satisfyPath(styleForParagraph(element));
        return convertElements(element.children, html);
    }
    
    function styleForParagraph(element) {
        return paragraphStyleMap[element.styleName] || defaultParagraphStyle;
    }
    
    function convertRun(run, html) {
        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"));
        }
        return convertElements(run.children, runHtml)
            .then(function() {
                runHtml.closeAll();
                html.append(runHtml);
            });
    }

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

function forEachPromise(array, func) {
    var index = -1;
    return next();
    
    function next() {
        index++;
        if (index < array.length) {
            return q.when(func(array[index]))
                .then(next);
        } else {
            return q.when();
        }
    }
}