@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.
Files changed (118) hide show
  1. package/.eslintrc.json +75 -0
  2. package/.github/ISSUE_TEMPLATE.md +12 -0
  3. package/.github/pull_request_template.md +3 -0
  4. package/.github/workflows/tests.yml +26 -0
  5. package/LICENSE +22 -0
  6. package/NEWS +530 -0
  7. package/README.md +37 -0
  8. package/bin/mammoth +38 -0
  9. package/browser/docx/files.js +14 -0
  10. package/browser/unzip.js +12 -0
  11. package/changes.json +34 -0
  12. package/lib/document-to-html.js +469 -0
  13. package/lib/documents.js +254 -0
  14. package/lib/docx/body-reader.js +798 -0
  15. package/lib/docx/comments-reader.js +31 -0
  16. package/lib/docx/content-types-reader.js +58 -0
  17. package/lib/docx/document-xml-reader.js +30 -0
  18. package/lib/docx/docx-reader.js +226 -0
  19. package/lib/docx/files.js +80 -0
  20. package/lib/docx/notes-reader.js +28 -0
  21. package/lib/docx/numbering-xml.js +111 -0
  22. package/lib/docx/office-xml-reader.js +73 -0
  23. package/lib/docx/relationships-reader.js +43 -0
  24. package/lib/docx/style-map.js +75 -0
  25. package/lib/docx/styles-reader.js +90 -0
  26. package/lib/docx/uris.js +21 -0
  27. package/lib/html/ast.js +51 -0
  28. package/lib/html/index.js +41 -0
  29. package/lib/html/simplify.js +88 -0
  30. package/lib/images.js +31 -0
  31. package/lib/index.d.ts +86 -0
  32. package/lib/index.js +111 -0
  33. package/lib/main.js +63 -0
  34. package/lib/options-reader.js +107 -0
  35. package/lib/promises.js +42 -0
  36. package/lib/raw-text.js +14 -0
  37. package/lib/results.js +72 -0
  38. package/lib/style-reader.js +365 -0
  39. package/lib/styles/document-matchers.js +100 -0
  40. package/lib/styles/html-paths.js +75 -0
  41. package/lib/styles/parser/tokeniser.js +30 -0
  42. package/lib/transforms.js +62 -0
  43. package/lib/underline.js +11 -0
  44. package/lib/unzip.js +20 -0
  45. package/lib/writers/html-writer.js +159 -0
  46. package/lib/writers/index.js +14 -0
  47. package/lib/writers/markdown-writer.js +163 -0
  48. package/lib/xml/index.js +8 -0
  49. package/lib/xml/nodes.js +70 -0
  50. package/lib/xml/reader.js +69 -0
  51. package/lib/xml/writer.js +61 -0
  52. package/lib/xml/xmldom.js +23 -0
  53. package/lib/zipfile.js +72 -0
  54. package/mammoth.browser.js +22096 -0
  55. package/mammoth.browser.min.js +20 -0
  56. package/package.json +106 -0
  57. package/test/.eslintrc.json +7 -0
  58. package/test/document-to-html.tests.js +892 -0
  59. package/test/docx/body-reader.tests.js +2037 -0
  60. package/test/docx/comments-reader.tests.js +53 -0
  61. package/test/docx/content-types-reader.tests.js +45 -0
  62. package/test/docx/document-matchers.js +42 -0
  63. package/test/docx/document-xml-reader.tests.js +41 -0
  64. package/test/docx/docx-reader.tests.js +179 -0
  65. package/test/docx/files.tests.js +107 -0
  66. package/test/docx/notes-reader.tests.js +36 -0
  67. package/test/docx/numbering-xml.tests.js +183 -0
  68. package/test/docx/office-xml-reader.tests.js +41 -0
  69. package/test/docx/relationships-reader.tests.js +65 -0
  70. package/test/docx/style-map.tests.js +113 -0
  71. package/test/docx/styles-reader.tests.js +143 -0
  72. package/test/docx/testing.js +12 -0
  73. package/test/docx/uris.tests.js +22 -0
  74. package/test/html/simplify.tests.js +141 -0
  75. package/test/html/write.tests.js +42 -0
  76. package/test/images.tests.js +112 -0
  77. package/test/main.tests.js +89 -0
  78. package/test/mammoth.tests.js +523 -0
  79. package/test/mocha.opts +1 -0
  80. package/test/options-reader.tests.js +63 -0
  81. package/test/raw-text.tests.js +61 -0
  82. package/test/results.tests.js +15 -0
  83. package/test/style-reader.tests.js +291 -0
  84. package/test/styles/document-matchers.tests.js +91 -0
  85. package/test/styles/html-paths.tests.js +20 -0
  86. package/test/styles/parser/tokeniser.tests.js +104 -0
  87. package/test/test-data/comments.docx +0 -0
  88. package/test/test-data/embedded-style-map.docx +0 -0
  89. package/test/test-data/empty.docx +0 -0
  90. package/test/test-data/empty.zip +0 -0
  91. package/test/test-data/endnotes.docx +0 -0
  92. package/test/test-data/external-picture.docx +0 -0
  93. package/test/test-data/footnote-hyperlink.docx +0 -0
  94. package/test/test-data/footnotes.docx +0 -0
  95. package/test/test-data/hello.zip +0 -0
  96. package/test/test-data/hyperlinks/word/_rels/document.xml.rels +10 -0
  97. package/test/test-data/hyperlinks/word/document.xml +18 -0
  98. package/test/test-data/simple/word/document.xml +18 -0
  99. package/test/test-data/simple-list.docx +0 -0
  100. package/test/test-data/single-paragraph.docx +0 -0
  101. package/test/test-data/strict-format.docx +0 -0
  102. package/test/test-data/strikethrough.docx +0 -0
  103. package/test/test-data/tables.docx +0 -0
  104. package/test/test-data/text-box.docx +0 -0
  105. package/test/test-data/tiny-picture-target-base-relative.docx +0 -0
  106. package/test/test-data/tiny-picture.docx +0 -0
  107. package/test/test-data/tiny-picture.png +0 -0
  108. package/test/test-data/underline.docx +0 -0
  109. package/test/test-data/utf8-bom.docx +0 -0
  110. package/test/test.js +11 -0
  111. package/test/testing.js +55 -0
  112. package/test/transforms.tests.js +125 -0
  113. package/test/unzip.tests.js +38 -0
  114. package/test/writers/html-writer.tests.js +133 -0
  115. package/test/writers/markdown-writer.tests.js +304 -0
  116. package/test/xml/reader.tests.js +85 -0
  117. package/test/xml/writer.tests.js +81 -0
  118. 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
+ }
@@ -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
+ }
@@ -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
+ }