@hyperlex/mammoth 1.4.9-beta

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 (112) hide show
  1. package/.eslintrc.json +77 -0
  2. package/.github/ISSUE_TEMPLATE.md +12 -0
  3. package/.idea/mammoth.js.iml +12 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/vcs.xml +6 -0
  6. package/.travis.yml +10 -0
  7. package/LICENSE +22 -0
  8. package/NEWS +373 -0
  9. package/README.md +883 -0
  10. package/bin/mammoth +38 -0
  11. package/browser/docx/files.js +14 -0
  12. package/browser/unzip.js +12 -0
  13. package/lib/document-to-html.js +453 -0
  14. package/lib/documents.js +238 -0
  15. package/lib/docx/body-reader.js +636 -0
  16. package/lib/docx/comments-reader.js +31 -0
  17. package/lib/docx/content-types-reader.js +58 -0
  18. package/lib/docx/document-xml-reader.js +26 -0
  19. package/lib/docx/docx-reader.js +222 -0
  20. package/lib/docx/files.js +67 -0
  21. package/lib/docx/notes-reader.js +28 -0
  22. package/lib/docx/numbering-xml.js +69 -0
  23. package/lib/docx/office-xml-reader.js +58 -0
  24. package/lib/docx/relationships-reader.js +43 -0
  25. package/lib/docx/style-map.js +75 -0
  26. package/lib/docx/styles-reader.js +70 -0
  27. package/lib/docx/uris.js +21 -0
  28. package/lib/html/ast.js +50 -0
  29. package/lib/html/index.js +41 -0
  30. package/lib/html/simplify.js +88 -0
  31. package/lib/images.js +29 -0
  32. package/lib/index.js +115 -0
  33. package/lib/main.js +63 -0
  34. package/lib/options-reader.js +98 -0
  35. package/lib/promises.js +42 -0
  36. package/lib/results.js +72 -0
  37. package/lib/style-reader.js +321 -0
  38. package/lib/styles/document-matchers.js +74 -0
  39. package/lib/styles/html-paths.js +81 -0
  40. package/lib/styles/parser/tokeniser.js +30 -0
  41. package/lib/transforms.js +61 -0
  42. package/lib/underline.js +11 -0
  43. package/lib/unzip.js +22 -0
  44. package/lib/writers/html-writer.js +160 -0
  45. package/lib/writers/index.js +14 -0
  46. package/lib/writers/markdown-writer.js +163 -0
  47. package/lib/xml/index.js +7 -0
  48. package/lib/xml/nodes.js +69 -0
  49. package/lib/xml/reader.js +83 -0
  50. package/lib/xml/writer.js +61 -0
  51. package/lib/zipfile.js +77 -0
  52. package/mammoth.browser.js +32950 -0
  53. package/mammoth.browser.min.js +18 -0
  54. package/package.json +65 -0
  55. package/test/.eslintrc.json +7 -0
  56. package/test/document-to-html.tests.js +834 -0
  57. package/test/docx/body-reader.tests.js +1342 -0
  58. package/test/docx/comments-reader.tests.js +52 -0
  59. package/test/docx/content-types-reader.tests.js +45 -0
  60. package/test/docx/document-matchers.js +37 -0
  61. package/test/docx/docx-reader.tests.js +179 -0
  62. package/test/docx/files.tests.js +94 -0
  63. package/test/docx/notes-reader.tests.js +35 -0
  64. package/test/docx/numbering-xml.tests.js +65 -0
  65. package/test/docx/office-xml-reader.tests.js +24 -0
  66. package/test/docx/relationships-reader.tests.js +65 -0
  67. package/test/docx/style-map.tests.js +112 -0
  68. package/test/docx/styles-reader.tests.js +133 -0
  69. package/test/docx/uris.tests.js +22 -0
  70. package/test/html/simplify.tests.js +134 -0
  71. package/test/html/write.tests.js +42 -0
  72. package/test/images.tests.js +34 -0
  73. package/test/main.tests.js +89 -0
  74. package/test/mammoth.tests.js +429 -0
  75. package/test/mocha.opts +1 -0
  76. package/test/options-reader.tests.js +63 -0
  77. package/test/results.tests.js +15 -0
  78. package/test/style-reader.tests.js +256 -0
  79. package/test/styles/document-matchers.tests.js +71 -0
  80. package/test/styles/html-paths.tests.js +20 -0
  81. package/test/styles/parser/tokeniser.tests.js +104 -0
  82. package/test/test-data/comments.docx +0 -0
  83. package/test/test-data/embedded-style-map.docx +0 -0
  84. package/test/test-data/empty.docx +0 -0
  85. package/test/test-data/empty.zip +0 -0
  86. package/test/test-data/endnotes.docx +0 -0
  87. package/test/test-data/external-picture.docx +0 -0
  88. package/test/test-data/footnote-hyperlink.docx +0 -0
  89. package/test/test-data/footnotes.docx +0 -0
  90. package/test/test-data/hello.zip +0 -0
  91. package/test/test-data/hyperlinks/word/_rels/document.xml.rels +10 -0
  92. package/test/test-data/hyperlinks/word/document.xml +18 -0
  93. package/test/test-data/simple/word/document.xml +18 -0
  94. package/test/test-data/simple-list.docx +0 -0
  95. package/test/test-data/single-paragraph.docx +0 -0
  96. package/test/test-data/strikethrough.docx +0 -0
  97. package/test/test-data/tables.docx +0 -0
  98. package/test/test-data/text-box.docx +0 -0
  99. package/test/test-data/tiny-picture-target-base-relative.docx +0 -0
  100. package/test/test-data/tiny-picture.docx +0 -0
  101. package/test/test-data/tiny-picture.png +0 -0
  102. package/test/test-data/underline.docx +0 -0
  103. package/test/test-data/utf8-bom.docx +0 -0
  104. package/test/test.js +11 -0
  105. package/test/testing.js +55 -0
  106. package/test/transforms.tests.js +125 -0
  107. package/test/unzip.tests.js +38 -0
  108. package/test/writers/html-writer.tests.js +133 -0
  109. package/test/writers/markdown-writer.tests.js +304 -0
  110. package/test/xml/reader.tests.js +85 -0
  111. package/test/xml/writer.tests.js +81 -0
  112. package/test/zipfile.tests.js +59 -0
