Skip to content

Commit 4a779b8

Browse files
committed
Support style mapping for highlights
1 parent 0d5b276 commit 4a779b8

File tree

7 files changed

+117
-1
lines changed

7 files changed

+117
-1
lines changed

NEWS

Lines changed: 1 addition & 1 deletion
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.1
66

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,43 @@ small-caps
622622
Note that this matches text that has had small caps explicitly applied to it.
623623
It will not match any text that is small caps because of its paragraph or run style.
624624

625+
#### Highlight
626+
627+
Match explicitly highlighted text:
628+
629+
```
630+
highlight
631+
```
632+
633+
Note that this matches text that has had a highlight explicitly applied to it.
634+
It will not match any text that is highlighted because of its paragraph or run style.
635+
636+
It's also possible to match specific colours.
637+
For instance, to match yellow highlights:
638+
639+
```
640+
highlight[color='yellow']
641+
```
642+
643+
The set of colours typically used are:
644+
645+
* `black`
646+
* `blue`
647+
* `cyan`
648+
* `green`
649+
* `magenta`
650+
* `red`
651+
* `yellow`
652+
* `white`
653+
* `darkBlue`
654+
* `darkCyan`
655+
* `darkGreen`
656+
* `darkMagenta`
657+
* `darkRed`
658+
* `darkYellow`
659+
* `darkGray`
660+
* `lightGray`
661+
625662
#### Ignoring document elements
626663

627664
Use `!` to ignore a document element.

mammoth/conversion.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ def children():
109109
def visit_run(self, run, context):
110110
nodes = lambda: self._visit_all(run.children, context)
111111
paths = []
112+
if run.highlight is not None:
113+
style = self._find_style(Highlight(color=run.highlight), "highlight")
114+
if style is not None:
115+
paths.append(style.html_path)
112116
if run.is_small_caps:
113117
paths.append(self._find_style_for_run_property("small_caps"))
114118
if run.is_all_caps:
@@ -354,9 +358,19 @@ def _html_id(self, suffix):
354358
return "{0}{1}".format(self._id_prefix, suffix)
355359

356360

361+
@cobble.data
362+
class Highlight:
363+
color = cobble.field()
364+
365+
357366
def _document_matcher_matches(matcher, element, element_type):
358367
if matcher.element_type in ["underline", "strikethrough", "all_caps", "small_caps", "bold", "italic", "comment_reference"]:
359368
return matcher.element_type == element_type
369+
elif matcher.element_type == "highlight":
370+
return (
371+
matcher.element_type == element_type and
372+
(matcher.color is None or matcher.color == element.color)
373+
)
360374
elif matcher.element_type == "break":
361375
return (
362376
matcher.element_type == element_type and

mammoth/document_matchers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class small_caps(object):
5151
element_type = "small_caps"
5252

5353

54+
def highlight(color=None):
55+
return HighlightMatcher(color=color)
56+
57+
58+
HighlightMatcher = collections.namedtuple("HighlightMatcher", ["color"])
59+
HighlightMatcher.element_type = "highlight"
60+
5461
class comment_reference(object):
5562
element_type = "comment_reference"
5663

mammoth/styles/parser/document_matcher_parser.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ def parse_document_matcher(tokens):
5252
elif tokens.try_skip(TokenType.IDENTIFIER, "small-caps"):
5353
return document_matchers.small_caps
5454

55+
elif tokens.try_skip(TokenType.IDENTIFIER, "highlight"):
56+
return _parse_highlight(tokens)
57+
5558
elif tokens.try_skip(TokenType.IDENTIFIER, "comment-reference"):
5659
return document_matchers.comment_reference
5760

@@ -98,6 +101,18 @@ def _parse_list_type(tokens):
98101
raise LineParseError("Unrecognised list type: {0}".format(list_type))
99102

100103

104+
def _parse_highlight(tokens):
105+
if tokens.try_skip(TokenType.SYMBOL, "["):
106+
tokens.skip(TokenType.IDENTIFIER, "color")
107+
tokens.skip(TokenType.SYMBOL, "=")
108+
color = parse_string(tokens)
109+
tokens.skip(TokenType.SYMBOL, "]");
110+
else:
111+
color = None
112+
113+
return document_matchers.highlight(color=color)
114+
115+
101116
def _parse_break(tokens):
102117
tokens.skip(TokenType.SYMBOL, "[")
103118
tokens.skip(TokenType.IDENTIFIER, "type")

tests/conversion_tests.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,37 @@ def test_small_caps_runs_can_be_mapped_using_style_mapping():
242242
assert_equal("<span>Hello</span>", result.value)
243243

244244

245+
def test_highlighted_runs_are_ignored_by_default():
246+
result = convert_document_element_to_html(
247+
documents.run(children=[documents.text("Hello")], highlight="yellow"),
248+
)
249+
assert_equal("Hello", result.value)
250+
251+
252+
def test_highlighted_runs_can_be_configured_with_style_mapping_for_all_highlights():
253+
result = convert_document_element_to_html(
254+
documents.run(children=[documents.text("Hello")], highlight="yellow"),
255+
style_map=[
256+
_style_mapping("highlight => mark"),
257+
],
258+
)
259+
assert_equal("<mark>Hello</mark>", result.value)
260+
261+
262+
def test_highlighted_runs_can_be_configured_with_style_mapping_for_specific_highlight_color():
263+
result = convert_document_element_to_html(
264+
documents.paragraph(children=[
265+
documents.run(children=[documents.text("Yellow")], highlight="yellow"),
266+
documents.run(children=[documents.text("Red")], highlight="red"),
267+
]),
268+
style_map=[
269+
_style_mapping("highlight[color='yellow'] => mark.yellow"),
270+
_style_mapping("highlight => mark"),
271+
]
272+
)
273+
assert_equal('<p><mark class="yellow">Yellow</mark><mark>Red</mark></p>', result.value)
274+
275+
245276
def test_superscript_runs_are_wrapped_in_sup_tags():
246277
result = convert_document_element_to_html(
247278
documents.run(

tests/styles/parser/document_matcher_parser_tests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ def test_reads_small_caps():
141141
read_document_matcher("small-caps")
142142
)
143143

144+
def test_reads_highlight_without_color():
145+
assert_equal(
146+
document_matchers.highlight(),
147+
read_document_matcher("highlight")
148+
)
149+
150+
def test_reads_highlight_with_color():
151+
assert_equal(
152+
document_matchers.highlight(color="yellow"),
153+
read_document_matcher("highlight[color='yellow']")
154+
)
155+
144156
def test_reads_comment_reference():
145157
assert_equal(
146158
document_matchers.comment_reference,

0 commit comments

Comments
 (0)