aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-06-17 14:33:43 +0100
committerMichael Williamson <mike@zwobble.org>2015-06-17 14:33:43 +0100
commit17577bdd715c65e71d81f762b54b8c27f60f4535 (patch)
tree5389d7741881b2d198daf450f915fa9b3527f7e7
parentdc31bacddd43e100a2793c76e26d35568262d89a (diff)
Support underlines in style map
-rw-r--r--lib/document-matchers.js1
-rw-r--r--lib/document-to-html.js15
-rw-r--r--lib/html-generator.js5
-rw-r--r--lib/style-reader.js9
-rw-r--r--tests/document-to-html.tests.js32
-rw-r--r--tests/html-generator.tests.js9
-rw-r--r--tests/mammoth.tests.js7
-rw-r--r--tests/style-reader.tests.js7
8 files changed, 81 insertions, 4 deletions
diff --git a/lib/document-matchers.js b/lib/document-matchers.js
index 9b01dfd..a4d59be 100644
--- a/lib/document-matchers.js
+++ b/lib/document-matchers.js
@@ -1,5 +1,6 @@
exports.paragraph = paragraph;
exports.run = run;
+exports.underline = new Matcher("underline");
function paragraph(options) {
diff --git a/lib/document-to-html.js b/lib/document-to-html.js
index 220ae2b..264f7c9 100644
--- a/lib/document-to-html.js
+++ b/lib/document-to-html.js
@@ -122,8 +122,8 @@ function DocumentConversion(options) {
if (run.verticalAlignment === documents.verticalAlignment.subscript) {
runHtml.open(htmlPaths.element("sub"));
}
- if (run.isUnderline && options.convertUnderline) {
- options.convertUnderline(runHtml);
+ if (run.isUnderline) {
+ convertUnderline(runHtml);
}
convertElements(run.children, runHtml, messages, function(err) {
if (err) {
@@ -136,6 +136,17 @@ function DocumentConversion(options) {
});
}
+ function convertUnderline(runHtml) {
+ (options.convertUnderline || defaultConvertUnderline)(runHtml);
+ }
+
+ function defaultConvertUnderline(runHtml) {
+ var style = findStyle({type: "underline"});
+ if (style) {
+ runHtml.appendPath(style.to);
+ }
+ }
+
function findStyle(element) {
for (var i = 0; i < styleMap.length; i++) {
if (styleMap[i].from.matches(element)) {
diff --git a/lib/html-generator.js b/lib/html-generator.js
index a071a5e..a20a714 100644
--- a/lib/html-generator.js
+++ b/lib/html-generator.js
@@ -43,6 +43,10 @@ function HtmlGenerator(options) {
}
}
+ function appendPath(style) {
+ style.forEach(open);
+ }
+
function stylePartMatchesStackElement(stylePart, stackElement) {
return stackElement && stylePart.matchesElement(stackElement);
}
@@ -86,6 +90,7 @@ function HtmlGenerator(options) {
return {
satisfyPath: satisfyPath,
+ appendPath: appendPath,
text: text,
open: open,
close: close,
diff --git a/lib/style-reader.js b/lib/style-reader.js
index ef379b6..811e06e 100644
--- a/lib/style-reader.js
+++ b/lib/style-reader.js
@@ -109,7 +109,7 @@ function documentMatcherRule() {
);
var matcherSuffixes = lop.rules.zeroOrMore(matcherSuffix);
- return sequence(
+ var paragraphOrRun = sequence(
sequence.capture(elementTypeRule),
sequence.capture(matcherSuffixes)
).map(function(createMatcher, suffixes) {
@@ -119,6 +119,13 @@ function documentMatcherRule() {
});
return createMatcher(matcherOptions);
});
+
+ var underline = identifierToConstant("u", documentMatchers.underline);
+
+ return lop.rules.firstOf("element type",
+ paragraphOrRun,
+ underline
+ );
}
function readHtmlPath(string) {
diff --git a/tests/document-to-html.tests.js b/tests/document-to-html.tests.js
index 5a271d0..516f2fe 100644
--- a/tests/document-to-html.tests.js
+++ b/tests/document-to-html.tests.js
@@ -177,7 +177,7 @@ describe('DocumentConverter', function() {
});
});
- test('underline runs can be wrapped in <u> tags', function() {
+ test('underline runs can be wrapped in <u> tags using convertUnderline option', function() {
var run = runOfText("Hello.", {isUnderline: true});
var converter = new DocumentConverter({
convertUnderline: mammoth.underline.element("u")
@@ -186,6 +186,36 @@ describe('DocumentConverter', function() {
assert.equal(result.value, "<u>Hello.</u>");
});
});
+
+ test('underline runs can be mapped using style mapping', function() {
+ var run = runOfText("Hello.", {isUnderline: true});
+ var converter = new DocumentConverter({
+ styleMap: [
+ {
+ from: documentMatchers.underline,
+ to: htmlPaths.elements([htmlPaths.element("u")])
+ }
+ ]
+ });
+ return converter.convertToHtml(run).then(function(result) {
+ assert.equal(result.value, "<u>Hello.</u>");
+ });
+ });
+
+ test('style mapping for underline runs does not close parent elements', function() {
+ var run = runOfText("Hello.", {isUnderline: true, isBold: true});
+ var converter = new DocumentConverter({
+ styleMap: [
+ {
+ from: documentMatchers.underline,
+ to: htmlPaths.elements([htmlPaths.element("u")])
+ }
+ ]
+ });
+ return converter.convertToHtml(run).then(function(result) {
+ assert.equal(result.value, "<strong><u>Hello.</u></strong>");
+ });
+ });
test('italic runs are wrapped in <em> tags', function() {
var run = runOfText("Hello.", {isItalic: true});
diff --git a/tests/html-generator.tests.js b/tests/html-generator.tests.js
index f361633..6921b45 100644
--- a/tests/html-generator.tests.js
+++ b/tests/html-generator.tests.js
@@ -69,4 +69,13 @@ describe('HtmlGenerator', function() {
generator.selfClosing({tagName: "br", attributes: {"data-blah": "<"}});
return assert.equal(generator.asString(), '<br data-blah="&lt;" />');
});
+
+ test('appendPath does not close currently-open elements', function() {
+ var generator = new HtmlGenerator();
+ generator.satisfyPath(htmlPaths.elements(["strong"]));
+ generator.appendPath(htmlPaths.elements(["em"]));
+ generator.text("Hello!");
+ generator.closeAll();
+ return assert.equal(generator.asString(), "<strong><em>Hello!</em></strong>");
+ });
});
diff --git a/tests/mammoth.tests.js b/tests/mammoth.tests.js
index e016fe1..93fc966 100644
--- a/tests/mammoth.tests.js
+++ b/tests/mammoth.tests.js
@@ -217,6 +217,13 @@ describe('mammoth', function() {
});
});
+ test('underline can be configured with style mapping', function() {
+ var docxPath = path.join(__dirname, "test-data/underline.docx");
+ return mammoth.convertToHtml({path: docxPath}, {styleMap: "u => em"}).then(function(result) {
+ assert.equal(result.value, '<p><strong>The </strong><strong><em>Sunset</em></strong><strong> Tree</strong></p>');
+ });
+ });
+
test('indentation is used if prettyPrint is true', function() {
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
return mammoth.convertToHtml({path: docxPath}, {prettyPrint: true}).then(function(result) {
diff --git a/tests/style-reader.tests.js b/tests/style-reader.tests.js
index 7927153..59d7c51 100644
--- a/tests/style-reader.tests.js
+++ b/tests/style-reader.tests.js
@@ -93,6 +93,13 @@ describe("styleReader.readDocumentMatcher", function() {
documentMatchers.run()
);
});
+
+ test("reads underline", function() {
+ assert.deepEqual(
+ readDocumentMatcher("u"),
+ documentMatchers.underline
+ );
+ });
});
describe("styleReader.read", function() {