@depup/mammoth 1.12.0-depup.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +75 -0
- package/.github/ISSUE_TEMPLATE.md +12 -0
- package/.github/pull_request_template.md +3 -0
- package/.github/workflows/tests.yml +26 -0
- package/LICENSE +22 -0
- package/NEWS +530 -0
- package/README.md +37 -0
- package/bin/mammoth +38 -0
- package/browser/docx/files.js +14 -0
- package/browser/unzip.js +12 -0
- package/changes.json +34 -0
- package/lib/document-to-html.js +469 -0
- package/lib/documents.js +254 -0
- package/lib/docx/body-reader.js +798 -0
- package/lib/docx/comments-reader.js +31 -0
- package/lib/docx/content-types-reader.js +58 -0
- package/lib/docx/document-xml-reader.js +30 -0
- package/lib/docx/docx-reader.js +226 -0
- package/lib/docx/files.js +80 -0
- package/lib/docx/notes-reader.js +28 -0
- package/lib/docx/numbering-xml.js +111 -0
- package/lib/docx/office-xml-reader.js +73 -0
- package/lib/docx/relationships-reader.js +43 -0
- package/lib/docx/style-map.js +75 -0
- package/lib/docx/styles-reader.js +90 -0
- package/lib/docx/uris.js +21 -0
- package/lib/html/ast.js +51 -0
- package/lib/html/index.js +41 -0
- package/lib/html/simplify.js +88 -0
- package/lib/images.js +31 -0
- package/lib/index.d.ts +86 -0
- package/lib/index.js +111 -0
- package/lib/main.js +63 -0
- package/lib/options-reader.js +107 -0
- package/lib/promises.js +42 -0
- package/lib/raw-text.js +14 -0
- package/lib/results.js +72 -0
- package/lib/style-reader.js +365 -0
- package/lib/styles/document-matchers.js +100 -0
- package/lib/styles/html-paths.js +75 -0
- package/lib/styles/parser/tokeniser.js +30 -0
- package/lib/transforms.js +62 -0
- package/lib/underline.js +11 -0
- package/lib/unzip.js +20 -0
- package/lib/writers/html-writer.js +159 -0
- package/lib/writers/index.js +14 -0
- package/lib/writers/markdown-writer.js +163 -0
- package/lib/xml/index.js +8 -0
- package/lib/xml/nodes.js +70 -0
- package/lib/xml/reader.js +69 -0
- package/lib/xml/writer.js +61 -0
- package/lib/xml/xmldom.js +23 -0
- package/lib/zipfile.js +72 -0
- package/mammoth.browser.js +22096 -0
- package/mammoth.browser.min.js +20 -0
- package/package.json +106 -0
- package/test/.eslintrc.json +7 -0
- package/test/document-to-html.tests.js +892 -0
- package/test/docx/body-reader.tests.js +2037 -0
- package/test/docx/comments-reader.tests.js +53 -0
- package/test/docx/content-types-reader.tests.js +45 -0
- package/test/docx/document-matchers.js +42 -0
- package/test/docx/document-xml-reader.tests.js +41 -0
- package/test/docx/docx-reader.tests.js +179 -0
- package/test/docx/files.tests.js +107 -0
- package/test/docx/notes-reader.tests.js +36 -0
- package/test/docx/numbering-xml.tests.js +183 -0
- package/test/docx/office-xml-reader.tests.js +41 -0
- package/test/docx/relationships-reader.tests.js +65 -0
- package/test/docx/style-map.tests.js +113 -0
- package/test/docx/styles-reader.tests.js +143 -0
- package/test/docx/testing.js +12 -0
- package/test/docx/uris.tests.js +22 -0
- package/test/html/simplify.tests.js +141 -0
- package/test/html/write.tests.js +42 -0
- package/test/images.tests.js +112 -0
- package/test/main.tests.js +89 -0
- package/test/mammoth.tests.js +523 -0
- package/test/mocha.opts +1 -0
- package/test/options-reader.tests.js +63 -0
- package/test/raw-text.tests.js +61 -0
- package/test/results.tests.js +15 -0
- package/test/style-reader.tests.js +291 -0
- package/test/styles/document-matchers.tests.js +91 -0
- package/test/styles/html-paths.tests.js +20 -0
- package/test/styles/parser/tokeniser.tests.js +104 -0
- package/test/test-data/comments.docx +0 -0
- package/test/test-data/embedded-style-map.docx +0 -0
- package/test/test-data/empty.docx +0 -0
- package/test/test-data/empty.zip +0 -0
- package/test/test-data/endnotes.docx +0 -0
- package/test/test-data/external-picture.docx +0 -0
- package/test/test-data/footnote-hyperlink.docx +0 -0
- package/test/test-data/footnotes.docx +0 -0
- package/test/test-data/hello.zip +0 -0
- package/test/test-data/hyperlinks/word/_rels/document.xml.rels +10 -0
- package/test/test-data/hyperlinks/word/document.xml +18 -0
- package/test/test-data/simple/word/document.xml +18 -0
- package/test/test-data/simple-list.docx +0 -0
- package/test/test-data/single-paragraph.docx +0 -0
- package/test/test-data/strict-format.docx +0 -0
- package/test/test-data/strikethrough.docx +0 -0
- package/test/test-data/tables.docx +0 -0
- package/test/test-data/text-box.docx +0 -0
- package/test/test-data/tiny-picture-target-base-relative.docx +0 -0
- package/test/test-data/tiny-picture.docx +0 -0
- package/test/test-data/tiny-picture.png +0 -0
- package/test/test-data/underline.docx +0 -0
- package/test/test-data/utf8-bom.docx +0 -0
- package/test/test.js +11 -0
- package/test/testing.js +55 -0
- package/test/transforms.tests.js +125 -0
- package/test/unzip.tests.js +38 -0
- package/test/writers/html-writer.tests.js +133 -0
- package/test/writers/markdown-writer.tests.js +304 -0
- package/test/xml/reader.tests.js +85 -0
- package/test/xml/writer.tests.js +81 -0
- package/test/zipfile.tests.js +61 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
exports.readOptions = readOptions;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _ = require("underscore");
|
|
5
|
+
|
|
6
|
+
var defaultStyleMap = exports._defaultStyleMap = [
|
|
7
|
+
"p.Heading1 => h1:fresh",
|
|
8
|
+
"p.Heading2 => h2:fresh",
|
|
9
|
+
"p.Heading3 => h3:fresh",
|
|
10
|
+
"p.Heading4 => h4:fresh",
|
|
11
|
+
"p.Heading5 => h5:fresh",
|
|
12
|
+
"p.Heading6 => h6:fresh",
|
|
13
|
+
"p[style-name='Heading 1'] => h1:fresh",
|
|
14
|
+
"p[style-name='Heading 2'] => h2:fresh",
|
|
15
|
+
"p[style-name='Heading 3'] => h3:fresh",
|
|
16
|
+
"p[style-name='Heading 4'] => h4:fresh",
|
|
17
|
+
"p[style-name='Heading 5'] => h5:fresh",
|
|
18
|
+
"p[style-name='Heading 6'] => h6:fresh",
|
|
19
|
+
"p[style-name='heading 1'] => h1:fresh",
|
|
20
|
+
"p[style-name='heading 2'] => h2:fresh",
|
|
21
|
+
"p[style-name='heading 3'] => h3:fresh",
|
|
22
|
+
"p[style-name='heading 4'] => h4:fresh",
|
|
23
|
+
"p[style-name='heading 5'] => h5:fresh",
|
|
24
|
+
"p[style-name='heading 6'] => h6:fresh",
|
|
25
|
+
|
|
26
|
+
// Apple Pages
|
|
27
|
+
"p.Heading => h1:fresh",
|
|
28
|
+
"p[style-name='Heading'] => h1:fresh",
|
|
29
|
+
|
|
30
|
+
"r[style-name='Strong'] => strong",
|
|
31
|
+
|
|
32
|
+
"p[style-name='footnote text'] => p:fresh",
|
|
33
|
+
"r[style-name='footnote reference'] =>",
|
|
34
|
+
"p[style-name='endnote text'] => p:fresh",
|
|
35
|
+
"r[style-name='endnote reference'] =>",
|
|
36
|
+
"p[style-name='annotation text'] => p:fresh",
|
|
37
|
+
"r[style-name='annotation reference'] =>",
|
|
38
|
+
|
|
39
|
+
// LibreOffice
|
|
40
|
+
"p[style-name='Footnote'] => p:fresh",
|
|
41
|
+
"r[style-name='Footnote anchor'] =>",
|
|
42
|
+
"p[style-name='Endnote'] => p:fresh",
|
|
43
|
+
"r[style-name='Endnote anchor'] =>",
|
|
44
|
+
|
|
45
|
+
"p:unordered-list(1) => ul > li:fresh",
|
|
46
|
+
"p:unordered-list(2) => ul|ol > li > ul > li:fresh",
|
|
47
|
+
"p:unordered-list(3) => ul|ol > li > ul|ol > li > ul > li:fresh",
|
|
48
|
+
"p:unordered-list(4) => ul|ol > li > ul|ol > li > ul|ol > li > ul > li:fresh",
|
|
49
|
+
"p:unordered-list(5) => ul|ol > li > ul|ol > li > ul|ol > li > ul|ol > li > ul > li:fresh",
|
|
50
|
+
"p:ordered-list(1) => ol > li:fresh",
|
|
51
|
+
"p:ordered-list(2) => ul|ol > li > ol > li:fresh",
|
|
52
|
+
"p:ordered-list(3) => ul|ol > li > ul|ol > li > ol > li:fresh",
|
|
53
|
+
"p:ordered-list(4) => ul|ol > li > ul|ol > li > ul|ol > li > ol > li:fresh",
|
|
54
|
+
"p:ordered-list(5) => ul|ol > li > ul|ol > li > ul|ol > li > ul|ol > li > ol > li:fresh",
|
|
55
|
+
|
|
56
|
+
"r[style-name='Hyperlink'] =>",
|
|
57
|
+
|
|
58
|
+
"p[style-name='Normal'] => p:fresh",
|
|
59
|
+
|
|
60
|
+
// Apple Pages
|
|
61
|
+
"p.Body => p:fresh",
|
|
62
|
+
"p[style-name='Body'] => p:fresh"
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
var standardOptions = exports._standardOptions = {
|
|
66
|
+
externalFileAccess: false,
|
|
67
|
+
transformDocument: identity,
|
|
68
|
+
includeDefaultStyleMap: true,
|
|
69
|
+
includeEmbeddedStyleMap: true
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function readOptions(options) {
|
|
73
|
+
options = options || {};
|
|
74
|
+
return _.extend({}, standardOptions, options, {
|
|
75
|
+
customStyleMap: readStyleMap(options.styleMap),
|
|
76
|
+
readStyleMap: function() {
|
|
77
|
+
var styleMap = this.customStyleMap;
|
|
78
|
+
if (this.includeEmbeddedStyleMap) {
|
|
79
|
+
styleMap = styleMap.concat(readStyleMap(this.embeddedStyleMap));
|
|
80
|
+
}
|
|
81
|
+
if (this.includeDefaultStyleMap) {
|
|
82
|
+
styleMap = styleMap.concat(defaultStyleMap);
|
|
83
|
+
}
|
|
84
|
+
return styleMap;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readStyleMap(styleMap) {
|
|
90
|
+
if (!styleMap) {
|
|
91
|
+
return [];
|
|
92
|
+
} else if (_.isString(styleMap)) {
|
|
93
|
+
return styleMap.split("\n")
|
|
94
|
+
.map(function(line) {
|
|
95
|
+
return line.trim();
|
|
96
|
+
})
|
|
97
|
+
.filter(function(line) {
|
|
98
|
+
return line !== "" && line.charAt(0) !== "#";
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
return styleMap;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function identity(value) {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
package/lib/promises.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
var bluebird = require("bluebird/js/release/promise")();
|
|
3
|
+
|
|
4
|
+
exports.defer = defer;
|
|
5
|
+
exports.when = bluebird.resolve;
|
|
6
|
+
exports.resolve = bluebird.resolve;
|
|
7
|
+
exports.all = bluebird.all;
|
|
8
|
+
exports.props = bluebird.props;
|
|
9
|
+
exports.reject = bluebird.reject;
|
|
10
|
+
exports.promisify = bluebird.promisify;
|
|
11
|
+
exports.mapSeries = bluebird.mapSeries;
|
|
12
|
+
exports.attempt = bluebird.attempt;
|
|
13
|
+
|
|
14
|
+
exports.nfcall = function(func) {
|
|
15
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
16
|
+
var promisedFunc = bluebird.promisify(func);
|
|
17
|
+
return promisedFunc.apply(null, args);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
bluebird.prototype.fail = bluebird.prototype.caught;
|
|
21
|
+
|
|
22
|
+
bluebird.prototype.also = function(func) {
|
|
23
|
+
return this.then(function(value) {
|
|
24
|
+
var returnValue = _.extend({}, value, func(value));
|
|
25
|
+
return bluebird.props(returnValue);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function defer() {
|
|
30
|
+
var resolve;
|
|
31
|
+
var reject;
|
|
32
|
+
var promise = new bluebird.Promise(function(resolveArg, rejectArg) {
|
|
33
|
+
resolve = resolveArg;
|
|
34
|
+
reject = rejectArg;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
resolve: resolve,
|
|
39
|
+
reject: reject,
|
|
40
|
+
promise: promise
|
|
41
|
+
};
|
|
42
|
+
}
|
package/lib/raw-text.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var documents = require("./documents");
|
|
2
|
+
|
|
3
|
+
function convertElementToRawText(element) {
|
|
4
|
+
if (element.type === "text") {
|
|
5
|
+
return element.value;
|
|
6
|
+
} else if (element.type === documents.types.tab) {
|
|
7
|
+
return "\t";
|
|
8
|
+
} else {
|
|
9
|
+
var tail = element.type === "paragraph" ? "\n\n" : "";
|
|
10
|
+
return (element.children || []).map(convertElementToRawText).join("") + tail;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
exports.convertElementToRawText = convertElementToRawText;
|
package/lib/results.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
exports.Result = Result;
|
|
5
|
+
exports.success = success;
|
|
6
|
+
exports.warning = warning;
|
|
7
|
+
exports.error = error;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function Result(value, messages) {
|
|
11
|
+
this.value = value;
|
|
12
|
+
this.messages = messages || [];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Result.prototype.map = function(func) {
|
|
16
|
+
return new Result(func(this.value), this.messages);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
Result.prototype.flatMap = function(func) {
|
|
20
|
+
var funcResult = func(this.value);
|
|
21
|
+
return new Result(funcResult.value, combineMessages([this, funcResult]));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Result.prototype.flatMapThen = function(func) {
|
|
25
|
+
var that = this;
|
|
26
|
+
return func(this.value).then(function(otherResult) {
|
|
27
|
+
return new Result(otherResult.value, combineMessages([that, otherResult]));
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
Result.combine = function(results) {
|
|
32
|
+
var values = _.flatten(_.pluck(results, "value"));
|
|
33
|
+
var messages = combineMessages(results);
|
|
34
|
+
return new Result(values, messages);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function success(value) {
|
|
38
|
+
return new Result(value, []);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function warning(message) {
|
|
42
|
+
return {
|
|
43
|
+
type: "warning",
|
|
44
|
+
message: message
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function error(exception) {
|
|
49
|
+
return {
|
|
50
|
+
type: "error",
|
|
51
|
+
message: exception.message,
|
|
52
|
+
error: exception
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function combineMessages(results) {
|
|
57
|
+
var messages = [];
|
|
58
|
+
_.flatten(_.pluck(results, "messages"), true).forEach(function(message) {
|
|
59
|
+
if (!containsMessage(messages, message)) {
|
|
60
|
+
messages.push(message);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return messages;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function containsMessage(messages, message) {
|
|
67
|
+
return _.find(messages, isSameMessage.bind(null, message)) !== undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function isSameMessage(first, second) {
|
|
71
|
+
return first.type === second.type && first.message === second.message;
|
|
72
|
+
}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
var lop = require("lop");
|
|
3
|
+
|
|
4
|
+
var documentMatchers = require("./styles/document-matchers");
|
|
5
|
+
var htmlPaths = require("./styles/html-paths");
|
|
6
|
+
var tokenise = require("./styles/parser/tokeniser").tokenise;
|
|
7
|
+
var results = require("./results");
|
|
8
|
+
|
|
9
|
+
exports.readHtmlPath = readHtmlPath;
|
|
10
|
+
exports.readDocumentMatcher = readDocumentMatcher;
|
|
11
|
+
exports.readStyle = readStyle;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function readStyle(string) {
|
|
15
|
+
return parseString(styleRule, string);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createStyleRule() {
|
|
19
|
+
return lop.rules.sequence(
|
|
20
|
+
lop.rules.sequence.capture(documentMatcherRule()),
|
|
21
|
+
lop.rules.tokenOfType("whitespace"),
|
|
22
|
+
lop.rules.tokenOfType("arrow"),
|
|
23
|
+
lop.rules.sequence.capture(lop.rules.optional(lop.rules.sequence(
|
|
24
|
+
lop.rules.tokenOfType("whitespace"),
|
|
25
|
+
lop.rules.sequence.capture(htmlPathRule())
|
|
26
|
+
).head())),
|
|
27
|
+
lop.rules.tokenOfType("end")
|
|
28
|
+
).map(function(documentMatcher, htmlPath) {
|
|
29
|
+
return {
|
|
30
|
+
from: documentMatcher,
|
|
31
|
+
to: htmlPath.valueOrElse(htmlPaths.empty)
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readDocumentMatcher(string) {
|
|
37
|
+
return parseString(documentMatcherRule(), string);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function documentMatcherRule() {
|
|
41
|
+
var sequence = lop.rules.sequence;
|
|
42
|
+
|
|
43
|
+
var identifierToConstant = function(identifier, constant) {
|
|
44
|
+
return lop.rules.then(
|
|
45
|
+
lop.rules.token("identifier", identifier),
|
|
46
|
+
function() {
|
|
47
|
+
return constant;
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
var paragraphRule = identifierToConstant("p", documentMatchers.paragraph);
|
|
53
|
+
var runRule = identifierToConstant("r", documentMatchers.run);
|
|
54
|
+
|
|
55
|
+
var elementTypeRule = lop.rules.firstOf("p or r or table",
|
|
56
|
+
paragraphRule,
|
|
57
|
+
runRule
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
var styleIdRule = lop.rules.sequence(
|
|
61
|
+
lop.rules.tokenOfType("dot"),
|
|
62
|
+
lop.rules.sequence.cut(),
|
|
63
|
+
lop.rules.sequence.capture(identifierRule)
|
|
64
|
+
).map(function(styleId) {
|
|
65
|
+
return {styleId: styleId};
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
var styleNameMatcherRule = lop.rules.firstOf("style name matcher",
|
|
69
|
+
lop.rules.then(
|
|
70
|
+
lop.rules.sequence(
|
|
71
|
+
lop.rules.tokenOfType("equals"),
|
|
72
|
+
lop.rules.sequence.cut(),
|
|
73
|
+
lop.rules.sequence.capture(stringRule)
|
|
74
|
+
).head(),
|
|
75
|
+
function(styleName) {
|
|
76
|
+
return {styleName: documentMatchers.equalTo(styleName)};
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
lop.rules.then(
|
|
80
|
+
lop.rules.sequence(
|
|
81
|
+
lop.rules.tokenOfType("startsWith"),
|
|
82
|
+
lop.rules.sequence.cut(),
|
|
83
|
+
lop.rules.sequence.capture(stringRule)
|
|
84
|
+
).head(),
|
|
85
|
+
function(styleName) {
|
|
86
|
+
return {styleName: documentMatchers.startsWith(styleName)};
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
var styleNameRule = lop.rules.sequence(
|
|
92
|
+
lop.rules.tokenOfType("open-square-bracket"),
|
|
93
|
+
lop.rules.sequence.cut(),
|
|
94
|
+
lop.rules.token("identifier", "style-name"),
|
|
95
|
+
lop.rules.sequence.capture(styleNameMatcherRule),
|
|
96
|
+
lop.rules.tokenOfType("close-square-bracket")
|
|
97
|
+
).head();
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
var listTypeRule = lop.rules.firstOf("list type",
|
|
101
|
+
identifierToConstant("ordered-list", {isOrdered: true}),
|
|
102
|
+
identifierToConstant("unordered-list", {isOrdered: false})
|
|
103
|
+
);
|
|
104
|
+
var listRule = sequence(
|
|
105
|
+
lop.rules.tokenOfType("colon"),
|
|
106
|
+
sequence.capture(listTypeRule),
|
|
107
|
+
sequence.cut(),
|
|
108
|
+
lop.rules.tokenOfType("open-paren"),
|
|
109
|
+
sequence.capture(integerRule),
|
|
110
|
+
lop.rules.tokenOfType("close-paren")
|
|
111
|
+
).map(function(listType, levelNumber) {
|
|
112
|
+
return {
|
|
113
|
+
list: {
|
|
114
|
+
isOrdered: listType.isOrdered,
|
|
115
|
+
levelIndex: levelNumber - 1
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
function createMatcherSuffixesRule(rules) {
|
|
121
|
+
var matcherSuffix = lop.rules.firstOf.apply(
|
|
122
|
+
lop.rules.firstOf,
|
|
123
|
+
["matcher suffix"].concat(rules)
|
|
124
|
+
);
|
|
125
|
+
var matcherSuffixes = lop.rules.zeroOrMore(matcherSuffix);
|
|
126
|
+
return lop.rules.then(matcherSuffixes, function(suffixes) {
|
|
127
|
+
var matcherOptions = {};
|
|
128
|
+
suffixes.forEach(function(suffix) {
|
|
129
|
+
_.extend(matcherOptions, suffix);
|
|
130
|
+
});
|
|
131
|
+
return matcherOptions;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var paragraphOrRun = sequence(
|
|
136
|
+
sequence.capture(elementTypeRule),
|
|
137
|
+
sequence.capture(createMatcherSuffixesRule([
|
|
138
|
+
styleIdRule,
|
|
139
|
+
styleNameRule,
|
|
140
|
+
listRule
|
|
141
|
+
]))
|
|
142
|
+
).map(function(createMatcher, matcherOptions) {
|
|
143
|
+
return createMatcher(matcherOptions);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
var table = sequence(
|
|
147
|
+
lop.rules.token("identifier", "table"),
|
|
148
|
+
sequence.capture(createMatcherSuffixesRule([
|
|
149
|
+
styleIdRule,
|
|
150
|
+
styleNameRule
|
|
151
|
+
]))
|
|
152
|
+
).map(function(options) {
|
|
153
|
+
return documentMatchers.table(options);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
var bold = identifierToConstant("b", documentMatchers.bold);
|
|
157
|
+
var italic = identifierToConstant("i", documentMatchers.italic);
|
|
158
|
+
var underline = identifierToConstant("u", documentMatchers.underline);
|
|
159
|
+
var strikethrough = identifierToConstant("strike", documentMatchers.strikethrough);
|
|
160
|
+
var allCaps = identifierToConstant("all-caps", documentMatchers.allCaps);
|
|
161
|
+
var smallCaps = identifierToConstant("small-caps", documentMatchers.smallCaps);
|
|
162
|
+
|
|
163
|
+
var highlight = sequence(
|
|
164
|
+
lop.rules.token("identifier", "highlight"),
|
|
165
|
+
lop.rules.sequence.capture(lop.rules.optional(lop.rules.sequence(
|
|
166
|
+
lop.rules.tokenOfType("open-square-bracket"),
|
|
167
|
+
lop.rules.sequence.cut(),
|
|
168
|
+
lop.rules.token("identifier", "color"),
|
|
169
|
+
lop.rules.tokenOfType("equals"),
|
|
170
|
+
lop.rules.sequence.capture(stringRule),
|
|
171
|
+
lop.rules.tokenOfType("close-square-bracket")
|
|
172
|
+
).head()))
|
|
173
|
+
).map(function(color) {
|
|
174
|
+
return documentMatchers.highlight({
|
|
175
|
+
color: color.valueOrElse(undefined)
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
var commentReference = identifierToConstant("comment-reference", documentMatchers.commentReference);
|
|
180
|
+
|
|
181
|
+
var breakMatcher = sequence(
|
|
182
|
+
lop.rules.token("identifier", "br"),
|
|
183
|
+
sequence.cut(),
|
|
184
|
+
lop.rules.tokenOfType("open-square-bracket"),
|
|
185
|
+
lop.rules.token("identifier", "type"),
|
|
186
|
+
lop.rules.tokenOfType("equals"),
|
|
187
|
+
sequence.capture(stringRule),
|
|
188
|
+
lop.rules.tokenOfType("close-square-bracket")
|
|
189
|
+
).map(function(breakType) {
|
|
190
|
+
switch (breakType) {
|
|
191
|
+
case "line":
|
|
192
|
+
return documentMatchers.lineBreak;
|
|
193
|
+
case "page":
|
|
194
|
+
return documentMatchers.pageBreak;
|
|
195
|
+
case "column":
|
|
196
|
+
return documentMatchers.columnBreak;
|
|
197
|
+
default:
|
|
198
|
+
// TODO: handle unknown document matchers
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return lop.rules.firstOf("element type",
|
|
203
|
+
paragraphOrRun,
|
|
204
|
+
table,
|
|
205
|
+
bold,
|
|
206
|
+
italic,
|
|
207
|
+
underline,
|
|
208
|
+
strikethrough,
|
|
209
|
+
allCaps,
|
|
210
|
+
smallCaps,
|
|
211
|
+
highlight,
|
|
212
|
+
commentReference,
|
|
213
|
+
breakMatcher
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function readHtmlPath(string) {
|
|
218
|
+
return parseString(htmlPathRule(), string);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function htmlPathRule() {
|
|
222
|
+
var capture = lop.rules.sequence.capture;
|
|
223
|
+
var whitespaceRule = lop.rules.tokenOfType("whitespace");
|
|
224
|
+
var freshRule = lop.rules.then(
|
|
225
|
+
lop.rules.optional(lop.rules.sequence(
|
|
226
|
+
lop.rules.tokenOfType("colon"),
|
|
227
|
+
lop.rules.token("identifier", "fresh")
|
|
228
|
+
)),
|
|
229
|
+
function(option) {
|
|
230
|
+
return option.map(function() {
|
|
231
|
+
return true;
|
|
232
|
+
}).valueOrElse(false);
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
var separatorRule = lop.rules.then(
|
|
237
|
+
lop.rules.optional(lop.rules.sequence(
|
|
238
|
+
lop.rules.tokenOfType("colon"),
|
|
239
|
+
lop.rules.token("identifier", "separator"),
|
|
240
|
+
lop.rules.tokenOfType("open-paren"),
|
|
241
|
+
capture(stringRule),
|
|
242
|
+
lop.rules.tokenOfType("close-paren")
|
|
243
|
+
).head()),
|
|
244
|
+
function(option) {
|
|
245
|
+
return option.valueOrElse("");
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
var tagNamesRule = lop.rules.oneOrMoreWithSeparator(
|
|
250
|
+
identifierRule,
|
|
251
|
+
lop.rules.tokenOfType("choice")
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
var styleElementRule = lop.rules.sequence(
|
|
255
|
+
capture(tagNamesRule),
|
|
256
|
+
capture(lop.rules.zeroOrMore(attributeOrClassRule)),
|
|
257
|
+
capture(freshRule),
|
|
258
|
+
capture(separatorRule)
|
|
259
|
+
).map(function(tagName, attributesList, fresh, separator) {
|
|
260
|
+
var attributes = {};
|
|
261
|
+
var options = {};
|
|
262
|
+
attributesList.forEach(function(attribute) {
|
|
263
|
+
if (attribute.append && attributes[attribute.name]) {
|
|
264
|
+
attributes[attribute.name] += " " + attribute.value;
|
|
265
|
+
} else {
|
|
266
|
+
attributes[attribute.name] = attribute.value;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
if (fresh) {
|
|
270
|
+
options.fresh = true;
|
|
271
|
+
}
|
|
272
|
+
if (separator) {
|
|
273
|
+
options.separator = separator;
|
|
274
|
+
}
|
|
275
|
+
return htmlPaths.element(tagName, attributes, options);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
return lop.rules.firstOf("html path",
|
|
279
|
+
lop.rules.then(lop.rules.tokenOfType("bang"), function() {
|
|
280
|
+
return htmlPaths.ignore;
|
|
281
|
+
}),
|
|
282
|
+
lop.rules.then(
|
|
283
|
+
lop.rules.zeroOrMoreWithSeparator(
|
|
284
|
+
styleElementRule,
|
|
285
|
+
lop.rules.sequence(
|
|
286
|
+
whitespaceRule,
|
|
287
|
+
lop.rules.tokenOfType("gt"),
|
|
288
|
+
whitespaceRule
|
|
289
|
+
)
|
|
290
|
+
),
|
|
291
|
+
htmlPaths.elements
|
|
292
|
+
)
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
var identifierRule = lop.rules.then(
|
|
297
|
+
lop.rules.tokenOfType("identifier"),
|
|
298
|
+
decodeEscapeSequences
|
|
299
|
+
);
|
|
300
|
+
var integerRule = lop.rules.tokenOfType("integer");
|
|
301
|
+
|
|
302
|
+
var stringRule = lop.rules.then(
|
|
303
|
+
lop.rules.tokenOfType("string"),
|
|
304
|
+
decodeEscapeSequences
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
var escapeSequences = {
|
|
308
|
+
"n": "\n",
|
|
309
|
+
"r": "\r",
|
|
310
|
+
"t": "\t"
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
function decodeEscapeSequences(value) {
|
|
314
|
+
return value.replace(/\\(.)/g, function(match, code) {
|
|
315
|
+
return escapeSequences[code] || code;
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
var attributeRule = lop.rules.sequence(
|
|
320
|
+
lop.rules.tokenOfType("open-square-bracket"),
|
|
321
|
+
lop.rules.sequence.cut(),
|
|
322
|
+
lop.rules.sequence.capture(identifierRule),
|
|
323
|
+
lop.rules.tokenOfType("equals"),
|
|
324
|
+
lop.rules.sequence.capture(stringRule),
|
|
325
|
+
lop.rules.tokenOfType("close-square-bracket")
|
|
326
|
+
).map(function(name, value) {
|
|
327
|
+
return {name: name, value: value, append: false};
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
var classRule = lop.rules.sequence(
|
|
331
|
+
lop.rules.tokenOfType("dot"),
|
|
332
|
+
lop.rules.sequence.cut(),
|
|
333
|
+
lop.rules.sequence.capture(identifierRule)
|
|
334
|
+
).map(function(className) {
|
|
335
|
+
return {name: "class", value: className, append: true};
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
var attributeOrClassRule = lop.rules.firstOf(
|
|
339
|
+
"attribute or class",
|
|
340
|
+
attributeRule,
|
|
341
|
+
classRule
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
function parseString(rule, string) {
|
|
345
|
+
var tokens = tokenise(string);
|
|
346
|
+
var parser = lop.Parser();
|
|
347
|
+
var parseResult = parser.parseTokens(rule, tokens);
|
|
348
|
+
if (parseResult.isSuccess()) {
|
|
349
|
+
return results.success(parseResult.value());
|
|
350
|
+
} else {
|
|
351
|
+
return new results.Result(null, [results.warning(describeFailure(string, parseResult))]);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function describeFailure(input, parseResult) {
|
|
356
|
+
return "Did not understand this style mapping, so ignored it: " + input + "\n" +
|
|
357
|
+
parseResult.errors().map(describeError).join("\n");
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function describeError(error) {
|
|
361
|
+
return "Error was at character number " + error.characterNumber() + ": " +
|
|
362
|
+
"Expected " + error.expected + " but got " + error.actual;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
var styleRule = createStyleRule();
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
exports.paragraph = paragraph;
|
|
2
|
+
exports.run = run;
|
|
3
|
+
exports.table = table;
|
|
4
|
+
exports.bold = new Matcher("bold");
|
|
5
|
+
exports.italic = new Matcher("italic");
|
|
6
|
+
exports.underline = new Matcher("underline");
|
|
7
|
+
exports.strikethrough = new Matcher("strikethrough");
|
|
8
|
+
exports.allCaps = new Matcher("allCaps");
|
|
9
|
+
exports.smallCaps = new Matcher("smallCaps");
|
|
10
|
+
exports.highlight = highlight;
|
|
11
|
+
exports.commentReference = new Matcher("commentReference");
|
|
12
|
+
exports.lineBreak = new BreakMatcher({breakType: "line"});
|
|
13
|
+
exports.pageBreak = new BreakMatcher({breakType: "page"});
|
|
14
|
+
exports.columnBreak = new BreakMatcher({breakType: "column"});
|
|
15
|
+
exports.equalTo = equalTo;
|
|
16
|
+
exports.startsWith = startsWith;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
function paragraph(options) {
|
|
20
|
+
return new Matcher("paragraph", options);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function run(options) {
|
|
24
|
+
return new Matcher("run", options);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function table(options) {
|
|
28
|
+
return new Matcher("table", options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function highlight(options) {
|
|
32
|
+
return new HighlightMatcher(options);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function Matcher(elementType, options) {
|
|
36
|
+
options = options || {};
|
|
37
|
+
this._elementType = elementType;
|
|
38
|
+
this._styleId = options.styleId;
|
|
39
|
+
this._styleName = options.styleName;
|
|
40
|
+
if (options.list) {
|
|
41
|
+
this._listIndex = options.list.levelIndex;
|
|
42
|
+
this._listIsOrdered = options.list.isOrdered;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Matcher.prototype.matches = function(element) {
|
|
47
|
+
return element.type === this._elementType &&
|
|
48
|
+
(this._styleId === undefined || element.styleId === this._styleId) &&
|
|
49
|
+
(this._styleName === undefined || (element.styleName && this._styleName.operator(this._styleName.operand, element.styleName))) &&
|
|
50
|
+
(this._listIndex === undefined || isList(element, this._listIndex, this._listIsOrdered)) &&
|
|
51
|
+
(this._breakType === undefined || this._breakType === element.breakType);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function HighlightMatcher(options) {
|
|
55
|
+
options = options || {};
|
|
56
|
+
this._color = options.color;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
HighlightMatcher.prototype.matches = function(element) {
|
|
60
|
+
return element.type === "highlight" &&
|
|
61
|
+
(this._color === undefined || element.color === this._color);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function BreakMatcher(options) {
|
|
65
|
+
options = options || {};
|
|
66
|
+
this._breakType = options.breakType;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
BreakMatcher.prototype.matches = function(element) {
|
|
70
|
+
return element.type === "break" &&
|
|
71
|
+
(this._breakType === undefined || element.breakType === this._breakType);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
function isList(element, levelIndex, isOrdered) {
|
|
75
|
+
return element.numbering &&
|
|
76
|
+
element.numbering.level == levelIndex &&
|
|
77
|
+
element.numbering.isOrdered == isOrdered;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function equalTo(value) {
|
|
81
|
+
return {
|
|
82
|
+
operator: operatorEqualTo,
|
|
83
|
+
operand: value
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function startsWith(value) {
|
|
88
|
+
return {
|
|
89
|
+
operator: operatorStartsWith,
|
|
90
|
+
operand: value
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function operatorEqualTo(first, second) {
|
|
95
|
+
return first.toUpperCase() === second.toUpperCase();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function operatorStartsWith(first, second) {
|
|
99
|
+
return second.toUpperCase().indexOf(first.toUpperCase()) === 0;
|
|
100
|
+
}
|