rbtr-lang-html 2026.7.0.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ """HTML language plugin package."""
@@ -0,0 +1,21 @@
1
+ ; Comments (`<!-- -->`).
2
+ (comment) @comment
3
+
4
+ (element (start_tag (tag_name) @_tag)
5
+ (#any-of? @_tag "head" "body" "article" "aside" "nav" "section" "header" "main" "footer" "figure" "form" "dialog" "details" "table")) @doc_section
6
+
7
+ (script_element
8
+ (start_tag
9
+ (attribute (attribute_name) @_a
10
+ (quoted_attribute_value (attribute_value) @_import_module))
11
+ (#eq? @_a "src"))) @import
12
+
13
+ (element
14
+ [(start_tag (tag_name) @_lt
15
+ (attribute (attribute_name) @_h
16
+ (quoted_attribute_value (attribute_value) @_import_module)))
17
+ (self_closing_tag (tag_name) @_lt
18
+ (attribute (attribute_name) @_h
19
+ (quoted_attribute_value (attribute_value) @_import_module)))]
20
+ (#eq? @_lt "link")
21
+ (#eq? @_h "href")) @import
@@ -0,0 +1,8 @@
1
+ ; Inline <script>/<style> delegate to JavaScript/CSS. External
2
+ ; <script src>/<link href> have no raw_text, so they become imports instead.
3
+
4
+ ((script_element (raw_text) @injection.content)
5
+ (#set! injection.language "javascript"))
6
+
7
+ ((style_element (raw_text) @injection.content)
8
+ (#set! injection.language "css"))
@@ -0,0 +1,110 @@
1
+ """HTML language plugin.
2
+
3
+ Extracts semantic and structural elements as doc sections and cross-language
4
+ import references, via a tree-sitter query.
5
+
6
+ Extracted chunks::
7
+
8
+ <main id="content">…</main> → doc_section "content" (named by id)
9
+ <nav>…</nav> → doc_section "nav" (named by tag)
10
+ <script src="app.js"> → import {module: "app.js", hint javascript}
11
+ <link href="styles.css"> → import {module: "styles.css", hint css}
12
+
13
+ Element chunks cover `head`, `body`, sectioning content, landmarks, and
14
+ self-contained units; nested elements are each extracted (overlapping, like a
15
+ class and its methods). A file with none of these is left to the engine's
16
+ presence handling. Inline `<script>`/`<style>` delegate to JavaScript/CSS via
17
+ `injection_query`; external `<script src>`/`<link href>` become import edges.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from typing import TYPE_CHECKING
23
+
24
+ from rbtr.index.models import ImportMeta
25
+ from rbtr.languages.registration import (
26
+ ImportResolver,
27
+ LanguageRegistration,
28
+ NameResolver,
29
+ QueryExtraction,
30
+ load_query,
31
+ )
32
+
33
+ if TYPE_CHECKING:
34
+ from tree_sitter import Node
35
+
36
+ # Elements that hold meaning of their own: the document containers, HTML5
37
+ # sectioning content and landmarks, and self-contained units. Named by their
38
+ # `id` when present, else by tag.
39
+
40
+
41
+ # Inline <script>/<style> delegate to JavaScript/CSS. External <script src>/
42
+ # <link href> have no raw_text, so they are skipped here and become imports.
43
+
44
+
45
+ def _get_attr(start_tag: Node, attr_name: str) -> str | None:
46
+ """Extract an attribute value from a start_tag node."""
47
+ for child in start_tag.children:
48
+ if child.type != "attribute":
49
+ continue
50
+ name_node = None
51
+ value_node = None
52
+ for gc in child.children:
53
+ if gc.type == "attribute_name" and gc.text:
54
+ name_node = gc
55
+ elif gc.type == "quoted_attribute_value":
56
+ for vg in gc.children:
57
+ if vg.type == "attribute_value" and vg.text:
58
+ value_node = vg
59
+ if (
60
+ name_node is not None
61
+ and value_node is not None
62
+ and name_node.text == attr_name.encode()
63
+ ):
64
+ text = value_node.text
65
+ return text.decode("utf-8", errors="replace") if text else None
66
+ return None
67
+
68
+
69
+ # ── Plugin ───────────────────────────────────────────────────────────
70
+
71
+
72
+ html = LanguageRegistration(
73
+ id="html",
74
+ extensions=frozenset({".html", ".htm"}),
75
+ grammar_module="tree_sitter_html",
76
+ extraction=QueryExtraction(
77
+ query=load_query(__package__, "html"),
78
+ ),
79
+ injection_query=load_query(__package__, "injections"),
80
+ import_targets=frozenset({"javascript", "typescript", "css"}),
81
+ extraction_serial=3,
82
+ )
83
+
84
+
85
+ @html.name_extractor
86
+ def _element_name(
87
+ resolver: NameResolver, capture_name: str, node: Node, captures: dict[str, list[Node]]
88
+ ) -> str:
89
+ """Name a semantic element by its `id`, else its tag; others by default."""
90
+ if capture_name != "doc_section":
91
+ return resolver(capture_name, node, captures)
92
+ start_tag = next((c for c in node.children if c.type == "start_tag"), None)
93
+ if start_tag is not None:
94
+ elem_id = _get_attr(start_tag, "id")
95
+ if elem_id:
96
+ return elem_id
97
+ tag_nodes = captures.get("_tag")
98
+ if tag_nodes and tag_nodes[0].text:
99
+ return tag_nodes[0].text.decode()
100
+ return "<anonymous>"
101
+
102
+
103
+ @html.import_extractor
104
+ def _import_meta(
105
+ resolver: ImportResolver, node: Node, captures: dict[str, list[Node]]
106
+ ) -> ImportMeta:
107
+ """Import metadata with a language hint from the element kind."""
108
+ meta = resolver(node, captures)
109
+ meta.language_hint = "javascript" if node.type == "script_element" else "css"
110
+ return meta
File without changes
File without changes
@@ -0,0 +1,4 @@
1
+ [
2
+ "html.html::<link rel=\"stylesheet\" href=\"styles.css\"> -> styles.css::.greeter [imports]",
3
+ "html.html::<script src=\"greeter.js\"></script> -> greeter.js::greet [imports]"
4
+ ]
@@ -0,0 +1,254 @@
1
+ [
2
+ {
3
+ "id": "0da3db16ee1c511c",
4
+ "blob_sha": "sha1",
5
+ "file_path": "greeter.js",
6
+ "kind": "comment",
7
+ "name": "<anonymous>",
8
+ "scope": "",
9
+ "language": "javascript",
10
+ "content": "// Client-side greeter.",
11
+ "line_start": 1,
12
+ "line_end": 1,
13
+ "metadata": {
14
+ "module": "",
15
+ "names": "",
16
+ "dots": "",
17
+ "language_hint": ""
18
+ }
19
+ },
20
+ {
21
+ "id": "7250027edb443428",
22
+ "blob_sha": "sha1",
23
+ "file_path": "greeter.js",
24
+ "kind": "function",
25
+ "name": "greet",
26
+ "scope": "",
27
+ "language": "javascript",
28
+ "content": "function greet(name) {\n return `Hello, ${name}`;\n}",
29
+ "line_start": 2,
30
+ "line_end": 4,
31
+ "metadata": {
32
+ "module": "",
33
+ "names": "",
34
+ "dots": "",
35
+ "language_hint": ""
36
+ }
37
+ },
38
+ {
39
+ "id": "a112d7329735ed9a",
40
+ "blob_sha": "sha1",
41
+ "file_path": "html.html",
42
+ "kind": "comment",
43
+ "name": "<anonymous>",
44
+ "scope": "",
45
+ "language": "html",
46
+ "content": "<!-- Greeter page. The HTML plugin extracts <script src>/<link href>\n as imports (with a language hint) and major <body> elements as\n doc sections. -->",
47
+ "line_start": 2,
48
+ "line_end": 4,
49
+ "metadata": {
50
+ "module": "",
51
+ "names": "",
52
+ "dots": "",
53
+ "language_hint": ""
54
+ }
55
+ },
56
+ {
57
+ "id": "27068c2cfea9cd2c",
58
+ "blob_sha": "sha1",
59
+ "file_path": "html.html",
60
+ "kind": "doc_section",
61
+ "name": "head",
62
+ "scope": "",
63
+ "language": "html",
64
+ "content": "<head>\n <title>Greeter</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n <script src=\"greeter.js\"></script>\n <style>\n .greeter {\n font-family: system-ui;\n }\n </style>\n </head>",
65
+ "line_start": 6,
66
+ "line_end": 15,
67
+ "metadata": {
68
+ "module": "",
69
+ "names": "",
70
+ "dots": "",
71
+ "language_hint": ""
72
+ }
73
+ },
74
+ {
75
+ "id": "f28a9a9f2f8997fb",
76
+ "blob_sha": "sha1",
77
+ "file_path": "html.html",
78
+ "kind": "import",
79
+ "name": "<link rel=\"stylesheet\" href=\"styles.css\">",
80
+ "scope": "",
81
+ "language": "html",
82
+ "content": "<link rel=\"stylesheet\" href=\"styles.css\">\n ",
83
+ "line_start": 8,
84
+ "line_end": 9,
85
+ "metadata": {
86
+ "module": "styles.css",
87
+ "names": "",
88
+ "dots": "",
89
+ "language_hint": "css"
90
+ }
91
+ },
92
+ {
93
+ "id": "97b687eb6737629d",
94
+ "blob_sha": "sha1",
95
+ "file_path": "html.html",
96
+ "kind": "import",
97
+ "name": "<script src=\"greeter.js\"></script>",
98
+ "scope": "",
99
+ "language": "html",
100
+ "content": "<script src=\"greeter.js\"></script>",
101
+ "line_start": 9,
102
+ "line_end": 9,
103
+ "metadata": {
104
+ "module": "greeter.js",
105
+ "names": "",
106
+ "dots": "",
107
+ "language_hint": "javascript"
108
+ }
109
+ },
110
+ {
111
+ "id": "6913a3afc10a6ef7",
112
+ "blob_sha": "sha1",
113
+ "file_path": "html.html",
114
+ "kind": "doc_section",
115
+ "name": "body",
116
+ "scope": "",
117
+ "language": "html",
118
+ "content": "<body>\n <header class=\"page-header\">\n <h1>Greeter</h1>\n </header>\n <main id=\"content\">\n <section id=\"intro\">\n <p>Format greetings for named recipients.</p>\n </section>\n </main>\n <footer>\n <small>Greeter &mdash; a greetings library.</small>\n </footer>\n <script>\n function init() {\n return greet(\"world\");\n }\n </script>\n </body>",
119
+ "line_start": 16,
120
+ "line_end": 33,
121
+ "metadata": {
122
+ "module": "",
123
+ "names": "",
124
+ "dots": "",
125
+ "language_hint": ""
126
+ }
127
+ },
128
+ {
129
+ "id": "e7560b4336313437",
130
+ "blob_sha": "sha1",
131
+ "file_path": "html.html",
132
+ "kind": "doc_section",
133
+ "name": "header",
134
+ "scope": "",
135
+ "language": "html",
136
+ "content": "<header class=\"page-header\">\n <h1>Greeter</h1>\n </header>",
137
+ "line_start": 17,
138
+ "line_end": 19,
139
+ "metadata": {
140
+ "module": "",
141
+ "names": "",
142
+ "dots": "",
143
+ "language_hint": ""
144
+ }
145
+ },
146
+ {
147
+ "id": "3c1680d2b75f7fa8",
148
+ "blob_sha": "sha1",
149
+ "file_path": "html.html",
150
+ "kind": "doc_section",
151
+ "name": "content",
152
+ "scope": "",
153
+ "language": "html",
154
+ "content": "<main id=\"content\">\n <section id=\"intro\">\n <p>Format greetings for named recipients.</p>\n </section>\n </main>",
155
+ "line_start": 20,
156
+ "line_end": 24,
157
+ "metadata": {
158
+ "module": "",
159
+ "names": "",
160
+ "dots": "",
161
+ "language_hint": ""
162
+ }
163
+ },
164
+ {
165
+ "id": "537c74674a50f01d",
166
+ "blob_sha": "sha1",
167
+ "file_path": "html.html",
168
+ "kind": "doc_section",
169
+ "name": "intro",
170
+ "scope": "",
171
+ "language": "html",
172
+ "content": "<section id=\"intro\">\n <p>Format greetings for named recipients.</p>\n </section>",
173
+ "line_start": 21,
174
+ "line_end": 23,
175
+ "metadata": {
176
+ "module": "",
177
+ "names": "",
178
+ "dots": "",
179
+ "language_hint": ""
180
+ }
181
+ },
182
+ {
183
+ "id": "766315b968053a92",
184
+ "blob_sha": "sha1",
185
+ "file_path": "html.html",
186
+ "kind": "doc_section",
187
+ "name": "footer",
188
+ "scope": "",
189
+ "language": "html",
190
+ "content": "<footer>\n <small>Greeter &mdash; a greetings library.</small>\n </footer>",
191
+ "line_start": 25,
192
+ "line_end": 27,
193
+ "metadata": {
194
+ "module": "",
195
+ "names": "",
196
+ "dots": "",
197
+ "language_hint": ""
198
+ }
199
+ },
200
+ {
201
+ "id": "ccfc3b2bb3faad2b",
202
+ "blob_sha": "sha1",
203
+ "file_path": "html.html",
204
+ "kind": "class",
205
+ "name": ".greeter",
206
+ "scope": "",
207
+ "language": "css",
208
+ "content": ".greeter {\n font-family: system-ui;\n }",
209
+ "line_start": 11,
210
+ "line_end": 13,
211
+ "metadata": {
212
+ "module": "",
213
+ "names": "",
214
+ "dots": "",
215
+ "language_hint": ""
216
+ }
217
+ },
218
+ {
219
+ "id": "3d6a94c70cb40c26",
220
+ "blob_sha": "sha1",
221
+ "file_path": "html.html",
222
+ "kind": "function",
223
+ "name": "init",
224
+ "scope": "",
225
+ "language": "javascript",
226
+ "content": "function init() {\n return greet(\"world\");\n }",
227
+ "line_start": 29,
228
+ "line_end": 31,
229
+ "metadata": {
230
+ "module": "",
231
+ "names": "",
232
+ "dots": "",
233
+ "language_hint": ""
234
+ }
235
+ },
236
+ {
237
+ "id": "6a463c4d63411e65",
238
+ "blob_sha": "sha1",
239
+ "file_path": "styles.css",
240
+ "kind": "class",
241
+ "name": ".greeter",
242
+ "scope": "",
243
+ "language": "css",
244
+ "content": ".greeter {\n color: #333;\n}",
245
+ "line_start": 1,
246
+ "line_end": 3,
247
+ "metadata": {
248
+ "module": "",
249
+ "names": "",
250
+ "dots": "",
251
+ "language_hint": ""
252
+ }
253
+ }
254
+ ]
@@ -0,0 +1,31 @@
1
+ """HTML extraction test cases."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pytest_cases import case
6
+
7
+ type SymbolCase = tuple[str, str, list[tuple[str, str, str]]]
8
+
9
+
10
+ @case(tags=["symbol"])
11
+ def case_html_semantic_elements() -> SymbolCase:
12
+ """HTML names an element by its id (even beside a class), else its tag."""
13
+ src = """\
14
+ <html>
15
+ <body>
16
+ <main id="content"><p>Hello</p></main>
17
+ <article class="post" id="first">Text</article>
18
+ <nav>Links</nav>
19
+ </body>
20
+ </html>
21
+ """
22
+ return (
23
+ "html",
24
+ src,
25
+ [
26
+ ("doc_section", "body", ""),
27
+ ("doc_section", "content", ""),
28
+ ("doc_section", "first", ""),
29
+ ("doc_section", "nav", ""),
30
+ ],
31
+ )
@@ -0,0 +1,4 @@
1
+ // Client-side greeter.
2
+ export function greet(name) {
3
+ return `Hello, ${name}`;
4
+ }
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <!-- Greeter page. The HTML plugin extracts <script src>/<link href>
3
+ as imports (with a language hint) and major <body> elements as
4
+ doc sections. -->
5
+ <html lang="en">
6
+ <head>
7
+ <title>Greeter</title>
8
+ <link rel="stylesheet" href="styles.css">
9
+ <script src="greeter.js"></script>
10
+ <style>
11
+ .greeter {
12
+ font-family: system-ui;
13
+ }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <header class="page-header">
18
+ <h1>Greeter</h1>
19
+ </header>
20
+ <main id="content">
21
+ <section id="intro">
22
+ <p>Format greetings for named recipients.</p>
23
+ </section>
24
+ </main>
25
+ <footer>
26
+ <small>Greeter &mdash; a greetings library.</small>
27
+ </footer>
28
+ <script>
29
+ function init() {
30
+ return greet("world");
31
+ }
32
+ </script>
33
+ </body>
34
+ </html>
@@ -0,0 +1,3 @@
1
+ .greeter {
2
+ color: #333;
3
+ }
@@ -0,0 +1,78 @@
1
+ """HTML extraction tests.
2
+
3
+ The symbol case (`cases_extraction.py`) drives the shared check; the functions
4
+ below pin HTML's element naming and its `<script src>` / `<link href>` import
5
+ and non-semantic-presence edge behaviour.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from pytest_cases import parametrize_with_cases
11
+
12
+ from rbtr.git import FileEntry
13
+ from rbtr.index.models import ChunkKind
14
+ from rbtr.languages.extract import extract_file
15
+
16
+
17
+ @parametrize_with_cases("lang, source, expected", cases=".cases_extraction", has_tag="symbol")
18
+ def test_extracts_expected_symbols(lang: str, source: str, expected: list) -> None:
19
+ """Each expected (kind, name, scope) tuple appears in the output."""
20
+ chunks = extract_file(FileEntry("input", "sha1", source.encode()), lang)
21
+ symbols = [(c.kind, c.name, c.scope) for c in chunks]
22
+ for exp in expected:
23
+ assert exp in symbols, f"expected {exp} not found in {symbols}"
24
+
25
+
26
+ def test_html_non_semantic_only_emits_presence() -> None:
27
+ """HTML with no head/body/semantic element yields only a presence chunk.
28
+
29
+ A non-semantic wrapper (`<div>`) is not elevated, so no searchable
30
+ doc_section is produced; the engine appends one content-less host chunk.
31
+ """
32
+ chunks = extract_file(FileEntry("input", "sha1", b"<div>hello</div>"), "html")
33
+ assert [c.kind for c in chunks if c.content] == []
34
+ assert [c.language for c in chunks] == ["html"]
35
+
36
+
37
+ def test_html_script_src_produces_import() -> None:
38
+ """HTML <script src> produces an import chunk."""
39
+ src = """\
40
+ <html>
41
+ <head><script src="app.js"></script></head>
42
+ <body><p>hello</p></body>
43
+ </html>
44
+ """
45
+ chunks = extract_file(FileEntry("input", "sha1", src.encode()), "html")
46
+ imports = [c for c in chunks if c.kind == ChunkKind.IMPORT]
47
+ assert len(imports) == 1
48
+ assert imports[0].metadata.module == "app.js"
49
+ assert imports[0].metadata.language_hint == "javascript"
50
+
51
+
52
+ def test_html_link_href_produces_import() -> None:
53
+ """HTML <link href> produces an import chunk."""
54
+ src = """\
55
+ <html>
56
+ <head><link rel="stylesheet" href="styles.css"></head>
57
+ <body><p>hello</p></body>
58
+ </html>
59
+ """
60
+ chunks = extract_file(FileEntry("input", "sha1", src.encode()), "html")
61
+ imports = [c for c in chunks if c.kind == ChunkKind.IMPORT]
62
+ assert len(imports) == 1
63
+ assert imports[0].metadata.module == "styles.css"
64
+ assert imports[0].metadata.language_hint == "css"
65
+
66
+
67
+ def test_html_self_closing_link_produces_import() -> None:
68
+ """An XHTML-style self-closing `<link ... />` produces an import."""
69
+ src = """\
70
+ <html>
71
+ <head><link rel="stylesheet" href="styles.css" /></head>
72
+ <body><p>hello</p></body>
73
+ </html>
74
+ """
75
+ chunks = extract_file(FileEntry("input", "sha1", src.encode()), "html")
76
+ imports = [c for c in chunks if c.kind == ChunkKind.IMPORT]
77
+ assert len(imports) == 1
78
+ assert imports[0].metadata.module == "styles.css"
@@ -0,0 +1,81 @@
1
+ """HTML sample extraction: the `samples/html/` project through the real pipeline.
2
+
3
+ The sample links a `.js` and a `.css` and embeds inline `<script>`/`<style>`,
4
+ so the javascript and css plugins (dev dependencies) extract the linked and
5
+ injected chunks, and the edge snapshot captures the cross-file links.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from pathlib import Path
11
+ from typing import TYPE_CHECKING
12
+
13
+ import pytest
14
+ from tree_sitter import Parser
15
+
16
+ from rbtr.git import FileEntry
17
+ from rbtr.index.models import Chunk, ChunkKind, Edge
18
+ from rbtr.languages.edges import build_resolution_map, infer_import_edges
19
+ from rbtr.languages.extract import extract_file
20
+ from rbtr.languages.manager import get_manager
21
+ from rbtr.testing import render_edges
22
+
23
+ if TYPE_CHECKING:
24
+ from syrupy.assertion import SnapshotAssertion
25
+
26
+
27
+ @pytest.fixture
28
+ def project() -> list[tuple[str, str]]:
29
+ """The `(relative path, text)` files of the `samples/html/` project."""
30
+ root = Path(__file__).parent / "samples" / "html"
31
+ return [
32
+ (str(p.relative_to(root)), p.read_text()) for p in sorted(root.rglob("*")) if p.is_file()
33
+ ]
34
+
35
+
36
+ @pytest.fixture
37
+ def chunks(project: list[tuple[str, str]]) -> list[Chunk]:
38
+ """Chunks from every project file, each via the real `extract_file`.
39
+
40
+ A file is extracted as its own detected language, so the project spans
41
+ html, javascript, and css.
42
+ """
43
+ manager = get_manager()
44
+ out: list[Chunk] = []
45
+ for path, text in project:
46
+ lang = manager.detect_language(path) or "html"
47
+ out.extend(extract_file(FileEntry(path, "sha1", text.encode()), lang))
48
+ return out
49
+
50
+
51
+ @pytest.fixture
52
+ def edges(project: list[tuple[str, str]], chunks: list[Chunk]) -> list[Edge]:
53
+ """Import edges inferred across the project's files."""
54
+ manager = get_manager()
55
+ repo_files = {path for path, _ in project}
56
+ return infer_import_edges(chunks, repo_files, build_resolution_map(manager))
57
+
58
+
59
+ def test_emits_expected_kinds(chunks: list[Chunk]) -> None:
60
+ """The sample exercises HTML's import, doc-section, and (injected) function chunks."""
61
+ kinds = {c.kind for c in chunks}
62
+ assert {ChunkKind.IMPORT, ChunkKind.DOC_SECTION, ChunkKind.FUNCTION, ChunkKind.COMMENT} <= kinds
63
+
64
+
65
+ def test_parses_cleanly(project: list[tuple[str, str]]) -> None:
66
+ """Every project file is valid source — no tree-sitter ERROR/MISSING nodes."""
67
+ manager = get_manager()
68
+ for path, text in project:
69
+ grammar = manager.grammar(manager.detect_language(path) or "html")
70
+ assert grammar is not None
71
+ assert not Parser(grammar).parse(text.encode()).root_node.has_error, path
72
+
73
+
74
+ def test_extraction_matches_snapshot(chunks: list[Chunk], snapshot_json: SnapshotAssertion) -> None:
75
+ assert chunks == snapshot_json
76
+
77
+
78
+ def test_edges_match_snapshot(
79
+ chunks: list[Chunk], edges: list[Edge], snapshot_json: SnapshotAssertion
80
+ ) -> None:
81
+ assert render_edges(edges, chunks) == snapshot_json
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: rbtr-lang-html
3
+ Version: 2026.7.0.dev0
4
+ Summary: rbtr — HTML language plugin
5
+ License-Expression: MIT
6
+ Requires-Dist: rbtr==2026.7.0.dev0
7
+ Requires-Dist: tree-sitter-html
8
+ Requires-Python: >=3.13
@@ -0,0 +1,18 @@
1
+ rbtr_lang_html/__init__.py,sha256=Ifd5TOOkiyk4FVpH_H05Y_OaYUAdB_WJAWZccTw0ZTE,36
2
+ rbtr_lang_html/html.scm,sha256=pJD-czYLz_D7aZkNG1kKR5rSNcrYzta3gU-mvvaV4ls,733
3
+ rbtr_lang_html/injections.scm,sha256=8KIi5RGBArLNv3MZEGQQ5zWugGMRamCf6y4NiAnNXOs,316
4
+ rbtr_lang_html/plugin.py,sha256=TcGamk_MdfNaaOZSRDRIap9gNuSo8d7neAMyUPNKTMs,3946
5
+ rbtr_lang_html/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ rbtr_lang_html/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ rbtr_lang_html/tests/__snapshots__/test_samples/test_edges_match_snapshot.json,sha256=h3GTsS80PKJHjcVELR63vPsOfsCbNwUmp_xfgf17izk,183
8
+ rbtr_lang_html/tests/__snapshots__/test_samples/test_extraction_matches_snapshot.json,sha256=fS01IS0qS-uB2v8Yd8f9qx9nQhrYQW7kziBUUEyUfHg,6489
9
+ rbtr_lang_html/tests/cases_extraction.py,sha256=MK6vNe5kdEqAYYp6h8Wcb8npKs1tLwjdDNZoE35lDog,712
10
+ rbtr_lang_html/tests/samples/html/greeter.js,sha256=79U_oQoQr9Hrnheou3syf_Fc1nBXlSwvbLSJiO4h2Yk,83
11
+ rbtr_lang_html/tests/samples/html/html.html,sha256=Rul0PJdMeAXTOScCOyIKF9-HUWa9COaeDK0BDj1Z1jI,812
12
+ rbtr_lang_html/tests/samples/html/styles.css,sha256=8SA3GIIHSpPFdXHLF0mif0lUB8QvIr48kAfBPwNlA50,28
13
+ rbtr_lang_html/tests/test_extraction.py,sha256=l1xVVBBPOczgVLURHpMCxD_jokwTy1erL_mrruuIxBs,2869
14
+ rbtr_lang_html/tests/test_samples.py,sha256=ZqCMjx5dUE7p5XK2L6ruBX_vbt17pCHPFSLOrXXl168,2939
15
+ rbtr_lang_html-2026.7.0.dev0.dist-info/WHEEL,sha256=CoDSoyhtC_eO_tlxRYzsTraPv1fPJRXFx91k6ISeAvA,81
16
+ rbtr_lang_html-2026.7.0.dev0.dist-info/entry_points.txt,sha256=kDPcrHuXzWY9QOwVpNf7bqNZKzSf-HcsQ4OVPxUgEzc,52
17
+ rbtr_lang_html-2026.7.0.dev0.dist-info/METADATA,sha256=YKbPVi_R5HG_gz4BPSABxb2Y37WZjm8JYEQ60yT3Tlo,220
18
+ rbtr_lang_html-2026.7.0.dev0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.28
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [rbtr.languages]
2
+ html = rbtr_lang_html.plugin:html
3
+