phml.utils.misc.component

 1# pylint: disable=missing-module-docstring
 2from pathlib import Path
 3
 4from phml.nodes import AST, Element
 5
 6__all__ = ["tag_from_file", "filename_from_path", "parse_component"]
 7
 8
 9def tag_from_file(filename: str | Path) -> str:
10    """Generates a tag name some-tag-name from a filename.
11    Assumes filenames of:
12    * snakecase - some_file_name
13    * camel case - someFileName
14    * pascal case - SomeFileName
15    """
16    from re import finditer  # pylint: disable=import-outside-toplevel
17
18    if isinstance(filename, Path):
19        if filename.is_file():
20            filename = filename.name.replace(filename.suffix, "")
21        else:
22            raise TypeError("If filename is a path it must also be a valid file.")
23
24    tokens = []
25    for token in finditer(r"(\b|[A-Z]|_|-)([a-z]+)|([A-Z]+)(?=[^a-z])", filename):
26        first, rest, cap = token.groups()
27
28        if first is not None and first.isupper():
29            rest = first + rest
30        elif cap is not None and cap.isupper():
31            rest = cap
32        tokens.append(rest.lower())
33
34    return "-".join(tokens)
35
36
37def filename_from_path(file: Path) -> str:
38    """Get the filename without the suffix from a pathlib.Path."""
39
40    if file.is_file():
41        return file.name.replace(file.suffix, "")
42
43    raise TypeError(f"Expected {type(Path)} not {type(file)}")
44
45
46def parse_component(ast: AST) -> dict[str, Element]:
47    """Helper function to parse the components elements."""
48    from phml.utils import check, visit_children  # pylint: disable=import-outside-toplevel
49
50    result = {"python": [], "script": [], "style": [], "component": None}
51    for node in visit_children(ast.tree):
52        if check(node, ["element", {"tag": "python"}]):
53            result["python"].append(node)
54        elif check(node, ["element", {"tag": "script"}]):
55            result["script"].append(node)
56        elif check(node, ["element", {"tag": "style"}]):
57            result["style"].append(node)
58        elif check(node, "element"):
59            if result["component"] is None:
60                result["component"] = node
61            else:
62                raise Exception(
63                    """\
64Components may only have one wrapping element. All other element in the root must be either a \
65script, style, or python tag.\
66"""
67                )
68
69    if result["component"] is None:
70        raise Exception("Must have at least one element in a component.")
71
72    return result
def tag_from_file(filename: str | pathlib.Path) -> str:
10def tag_from_file(filename: str | Path) -> str:
11    """Generates a tag name some-tag-name from a filename.
12    Assumes filenames of:
13    * snakecase - some_file_name
14    * camel case - someFileName
15    * pascal case - SomeFileName
16    """
17    from re import finditer  # pylint: disable=import-outside-toplevel
18
19    if isinstance(filename, Path):
20        if filename.is_file():
21            filename = filename.name.replace(filename.suffix, "")
22        else:
23            raise TypeError("If filename is a path it must also be a valid file.")
24
25    tokens = []
26    for token in finditer(r"(\b|[A-Z]|_|-)([a-z]+)|([A-Z]+)(?=[^a-z])", filename):
27        first, rest, cap = token.groups()
28
29        if first is not None and first.isupper():
30            rest = first + rest
31        elif cap is not None and cap.isupper():
32            rest = cap
33        tokens.append(rest.lower())
34
35    return "-".join(tokens)

Generates a tag name some-tag-name from a filename. Assumes filenames of:

  • snakecase - some_file_name
  • camel case - someFileName
  • pascal case - SomeFileName
def filename_from_path(file: pathlib.Path) -> str:
38def filename_from_path(file: Path) -> str:
39    """Get the filename without the suffix from a pathlib.Path."""
40
41    if file.is_file():
42        return file.name.replace(file.suffix, "")
43
44    raise TypeError(f"Expected {type(Path)} not {type(file)}")

Get the filename without the suffix from a pathlib.Path.

def parse_component(ast: phml.nodes.AST.AST) -> dict[str, phml.nodes.element.Element]:
47def parse_component(ast: AST) -> dict[str, Element]:
48    """Helper function to parse the components elements."""
49    from phml.utils import check, visit_children  # pylint: disable=import-outside-toplevel
50
51    result = {"python": [], "script": [], "style": [], "component": None}
52    for node in visit_children(ast.tree):
53        if check(node, ["element", {"tag": "python"}]):
54            result["python"].append(node)
55        elif check(node, ["element", {"tag": "script"}]):
56            result["script"].append(node)
57        elif check(node, ["element", {"tag": "style"}]):
58            result["style"].append(node)
59        elif check(node, "element"):
60            if result["component"] is None:
61                result["component"] = node
62            else:
63                raise Exception(
64                    """\
65Components may only have one wrapping element. All other element in the root must be either a \
66script, style, or python tag.\
67"""
68                )
69
70    if result["component"] is None:
71        raise Exception("Must have at least one element in a component.")
72
73    return result

Helper function to parse the components elements.