1"""
2The source-location records :attr:`turbohtml.Node.source_location` exposes.
3
4A parse with ``source_locations=True`` records, for every element, where its start tag, end tag, and each attribute sat
5in the source -- parse5's ``sourceCodeLocationInfo``. The tracking lives in the C core (``turbohtml._html``): the
6tokenizer stamps the spans as it runs and the tree builder hangs one :class:`SourceLocation` off each element. Importing
7this module registers the two record types with the core.
8"""
9
10from __future__ import annotations
11
12from typing import NamedTuple
13
14from turbohtml._html import _register_locations # Element stays importable so autodoc resolves it
15
16__all__ = ["SourceLocation", "SourceSpan"]
17
18
19class SourceSpan(NamedTuple):
20 r"""
21 Where one construct sat in the source: its start and end line, column, and code-point offset.
22
23 Lines are 1-based, columns 0-based, and offsets are code-point indices into the newline-normalized source (a
24 ``\\r\\n`` counts once), the same convention as :attr:`~turbohtml.Node.source_line` and
25 :attr:`~turbohtml.Node.source_col`. The half-open ``[start_offset, end_offset)`` slices the construct out of the
26 source.
27 """
28
29 start_line: int
30 """the 1-based line the construct starts on."""
31 start_col: int
32 """the 0-based column the construct starts at."""
33 start_offset: int
34 """the code-point offset the construct starts at."""
35 end_line: int
36 """the 1-based line just past the construct's end."""
37 end_col: int
38 """the 0-based column just past the construct's end."""
39 end_offset: int
40 """the code-point offset just past the construct's end."""
41
42
43class SourceLocation(NamedTuple):
44 """
45 Where a parsed element sat in the source.
46
47 ``start_tag`` spans the ``<tag ...>``; ``end_tag`` spans the ``</tag>`` or is ``None`` when the source never closed
48 the element (a void, self-closed, or implicitly/EOF-closed one). ``attrs`` maps each attribute's name to the span
49 covering its ``name="value"`` (the name alone for a valueless attribute), keyed by the same lowercased name
50 :attr:`~turbohtml.Element.attrs` uses, first occurrence winning on a duplicate.
51 """
52
53 start_tag: SourceSpan
54 """the span of the element's start tag."""
55 end_tag: SourceSpan | None
56 """the span of the element's end tag, or ``None`` when the source did not close it."""
57 attrs: dict[str, SourceSpan]
58 """each attribute name mapped to the span of its whole ``name="value"``."""
59
60
61_register_locations(SourceLocation, SourceSpan)