@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.
- package/.eslintrc.json +77 -0
- package/.github/ISSUE_TEMPLATE.md +12 -0
- package/.idea/mammoth.js.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.travis.yml +10 -0
- package/LICENSE +22 -0
- package/NEWS +373 -0
- package/README.md +883 -0
- package/bin/mammoth +38 -0
- package/browser/docx/files.js +14 -0
- package/browser/unzip.js +12 -0
- package/lib/document-to-html.js +453 -0
- package/lib/documents.js +238 -0
- package/lib/docx/body-reader.js +636 -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 +26 -0
- package/lib/docx/docx-reader.js +222 -0
- package/lib/docx/files.js +67 -0
- package/lib/docx/notes-reader.js +28 -0
- package/lib/docx/numbering-xml.js +69 -0
- package/lib/docx/office-xml-reader.js +58 -0
- package/lib/docx/relationships-reader.js +43 -0
- package/lib/docx/style-map.js +75 -0
- package/lib/docx/styles-reader.js +70 -0
- package/lib/docx/uris.js +21 -0
- package/lib/html/ast.js +50 -0
- package/lib/html/index.js +41 -0
- package/lib/html/simplify.js +88 -0
- package/lib/images.js +29 -0
- package/lib/index.js +115 -0
- package/lib/main.js +63 -0
- package/lib/options-reader.js +98 -0
- package/lib/promises.js +42 -0
- package/lib/results.js +72 -0
- package/lib/style-reader.js +321 -0
- package/lib/styles/document-matchers.js +74 -0
- package/lib/styles/html-paths.js +81 -0
- package/lib/styles/parser/tokeniser.js +30 -0
- package/lib/transforms.js +61 -0
- package/lib/underline.js +11 -0
- package/lib/unzip.js +22 -0
- package/lib/writers/html-writer.js +160 -0
- package/lib/writers/index.js +14 -0
- package/lib/writers/markdown-writer.js +163 -0
- package/lib/xml/index.js +7 -0
- package/lib/xml/nodes.js +69 -0
- package/lib/xml/reader.js +83 -0
- package/lib/xml/writer.js +61 -0
- package/lib/zipfile.js +77 -0
- package/mammoth.browser.js +32950 -0
- package/mammoth.browser.min.js +18 -0
- package/package.json +65 -0
- package/test/.eslintrc.json +7 -0
- package/test/document-to-html.tests.js +834 -0
- package/test/docx/body-reader.tests.js +1342 -0
- package/test/docx/comments-reader.tests.js +52 -0
- package/test/docx/content-types-reader.tests.js +45 -0
- package/test/docx/document-matchers.js +37 -0
- package/test/docx/docx-reader.tests.js +179 -0
- package/test/docx/files.tests.js +94 -0
- package/test/docx/notes-reader.tests.js +35 -0
- package/test/docx/numbering-xml.tests.js +65 -0
- package/test/docx/office-xml-reader.tests.js +24 -0
- package/test/docx/relationships-reader.tests.js +65 -0
- package/test/docx/style-map.tests.js +112 -0
- package/test/docx/styles-reader.tests.js +133 -0
- package/test/docx/uris.tests.js +22 -0
- package/test/html/simplify.tests.js +134 -0
- package/test/html/write.tests.js +42 -0
- package/test/images.tests.js +34 -0
- package/test/main.tests.js +89 -0
- package/test/mammoth.tests.js +429 -0
- package/test/mocha.opts +1 -0
- package/test/options-reader.tests.js +63 -0
- package/test/results.tests.js +15 -0
- package/test/style-reader.tests.js +256 -0
- package/test/styles/document-matchers.tests.js +71 -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/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 +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
|
+
}
|
package/lib/underline.js
ADDED
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
|
+
}
|