diff options
| author | Michael Williamson <mike@zwobble.org> | 2024-06-13 11:52:30 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2024-06-13 11:52:30 +0100 |
| commit | 66c9ef99816708cb1ffedd3ec37e5622bf823c20 (patch) | |
| tree | 10e640bcda8b6ecd92a7486a9d700366cf40f239 | |
| parent | 700e395a3d2a0c9f6526fe7c69a92bd347fa1b88 (diff) | |
Support style mapping for highlights
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | README.md | 37 | ||||
| -rw-r--r-- | lib/document-to-html.js | 6 | ||||
| -rw-r--r-- | lib/style-reader.js | 18 | ||||
| -rw-r--r-- | lib/styles/document-matchers.js | 15 | ||||
| -rw-r--r-- | test/document-to-html.tests.js | 46 | ||||
| -rw-r--r-- | test/style-reader.tests.js | 14 | ||||
| -rw-r--r-- | test/styles/document-matchers.tests.js | 20 |
8 files changed, 157 insertions, 1 deletions
@@ -1,6 +1,6 @@ # 1.8.0 -* Support parsing of run highlights. +* Add style mapping for highlights. # 1.7.2 @@ -778,6 +778,43 @@ small-caps Note that this matches text that has had small caps explicitly applied to it. It will not match any text that is small caps because of its paragraph or run style. +#### Highlight + +Match explicitly highlighted text: + +``` +highlight +``` + +Note that this matches text that has had a highlight explicitly applied to it. +It will not match any text that is highlighted because of its paragraph or run style. + +It's also possible to match specific colours. +For instance, to match yellow highlights: + +``` +highlight[color='yellow'] +``` + +The set of colours typically used are: + +* `black` +* `blue` +* `cyan` +* `green` +* `magenta` +* `red` +* `yellow` +* `white` +* `darkBlue` +* `darkCyan` +* `darkGreen` +* `darkMagenta` +* `darkRed` +* `darkYellow` +* `darkGray` +* `lightGray` + #### Ignoring document elements Use `!` to ignore a document element. diff --git a/lib/document-to-html.js b/lib/document-to-html.js index 32e8b03..bd845f6 100644 --- a/lib/document-to-html.js +++ b/lib/document-to-html.js @@ -127,6 +127,12 @@ function DocumentConversion(options, comments) { return convertElements(run.children, messages, options); }; var paths = []; + if (run.highlight !== null) { + var path = findHtmlPath({type: "highlight", color: run.highlight}); + if (path) { + paths.push(path); + } + } if (run.isSmallCaps) { paths.push(findHtmlPathForRunProperty("smallCaps")); } diff --git a/lib/style-reader.js b/lib/style-reader.js index 38202f9..6305c59 100644 --- a/lib/style-reader.js +++ b/lib/style-reader.js @@ -159,6 +159,23 @@ function documentMatcherRule() { var strikethrough = identifierToConstant("strike", documentMatchers.strikethrough); var allCaps = identifierToConstant("all-caps", documentMatchers.allCaps); var smallCaps = identifierToConstant("small-caps", documentMatchers.smallCaps); + + var highlight = sequence( + lop.rules.token("identifier", "highlight"), + lop.rules.sequence.capture(lop.rules.optional(lop.rules.sequence( + lop.rules.tokenOfType("open-square-bracket"), + lop.rules.sequence.cut(), + lop.rules.token("identifier", "color"), + lop.rules.tokenOfType("equals"), + lop.rules.sequence.capture(stringRule), + lop.rules.tokenOfType("close-square-bracket") + ).head())) + ).map(function(color) { + return documentMatchers.highlight({ + color: color.valueOrElse(undefined) + }); + }); + var commentReference = identifierToConstant("comment-reference", documentMatchers.commentReference); var breakMatcher = sequence( @@ -191,6 +208,7 @@ function documentMatcherRule() { strikethrough, allCaps, smallCaps, + highlight, commentReference, breakMatcher ); diff --git a/lib/styles/document-matchers.js b/lib/styles/document-matchers.js index 005e2db..58c844a 100644 --- a/lib/styles/document-matchers.js +++ b/lib/styles/document-matchers.js @@ -7,6 +7,7 @@ exports.underline = new Matcher("underline"); exports.strikethrough = new Matcher("strikethrough"); exports.allCaps = new Matcher("allCaps"); exports.smallCaps = new Matcher("smallCaps"); +exports.highlight = highlight; exports.commentReference = new Matcher("commentReference"); exports.lineBreak = new Matcher("break", {breakType: "line"}); exports.pageBreak = new Matcher("break", {breakType: "page"}); @@ -27,6 +28,10 @@ function table(options) { return new Matcher("table", options); } +function highlight(options) { + return new HighlightMatcher(options); +} + function Matcher(elementType, options) { options = options || {}; this._elementType = elementType; @@ -46,6 +51,16 @@ Matcher.prototype.matches = function(element) { (this._breakType === undefined || this._breakType === element.breakType); }; +function HighlightMatcher(options) { + options = options || {}; + this._color = options.color; +} + +HighlightMatcher.prototype.matches = function(element) { + return element.type === "highlight" && + (this._color === undefined || element.color === this._color); +}; + function isList(element, levelIndex, isOrdered) { return element.numbering && element.numbering.level == levelIndex && diff --git a/test/document-to-html.tests.js b/test/document-to-html.tests.js index 4283e86..4587602 100644 --- a/test/document-to-html.tests.js +++ b/test/document-to-html.tests.js @@ -344,6 +344,52 @@ test('small caps runs can be configured with style mapping', function() { }); +test('highlighted runs are ignored by default', function() { + var run = runOfText("Hello.", {highlight: "yellow"}); + var converter = new DocumentConverter(); + return converter.convertToHtml(run).then(function(result) { + assert.equal(result.value, "Hello."); + }); +}); + +test('highlighted runs can be configured with style mapping for all highlights', function() { + var run = runOfText("Hello.", {highlight: "yellow"}); + var converter = new DocumentConverter({ + styleMap: [ + { + from: documentMatchers.highlight(null), + to: htmlPaths.elements([htmlPaths.element("mark")]) + } + ] + }); + return converter.convertToHtml(run).then(function(result) { + assert.equal(result.value, "<mark>Hello.</mark>"); + }); +}); + +test('highlighted runs can be configured with style mapping for specific highlight color', function() { + var paragraph = new documents.Paragraph([ + runOfText("Yellow", {highlight: "yellow"}), + runOfText("Red", {highlight: "red"}) + ]); + var converter = new DocumentConverter({ + styleMap: [ + { + from: documentMatchers.highlight({color: "yellow"}), + to: htmlPaths.elements([htmlPaths.element("mark", {"class": "yellow"})]) + }, + { + from: documentMatchers.highlight({color: undefined}), + to: htmlPaths.elements([htmlPaths.element("mark")]) + } + ] + }); + return converter.convertToHtml(paragraph).then(function(result) { + assert.equal(result.value, '<p><mark class="yellow">Yellow</mark><mark>Red</mark></p>'); + }); +}); + + test('run styles are converted to HTML if mapping exists', function() { var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"}); var converter = new DocumentConverter({ diff --git a/test/style-reader.tests.js b/test/style-reader.tests.js index 93ddc79..79be1dd 100644 --- a/test/style-reader.tests.js +++ b/test/style-reader.tests.js @@ -209,6 +209,20 @@ test("styleReader.readDocumentMatcher", { ); }, + "reads highlight without color": function() { + assertDocumentMatcher( + "highlight", + documentMatchers.highlight() + ); + }, + + "reads highlight with color": function() { + assertDocumentMatcher( + "highlight[color='yellow']", + documentMatchers.highlight({color: "yellow"}) + ); + }, + "reads comment-reference": function() { assertDocumentMatcher( "comment-reference", diff --git a/test/styles/document-matchers.tests.js b/test/styles/document-matchers.tests.js index 5ce3f72..63a00a8 100644 --- a/test/styles/document-matchers.tests.js +++ b/test/styles/document-matchers.tests.js @@ -45,6 +45,26 @@ test("matchers for lists with index 0 do not match elements that are not lists", assert.ok(!matcher.matches(new Paragraph())); }); +test("highlight matcher does not match non-highlight elements", function() { + var matcher = documentMatchers.highlight(); + assert.ok(!matcher.matches(new Paragraph())); +}); + +test("highlight matcher without color matches all highlight elements", function() { + var matcher = documentMatchers.highlight({}); + assert.ok(matcher.matches({type: "highlight", color: "yellow"})); +}); + +test("highlight matcher with color matches highlight with that color", function() { + var matcher = documentMatchers.highlight({color: "yellow"}); + assert.ok(matcher.matches({type: "highlight", color: "yellow"})); +}); + +test("highlight matcher with color does not match highlights with other colors", function() { + var matcher = documentMatchers.highlight({color: "yellow"}); + assert.ok(!matcher.matches({type: "highlight", color: "red"})); +}); + function paragraphWithStyle(styleId, styleName) { return new Paragraph([], {styleId: styleId, styleName: styleName}); } |
