Skip to content

Commit 66c9ef9

Browse files
committed
Support style mapping for highlights
1 parent 700e395 commit 66c9ef9

8 files changed

+157
-1
lines changed

NEWS

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 1.8.0
22

3-
* Support parsing of run highlights.
3+
* Add style mapping for highlights.
44

55
# 1.7.2
66

README.md

+37
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,43 @@ small-caps
778778
Note that this matches text that has had small caps explicitly applied to it.
779779
It will not match any text that is small caps because of its paragraph or run style.
780780

781+
#### Highlight
782+
783+
Match explicitly highlighted text:
784+
785+
```
786+
highlight
787+
```
788+
789+
Note that this matches text that has had a highlight explicitly applied to it.
790+
It will not match any text that is highlighted because of its paragraph or run style.
791+
792+
It's also possible to match specific colours.
793+
For instance, to match yellow highlights:
794+
795+
```
796+
highlight[color='yellow']
797+
```
798+
799+
The set of colours typically used are:
800+
801+
* `black`
802+
* `blue`
803+
* `cyan`
804+
* `green`
805+
* `magenta`
806+
* `red`
807+
* `yellow`
808+
* `white`
809+
* `darkBlue`
810+
* `darkCyan`
811+
* `darkGreen`
812+
* `darkMagenta`
813+
* `darkRed`
814+
* `darkYellow`
815+
* `darkGray`
816+
* `lightGray`
817+
781818
#### Ignoring document elements
782819

783820
Use `!` to ignore a document element.

lib/document-to-html.js

+6
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ function DocumentConversion(options, comments) {
127127
return convertElements(run.children, messages, options);
128128
};
129129
var paths = [];
130+
if (run.highlight !== null) {
131+
var path = findHtmlPath({type: "highlight", color: run.highlight});
132+
if (path) {
133+
paths.push(path);
134+
}
135+
}
130136
if (run.isSmallCaps) {
131137
paths.push(findHtmlPathForRunProperty("smallCaps"));
132138
}

lib/style-reader.js