@@ -0,0 +1,321 @@
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.then(
61
+ classRule,
62
+ function(styleId) {
63
+ return {styleId: styleId};
64
+ }
65
+ );
66
+
67
+ var styleNameMatcherRule = lop.rules.firstOf("style name matcher",
68
+ lop.rules.then(
69
+ lop.rules.sequence(
70
+ lop.rules.tokenOfType("equals"),
71
+ lop.rules.sequence.cut(),
72
+ lop.rules.sequence.capture(stringRule)
73
+ ).head(),
74
+ function(styleName) {
75
+ return {styleName: documentMatchers.equalTo(styleName)};
76
+ }
77
+ ),
78
+ lop.rules.then(
79
+ lop.rules.sequence(
80
+ lop.rules.tokenOfType("startsWith"),
81
+ lop.rules.sequence.cut(),
82
+ lop.rules.sequence.capture(stringRule)
83
+ ).head(),
84
+ function(styleName) {
85
+ return {styleName: documentMatchers.startsWith(styleName)};
86
+ }
87
+ )
88
+ );
89
+
90
+ var styleNameRule = lop.rules.sequence(
91
+ lop.rules.tokenOfType("open-square-bracket"),
92
+ lop.rules.sequence.cut(),
93
+ lop.rules.token("identifier", "style-name"),
94
+ lop.rules.sequence.capture(styleNameMatcherRule),
95
+ lop.rules.tokenOfType("close-square-bracket")
96
+ ).head();
97
+
98
+
99
+ var listTypeRule = lop.rules.firstOf("list type",
100
+ identifierToConstant("ordered-list", {isOrdered: true}),
101
+ identifierToConstant("unordered-list", {isOrdered: false})
102
+ );
103
+ var listRule = sequence(
104
+ lop.rules.tokenOfType("colon"),
105
+ sequence.capture(listTypeRule),
106
+ sequence.cut(),
107
+ lop.rules.tokenOfType("open-paren"),
108
+ sequence.capture(integerRule),
109
+ lop.rules.tokenOfType("close-paren")
110
+ ).map(function(listType, levelNumber) {
111
+ return {
112
+ list: {
113
+ isOrdered: listType.isOrdered,
114
+ levelIndex: levelNumber - 1
115
+ }
116
+ };
117
+ });
118
+
119
+ function createMatcherSuffixesRule(rules) {
120
+ var matcherSuffix = lop.rules.firstOf.apply(
121
+ lop.rules.firstOf,
122
+ ["matcher suffix"].concat(rules)
123
+ );
124
+ var matcherSuffixes = lop.rules.zeroOrMore(matcherSuffix);
125
+ return lop.rules.then(matcherSuffixes, function(suffixes) {
126
+ var matcherOptions = {};
127
+ suffixes.forEach(function(suffix) {
128
+ _.extend(matcherOptions, suffix);
129
+ });
130
+ return matcherOptions;
131
+ });
132
+ }
133
+
134
+ var paragraphOrRun = sequence(
135
+ sequence.capture(elementTypeRule),
136
+ sequence.capture(createMatcherSuffixesRule([
137
+ styleIdRule,
138
+ styleNameRule,
139
+ listRule
140
+ ]))
141
+ ).map(function(createMatcher, matcherOptions) {
142
+ return createMatcher(matcherOptions);
143
+ });
144
+
145
+ var table = sequence(
146
+ lop.rules.token("identifier", "table"),
147
+ sequence.capture(createMatcherSuffixesRule([
148
+ styleIdRule,
149
+ styleNameRule
150
+ ]))
151
+ ).map(function(options) {
152
+ return documentMatchers.table(options);
153
+ });
154
+
155
+ var bold = identifierToConstant("b", documentMatchers.bold);
156
+ var italic = identifierToConstant("i", documentMatchers.italic);
157
+ var underline = identifierToConstant("u", documentMatchers.underline);
158
+ var strikethrough = identifierToConstant("strike", documentMatchers.strikethrough);
159
+ var smallCaps = identifierToConstant("small-caps", documentMatchers.smallCaps);
160
+ var commentReference = identifierToConstant("comment-reference", documentMatchers.commentReference);
161
+
162
+ var breakMatcher = sequence(
163
+ lop.rules.token("identifier", "br"),
164
+ sequence.cut(),
165
+ lop.rules.tokenOfType("open-square-bracket"),
166
+ lop.rules.token("identifier", "type"),
167
+ lop.rules.tokenOfType("equals"),
168
+ sequence.capture(stringRule),
169
+ lop.rules.tokenOfType("close-square-bracket")
170
+ ).map(function(breakType) {
171
+ switch (breakType) {
172
+ case "line":
173
+ return documentMatchers.lineBreak;
174
+ case "page":
175
+ return documentMatchers.pageBreak;
176
+ case "column":
177
+ return documentMatchers.columnBreak;
178
+ default:
179
+ // TODO: handle unknown document matchers
180
+ }
181
+ });
182
+
183
+ return lop.rules.firstOf("element type",
184
+ paragraphOrRun,
185
+ table,
186
+ bold,
187
+ italic,
188
+ underline,
189
+ strikethrough,
190
+ smallCaps,
191
+ commentReference,
192
+ breakMatcher
193
+ );
194
+ }
195
+
196
+ function readHtmlPath(string) {
197
+ return parseString(htmlPathRule(), string);
198
+ }
199
+
200
+ function htmlPathRule() {
201
+ var capture = lop.rules.sequence.capture;
202
+ var whitespaceRule = lop.rules.tokenOfType("whitespace");
203
+ var freshRule = lop.rules.then(
204
+ lop.rules.optional(lop.rules.sequence(
205
+ lop.rules.tokenOfType("colon"),
206
+ lop.rules.token("identifier", "fresh")
207
+ )),
208
+ function(option) {
209
+ return option.map(function() {
210
+ return true;
211
+ }).valueOrElse(false);
212
+ }
213
+ );
214
+
215
+ var separatorRule = lop.rules.then(
216
+ lop.rules.optional(lop.rules.sequence(
217
+ lop.rules.tokenOfType("colon"),
218
+ lop.rules.token("identifier", "separator"),
219
+ lop.rules.tokenOfType("open-paren"),
220
+ capture(stringRule),
221
+ lop.rules.tokenOfType("close-paren")
222
+ ).head()),
223
+ function(option) {
224
+ return option.valueOrElse("");
225
+ }
226
+ );
227
+
228
+ var tagNamesRule = lop.rules.oneOrMoreWithSeparator(
229
+ identifierRule,
230
+ lop.rules.tokenOfType("choice")
231
+ );
232
+
233
+ var styleElementRule = lop.rules.sequence(
234
+ capture(tagNamesRule),
235
+ capture(lop.rules.zeroOrMore(classRule)),
236
+ capture(freshRule),
237
+ capture(separatorRule)
238
+ ).map(function(tagName, classNames, fresh, separator) {
239
+ var attributes = {};
240
+ var options = {};
241
+ if (classNames.length > 0) {
242
+ attributes["class"] = classNames.join(" ");
243
+ }
244
+ if (fresh) {
245
+ options.fresh = true;
246
+ }
247
+ if (separator) {
248
+ options.separator = separator;
249
+ }
250
+ return htmlPaths.element(tagName, attributes, options);
251
+ });
252
+
253
+ return lop.rules.firstOf("html path",
254
+ lop.rules.then(lop.rules.tokenOfType("bang"), function() {
255
+ return htmlPaths.ignore;
256
+ }),
257
+ lop.rules.then(
258
+ lop.rules.zeroOrMoreWithSeparator(
259
+ styleElementRule,
260
+ lop.rules.sequence(
261
+ whitespaceRule,
262
+ lop.rules.tokenOfType("gt"),
263
+ whitespaceRule
264
+ )
265
+ ),
266
+ htmlPaths.elements
267
+ )
268
+ );
269
+ }
270
+
271
+ var identifierRule = lop.rules.then(
272
+ lop.rules.tokenOfType("identifier"),
273
+ decodeEscapeSequences
274
+ );
275
+ var integerRule = lop.rules.tokenOfType("integer");
276
+
277
+ var stringRule = lop.rules.then(
278
+ lop.rules.tokenOfType("string"),
279
+ decodeEscapeSequences
280
+ );
281
+
282
+ var escapeSequences = {
283
+ "n": "\n",
284
+ "r": "\r",
285
+ "t": "\t"
286
+ };
287
+
288
+ function decodeEscapeSequences(value) {
289
+ return value.replace(/\\(.)/g, function(match, code) {
290
+ return escapeSequences[code] || code;
291
+ });
292
+ }
293
+
294
+ var classRule = lop.rules.sequence(
295
+ lop.rules.tokenOfType("dot"),
296
+ lop.rules.sequence.cut(),
297
+ lop.rules.sequence.capture(identifierRule)
298
+ ).head();
299
+
300
+ function parseString(rule, string) {
301
+ var tokens = tokenise(string);
302
+ var parser = lop.Parser();
303
+ var parseResult = parser.parseTokens(rule, tokens);
304
+ if (parseResult.isSuccess()) {
305
+ return results.success(parseResult.value());
306
+ } else {
307
+ return new results.Result(null, [results.warning(describeFailure(string, parseResult))]);
308
+ }
309
+ }
310
+
311
+ function describeFailure(input, parseResult) {
312
+ return "Did not understand this style mapping, so ignored it: " + input + "\n" +
313
+ parseResult.errors().map(describeError).join("\n");
314
+ }
315
+
316
+ function describeError(error) {
317
+ return "Error was at character number " + error.characterNumber() + ": " +
318
+ "Expected " + error.expected + " but got " + error.actual;
319
+ }
320
+
321
+ var styleRule = createStyleRule();
@@ -0,0 +1,74 @@
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.smallCaps = new Matcher("smallCaps");
9
+ exports.commentReference = new Matcher("commentReference");
10
+ exports.lineBreak = new Matcher("break", {breakType: "line"});
11
+ exports.pageBreak = new Matcher("break", {breakType: "page"});
12
+ exports.columnBreak = new Matcher("break", {breakType: "column"});
13
+ exports.equalTo = equalTo;
14
+ exports.startsWith = startsWith;
15
+
16
+
17
+ function paragraph(options) {
18
+ return new Matcher("paragraph", options);
19
+ }
20
+
21
+ function run(options) {
22
+ return new Matcher("run", options);
23
+ }
24
+
25
+ function table(options) {
26
+ return new Matcher("table", options);
27
+ }
28
+
29
+ function Matcher(elementType, options) {
30
+ options = options || {};
31
+ this._elementType = elementType;
32
+ this._styleId = options.styleId;
33
+ this._styleName = options.styleName;
34
+ if (options.list) {
35
+ this._listIndex = options.list.levelIndex;
36
+ this._listIsOrdered = options.list.isOrdered;
37
+ }
38
+ }
39
+
40
+ Matcher.prototype.matches = function(element) {
41
+ return element.type === this._elementType &&
42
+ (this._styleId === undefined || element.styleId === this._styleId) &&
43
+ (this._styleName === undefined || (element.styleName && this._styleName.operator(this._styleName.operand, element.styleName))) &&
44
+ (this._listIndex === undefined || isList(element, this._listIndex, this._listIsOrdered)) &&
45
+ (this._breakType === undefined || this._breakType === element.breakType);
46
+ };
47
+
48
+ function isList(element, levelIndex, isOrdered) {
49
+ return element.numbering &&
50
+ element.numbering.level == levelIndex &&
51
+ element.numbering.isOrdered == isOrdered;
52
+ }
53
+
54
+ function equalTo(value) {
55
+ return {
56
+ operator: operatorEqualTo,
57
+ operand: value
58
+ };
59
+ }
60
+
61
+ function startsWith(value) {
62
+ return {
63
+ operator: operatorStartsWith,
64
+ operand: value
65
+ };
66
+ }
67
+
68
+ function operatorEqualTo(first, second) {
69
+ return first.toUpperCase() === second.toUpperCase();
70
+ }
71
+
72
+ function operatorStartsWith(first, second) {
73
+ return second.toUpperCase().indexOf(first.toUpperCase()) === 0;
74
+ }
@@ -0,0 +1,81 @@
1
+ var _ = require("underscore");
2
+
3
+ var html = require("../html");
4
+
5
+ exports.topLevelElement = topLevelElement;
6
+ exports.elements = elements;
7
+ exports.element = element;
8
+
9
+ function topLevelElement(tagName, attributes, calculateAttributes) {
10
+ return elements([element(tagName, attributes, {fresh: true}, calculateAttributes)]);
11
+ }
12
+
13
+ function elements(elementStyles) {
14
+ return new HtmlPath(elementStyles.map(function(elementStyle) {
15
+ if (_.isString(elementStyle)) {
16
+ return element(elementStyle);
17
+ } else {
18
+ return elementStyle;
19
+ }
20
+ }));
21
+ }
22
+
23
+ function HtmlPath(elements) {
24
+ this._elements = elements;
25
+ }
26
+
27
+ HtmlPath.prototype.wrap = function wrap(children, element) {
28
+ var result = children();
29
+ for (var index = this._elements.length - 1; index >= 0; index--) {
30
+ result = this._elements[index].wrapNodes(result, element);
31
+ }
32
+ return result;
33
+ };
34
+
35
+ function element(tagName, attributes, options, calculateAttributes) {
36
+ options = options || {};
37
+ return new Element(tagName, attributes, options, calculateAttributes);
38
+ }
39
+
40
+ function Element(tagName, attributes, options, calculateAttributes) {
41
+ var tagNames = {};
42
+ if (_.isArray(tagName)) {
43
+ tagName.forEach(function(tagName) {
44
+ tagNames[tagName] = true;
45
+ });
46
+ tagName = tagName[0];
47
+ } else {
48
+ tagNames[tagName] = true;
49
+ }
50
+
51
+ this.tagName = tagName;
52
+ this.tagNames = tagNames;
53
+ this.attributes = attributes || {};
54
+ this.calculateAttributes = calculateAttributes;
55
+ this.fresh = options.fresh;
56
+ this.separator = options.separator;
57
+ }
58
+
59
+ Element.prototype.matchesElement = function(element) {
60
+ return this.tagNames[element.tagName] && _.isEqual(this.attributes || {}, element.attributes || {});
61
+ };
62
+
63
+ Element.prototype.wrap = function wrap(generateNodes, element) {
64
+ return this.wrapNodes(generateNodes(), element);
65
+ };
66
+
67
+ Element.prototype.wrapNodes = function wrapNodes(nodes, element) {
68
+ var attributes = this.attributes;
69
+ if (this.calculateAttributes) {
70
+ attributes = this.calculateAttributes(element);
71
+ }
72
+ var tag = _.extend({}, this, {attributes: attributes});
73
+ return [html.elementWithTag(tag, nodes)];
74
+ };
75
+
76
+ exports.empty = elements([]);
77
+ exports.ignore = {
78
+ wrap: function() {
79
+ return [];
80
+ }
81
+ };
@@ -0,0 +1,30 @@
1
+ var lop = require("lop");
2
+ var RegexTokeniser = lop.RegexTokeniser;
3
+
4
+ exports.tokenise = tokenise;
5
+
6
+ var stringPrefix = "'((?:\\\\.|[^'])*)";
7
+
8
+ function tokenise(string) {
9
+ var identifierCharacter = "(?:[a-zA-Z\\-_]|\\\\.)";
10
+ var tokeniser = new RegexTokeniser([
11
+ {name: "identifier", regex: new RegExp("(" + identifierCharacter + "(?:" + identifierCharacter + "|[0-9])*)")},
12
+ {name: "dot", regex: /\./},
13
+ {name: "colon", regex: /:/},
14
+ {name: "gt", regex: />/},
15
+ {name: "whitespace", regex: /\s+/},
16
+ {name: "arrow", regex: /=>/},
17
+ {name: "equals", regex: /=/},
18
+ {name: "startsWith", regex: /\^=/},
19
+ {name: "open-paren", regex: /\(/},
20
+ {name: "close-paren", regex: /\)/},
21
+ {name: "open-square-bracket", regex: /\[/},
22
+ {name: "close-square-bracket", regex: /\]/},
23
+ {name: "string", regex: new RegExp(stringPrefix + "'")},
24
+ {name: "unterminated-string", regex: new RegExp(stringPrefix)},
25
+ {name: "integer", regex: /([0-9]+)/},
26
+ {name: "choice", regex: /\|/},
27
+ {name: "bang", regex: /(!)/}
28
+ ]);
29
+ return tokeniser.tokenise(string);
30
+ }
@@ -0,0 +1,61 @@
1
+ var _ = require("underscore");
2
+
3
+ exports.paragraph = paragraph;
4
+ exports.run = run;
5
+ exports._elements = elements;
6
+ exports.getDescendantsOfType = getDescendantsOfType;
7
+ exports.getDescendants = getDescendants;
8
+
9
+ function paragraph(transform) {
10
+ return elementsOfType("paragraph", transform);
11
+ }
12
+
13
+ function run(transform) {
14
+ return elementsOfType("run", transform);
15
+ }
16
+
17
+ function elementsOfType(elementType, transform) {
18
+ return elements(function(element) {
19
+ if (element.type === elementType) {
20
+ return transform(element);
21
+ } else {
22
+ return element;
23
+ }
24
+ });
25
+ }
26
+
27
+ function elements(transform) {
28
+ return function transformElement(element) {
29
+ if (element.children) {
30
+ var children = _.map(element.children, transformElement);
31
+ element = _.extend(element, {children: children});
32
+ }
33
+ return transform(element);
34
+ };
35
+ }
36
+
37
+
38
+ function getDescendantsOfType(element, type) {
39
+ return getDescendants(element).filter(function(descendant) {
40
+ return descendant.type === type;
41
+ });
42
+ }
43
+
44
+ function getDescendants(element) {
45
+ var descendants = [];
46
+
47
+ visitDescendants(element, function(descendant) {
48
+ descendants.push(descendant);
49
+ });
50
+
51
+ return descendants;
52
+ }
53
+
54
+ function visitDescendants(element, visit) {
55
+ if (element.children) {
56
+ element.children.forEach(function(child) {
57
+ visitDescendants(child, visit);
58
+ visit(child);
59
+ });
60
+ }
61
+ }
@@ -0,0 +1,11 @@
1
+ var htmlPaths = require("./styles/html-paths");
2
+ var Html = require("./html");
3
+
4
+
5
+ exports.element = element;
6
+
7
+ function element(name) {
8
+ return function(html) {
9
+ return Html.elementWithTag(htmlPaths.element(name), [html]);
10
+ };
11
+ }
package/lib/unzip.js ADDED
@@ -0,0 +1,22 @@
1
+ exports.openZip = openZip;
2
+
3
+ var fs = require("fs");
4
+
5
+ var promises = require("./promises");
6
+ var zipfile = require("./zipfile");
7
+
8
+ exports.openZip = openZip;
9
+
10
+ var readFile = promises.promisify(fs.readFile);
11
+
12
+ function openZip(options) {
13
+ if (options.path) {
14
+ return readFile(options.path).then(zipfile.openArrayBuffer);
15
+ } else if (options.buffer) {
16
+ return promises.resolve(zipfile.openArrayBuffer(options.buffer));
17
+ } else if (options.file) {
18
+ return promises.resolve(options.file);
19
+ } else {
20
+ return promises.reject(new Error("Could not find file in options"));
21
+ }
22
+ }