aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-06-13 12:16:25 +0100
committerMichael Williamson <mike@zwobble.org>2024-06-13 12:16:25 +0100
commit4a779b8d4fe83a80d99324a947b714c76468a88f (patch)
tree71e9cd15e8a76beb4d7ec4145234ae70ec4c8dae
parent0d5b27652c119dfaf99fae5f4e624c9efec408b5 (diff)
Support style mapping for highlights
-rw-r--r--NEWS2
-rw-r--r--README.md37
-rw-r--r--mammoth/conversion.py14
-rw-r--r--mammoth/document_matchers.py7
-rw-r--r--mammoth/styles/parser/document_matcher_parser.py15
-rw-r--r--tests/conversion_tests.py31
-rw-r--r--tests/styles/parser/document_matcher_parser_tests.py12
7 files changed, 117 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index eddda52..447f685 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
# 1.8.0
-* Support parsing of run highlights.
+* Add style mapping for highlights.
# 1.7.1
diff --git a/README.md b/README.md
index 2e501e2..897f7a2 100644
--- a/README.md
+++ b/README.md
@@ -622,6 +622,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/mammoth/conversion.py b/mammoth/conversion.py
index bdc8687..33f61cc 100644
--- a/mammoth/conversion.py
+++ b/mammoth/conversion.py
@@ -109,6 +109,10 @@ class _DocumentConverter(documents.element_visitor(args=1)):
def visit_run(self, run, context):
nodes = lambda: self._visit_all(run.children, context)
paths = []
+ if run.highlight is not None:
+ style = self._find_style(Highlight(color=run.highlight), "highlight")
+ if style is not None:
+ paths.append(style.html_path)
if run.is_small_caps:
paths.append(self._find_style_for_run_property("small_caps"))
if run.is_all_caps:
@@ -354,9 +358,19 @@ class _DocumentConverter(documents.element_visitor(args=1)):
return "{0}{1}".format(self._id_prefix, suffix)
+@cobble.data
+class Highlight:
+ color = cobble.field()
+
+
def _document_matcher_matches(matcher, element, element_type):
if matcher.element_type in ["underline", "strikethrough", "all_caps", "small_caps", "bold", "italic", "comment_reference"]:
return matcher.element_type == element_type
+ elif matcher.element_type == "highlight":
+ return (
+ matcher.element_type == element_type and
+ (matcher.color is None or matcher.color == element.color)
+ )
elif matcher.element_type == "break":
return (
matcher.element_type == element_type and
diff --git a/mammoth/document_matchers.py b/mammoth/document_matchers.py
index f831b8a..5d07d39 100644
--- a/mammoth/document_matchers.py
+++ b/mammoth/document_matchers.py
@@ -51,6 +51,13 @@ class small_caps(object):
element_type = "small_caps"
+def highlight(color=None):
+ return HighlightMatcher(color=color)
+
+
+HighlightMatcher = collections.namedtuple("HighlightMatcher", ["color"])
+HighlightMatcher.element_type = "highlight"
+
class comment_reference(object):
element_type = "comment_reference"
diff --git a/mammoth/styles/parser/document_matcher_parser.py b/mammoth/styles/parser/document_matcher_parser.py
index 9891e4b..e0eb4e1 100644
--- a/mammoth/styles/parser/document_matcher_parser.py
+++ b/mammoth/styles/parser/document_matcher_parser.py
@@ -52,6 +52,9 @@ def parse_document_matcher(tokens):
elif tokens.try_skip(TokenType.IDENTIFIER, "small-caps"):
return document_matchers.small_caps
+ elif tokens.try_skip(TokenType.IDENTIFIER, "highlight"):
+ return _parse_highlight(tokens)
+
elif tokens.try_skip(TokenType.IDENTIFIER, "comment-reference"):
return document_matchers.comment_reference
@@ -98,6 +101,18 @@ def _parse_list_type(tokens):
raise LineParseError("Unrecognised list type: {0}".format(list_type))
+def _parse_highlight(tokens):
+ if tokens.try_skip(TokenType.SYMBOL, "["):
+ tokens.skip(TokenType.IDENTIFIER, "color")
+ tokens.skip(TokenType.SYMBOL, "=")
+ color = parse_string(tokens)
+ tokens.skip(TokenType.SYMBOL, "]");
+ else:
+ color = None
+
+ return document_matchers.highlight(color=color)
+
+
def _parse_break(tokens):
tokens.skip(TokenType.SYMBOL, "[")
tokens.skip(TokenType.IDENTIFIER, "type")
diff --git a/tests/conversion_tests.py b/tests/conversion_tests.py
index 8f02048..8e76714 100644
--- a/tests/conversion_tests.py
+++ b/tests/conversion_tests.py
@@ -242,6 +242,37 @@ def test_small_caps_runs_can_be_mapped_using_style_mapping():
assert_equal("<span>Hello</span>", result.value)
+def test_highlighted_runs_are_ignored_by_default():
+ result = convert_document_element_to_html(
+ documents.run(children=[documents.text("Hello")], highlight="yellow"),
+ )
+ assert_equal("Hello", result.value)
+
+
+def test_highlighted_runs_can_be_configured_with_style_mapping_for_all_highlights():
+ result = convert_document_element_to_html(
+ documents.run(children=[documents.text("Hello")], highlight="yellow"),
+ style_map=[
+ _style_mapping("highlight => mark"),
+ ],
+ )
+ assert_equal("<mark>Hello</mark>", result.value)
+
+
+def test_highlighted_runs_can_be_configured_with_style_mapping_for_specific_highlight_color():
+ result = convert_document_element_to_html(
+ documents.paragraph(children=[
+ documents.run(children=[documents.text("Yellow")], highlight="yellow"),
+ documents.run(children=[documents.text("Red")], highlight="red"),
+ ]),
+ style_map=[
+ _style_mapping("highlight[color='yellow'] => mark.yellow"),
+ _style_mapping("highlight => mark"),
+ ]
+ )
+ assert_equal('<p><mark class="yellow">Yellow</mark><mark>Red</mark></p>', result.value)
+
+
def test_superscript_runs_are_wrapped_in_sup_tags():
result = convert_document_element_to_html(
documents.run(
diff --git a/tests/styles/parser/document_matcher_parser_tests.py b/tests/styles/parser/document_matcher_parser_tests.py
index 1808571..dd613a1 100644
--- a/tests/styles/parser/document_matcher_parser_tests.py
+++ b/tests/styles/parser/document_matcher_parser_tests.py
@@ -141,6 +141,18 @@ def test_reads_small_caps():
read_document_matcher("small-caps")
)
+def test_reads_highlight_without_color():
+ assert_equal(
+ document_matchers.highlight(),
+ read_document_matcher("highlight")
+ )
+
+def test_reads_highlight_with_color():
+ assert_equal(
+ document_matchers.highlight(color="yellow"),
+ read_document_matcher("highlight[color='yellow']")
+ )
+
def test_reads_comment_reference():
assert_equal(
document_matchers.comment_reference,