+18
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,23 @@ function documentMatcherRule() {
159159
var strikethrough = identifierToConstant("strike", documentMatchers.strikethrough);
160160
var allCaps = identifierToConstant("all-caps", documentMatchers.allCaps);
161161
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+
162179
var commentReference = identifierToConstant("comment-reference", documentMatchers.commentReference);
163180

164181
var breakMatcher = sequence(
@@ -191,6 +208,7 @@ function documentMatcherRule() {
191208
strikethrough,
192209
allCaps,
193210
smallCaps,
211+
highlight,
194212
commentReference,
195213
breakMatcher
196214
);

lib/styles/document-matchers.js

+15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ exports.underline = new Matcher("underline");
77
exports.strikethrough = new Matcher("strikethrough");
88
exports.allCaps = new Matcher("allCaps");
99
exports.smallCaps = new Matcher("smallCaps");
10+
exports.highlight = highlight;
1011
exports.commentReference = new Matcher("commentReference");
1112
exports.lineBreak = new Matcher("break", {breakType: "line"});
1213
exports.pageBreak = new Matcher("break", {breakType: "page"});
@@ -27,6 +28,10 @@ function table(options) {
2728
return new Matcher("table", options);
2829
}
2930

31+
function highlight(options) {
32+
return new HighlightMatcher(options);
33+
}
34+
3035
function Matcher(elementType, options) {
3136
options = options || {};
3237
this._elementType = elementType;
@@ -46,6 +51,16 @@ Matcher.prototype.matches = function(element) {
4651
(this._breakType === undefined || this._breakType === element.breakType);
4752
};
4853

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+
4964
function isList(element, levelIndex, isOrdered) {
5065
return element.numbering &&
5166
element.numbering.level == levelIndex &&

test/document-to-html.tests.js

+46
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,52 @@ test('small caps runs can be configured with style mapping', function() {
344344
});
345345

346346

347+
test('highlighted runs are ignored by default', function() {
348+
var run = runOfText("Hello.", {highlight: "yellow"});
349+
var converter = new DocumentConverter();
350+
return converter.convertToHtml(run).then(function(result) {
351+
assert.equal(result.value, "Hello.");
352+
});
353+
});
354+
355+
test('highlighted runs can be configured with style mapping for all highlights', function() {
356+
var run = runOfText("Hello.", {highlight: "yellow"});
357+
var converter = new DocumentConverter({
358+
styleMap: [
359+
{
360+
from: documentMatchers.highlight(null),
361+
to: htmlPaths.elements([htmlPaths.element("mark")])
362+
}
363+
]
364+
});
365+
return converter.convertToHtml(run).then(function(result) {
366+
assert.equal(result.value, "<mark>Hello.</mark>");
367+
});
368+
});
369+
370+
test('highlighted runs can be configured with style mapping for specific highlight color', function() {
371+
var paragraph = new documents.Paragraph([
372+
runOfText("Yellow", {highlight: "yellow"}),
373+
runOfText("Red", {highlight: "red"})
374+
]);
375+
var converter = new DocumentConverter({
376+
styleMap: [
377+
{
378+
from: documentMatchers.highlight({color: "yellow"}),
379+
to: htmlPaths.elements([htmlPaths.element("mark", {"class": "yellow"})])
380+
},
381+
{
382+
from: documentMatchers.highlight({color: undefined}),
383+
to: htmlPaths.elements([htmlPaths.element("mark")])
384+
}
385+
]
386+
});
387+
return converter.convertToHtml(paragraph).then(function(result) {
388+
assert.equal(result.value, '<p><mark class="yellow">Yellow</mark><mark>Red</mark></p>');
389+
});
390+
});
391+
392+
347393
test('run styles are converted to HTML if mapping exists', function() {
348394
var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"});
349395
var converter = new DocumentConverter({

test/style-reader.tests.js

+14
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,20 @@ test("styleReader.readDocumentMatcher", {
209209
);
210210
},
211211

212+
"reads highlight without color": function() {
213+
assertDocumentMatcher(
214+
"highlight",
215+
documentMatchers.highlight()
216+
);
217+
},
218+
219+
"reads highlight with color": function() {
220+
assertDocumentMatcher(
221+
"highlight[color='yellow']",
222+
documentMatchers.highlight({color: "yellow"})
223+
);
224+
},
225+
212226
"reads comment-reference": function() {
213227
assertDocumentMatcher(
214228
"comment-reference",

test/styles/document-matchers.tests.js

+20
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ test("matchers for lists with index 0 do not match elements that are not lists",
4545
assert.ok(!matcher.matches(new Paragraph()));
4646
});
4747

48+
test("highlight matcher does not match non-highlight elements", function() {
49+
var matcher = documentMatchers.highlight();
50+
assert.ok(!matcher.matches(new Paragraph()));
51+
});
52+
53+
test("highlight matcher without color matches all highlight elements", function() {
54+
var matcher = documentMatchers.highlight({});
55+
assert.ok(matcher.matches({type: "highlight", color: "yellow"}));
56+
});
57+
58+
test("highlight matcher with color matches highlight with that color", function() {
59+
var matcher = documentMatchers.highlight({color: "yellow"});
60+
assert.ok(matcher.matches({type: "highlight", color: "yellow"}));
61+
});
62+
63+
test("highlight matcher with color does not match highlights with other colors", function() {
64+
var matcher = documentMatchers.highlight({color: "yellow"});
65+
assert.ok(!matcher.matches({type: "highlight", color: "red"}));
66+
});
67+
4868
function paragraphWithStyle(styleId, styleName) {
4969
return new Paragraph([], {styleId: styleId, styleName: styleName});
5070
}

0 commit comments

Comments
 (0)