summaryrefslogtreecommitdiff
path: root/mammoth/styles/parser/html_path_parser.py
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-02-17 13:52:16 +0000
committerMichael Williamson <mike@zwobble.org>2024-02-17 13:52:16 +0000
commitfe41ddbc51b4b7c6ce7d958ea7622983d7805b7e (patch)
tree6a477e4a54657b5b89b87141ed85f088c2f03015 /mammoth/styles/parser/html_path_parser.py
parentd037ef5cf7fc976047bed20859dbcd5c90f45d67 (diff)
Support attributes in HTML paths in style mappings
Diffstat (limited to 'mammoth/styles/parser/html_path_parser.py')
-rw-r--r--mammoth/styles/parser/html_path_parser.py74
1 files changed, 57 insertions, 17 deletions
diff --git a/mammoth/styles/parser/html_path_parser.py b/mammoth/styles/parser/html_path_parser.py
index 9e155b6..8ed6fed 100644
--- a/mammoth/styles/parser/html_path_parser.py
+++ b/mammoth/styles/parser/html_path_parser.py
@@ -1,6 +1,15 @@
+import cobble
+
from ... import html_paths
from .tokeniser import TokenType
-from .token_parser import parse_identifier, parse_string, try_parse_class_name
+from .token_parser import parse_identifier, parse_string
+
+
+@cobble.data
+class _AttributeOrClassName(object):
+ name = cobble.field()
+ value = cobble.field()
+ append = cobble.field()
def parse_html_path(tokens):
@@ -12,26 +21,33 @@ def parse_html_path(tokens):
def _parse_html_path_elements(tokens):
elements = []
-
+
if tokens.peek_token_type() == TokenType.IDENTIFIER:
elements.append(_parse_element(tokens))
-
+
while tokens.try_skip_many(((TokenType.WHITESPACE, None), (TokenType.SYMBOL, ">"))):
tokens.skip(TokenType.WHITESPACE)
elements.append(_parse_element(tokens))
-
+
return elements
def _parse_element(tokens):
tag_names = _parse_tag_names(tokens)
- class_names = _parse_class_names(tokens)
+ attributes_list = _parse_attribute_or_class_names(tokens)
is_fresh = _parse_is_fresh(tokens)
separator = _parse_separator(tokens)
-
+
+ attributes = {}
+ for attribute in attributes_list:
+ if attribute.append and attributes.get(attribute.name):
+ attributes[attribute.name] += " " + attribute.value
+ else:
+ attributes[attribute.name] = attribute.value
+
return html_paths.element(
tag_names,
- class_names=class_names,
+ attributes=attributes,
fresh=is_fresh,
separator=separator,
)
@@ -39,24 +55,48 @@ def _parse_element(tokens):
def _parse_tag_names(tokens):
tag_names = [parse_identifier(tokens)]
-
+
while tokens.try_skip(TokenType.SYMBOL, "|"):
tag_names.append(parse_identifier(tokens))
-
+
return tag_names
-def _parse_class_names(tokens):
- class_names = []
-
+def _parse_attribute_or_class_names(tokens):
+ attribute_or_class_names = []
+
while True:
- class_name = try_parse_class_name(tokens)
- if class_name is None:
+ attribute_or_class_name = _try_parse_attribute_or_class_name(tokens)
+ if attribute_or_class_name is None:
break
else:
- class_names.append(class_name)
-
- return class_names
+ attribute_or_class_names.append(attribute_or_class_name)
+
+ return attribute_or_class_names
+
+
+def _try_parse_attribute_or_class_name(tokens):
+ if tokens.is_next(TokenType.SYMBOL, "["):
+ return _parse_attribute(tokens)
+ if tokens.is_next(TokenType.SYMBOL, "."):
+ return _parse_class_name(tokens)
+ else:
+ return None
+
+
+def _parse_attribute(tokens):
+ tokens.skip(TokenType.SYMBOL, "[")
+ name = parse_identifier(tokens)
+ tokens.skip(TokenType.SYMBOL, "=")
+ value = parse_string(tokens)
+ tokens.skip(TokenType.SYMBOL, "]")
+ return _AttributeOrClassName(name=name, value=value, append=False)
+
+
+def _parse_class_name(tokens):
+ tokens.skip(TokenType.SYMBOL, ".")
+ class_name = parse_identifier(tokens)
+ return _AttributeOrClassName(name="class", value=class_name, append=True)
def _parse_is_fresh(tokens):