Parse a Svelte SFC by extracting blocks. Uses the same approach as Vue: parse the outer HTML structure, locate `` `` blocks, detect ``lang="ts"`` for TypeScript, and delegate each block to the appropriate JS/TS parser.
(
self, path: Path, source: bytes,
)
| 1156 | return all_nodes, all_edges |
| 1157 | |
| 1158 | def _parse_svelte( |
| 1159 | self, path: Path, source: bytes, |
| 1160 | ) -> tuple[list[NodeInfo], list[EdgeInfo]]: |
| 1161 | """Parse a Svelte SFC by extracting <script> blocks. |
| 1162 | |
| 1163 | Uses the same approach as Vue: parse the outer HTML structure, |
| 1164 | locate ``<script>`` blocks, detect ``lang="ts"`` for TypeScript, |
| 1165 | and delegate each block to the appropriate JS/TS parser. |
| 1166 | """ |
| 1167 | # Svelte uses HTML-like structure; reuse the vue grammar which |
| 1168 | # also handles generic HTML with <script> elements. |
| 1169 | svelte_parser = self._get_parser("svelte") |
| 1170 | # Fall back to the vue grammar if a dedicated svelte grammar |
| 1171 | # is not available in the installed tree-sitter language pack. |
| 1172 | if not svelte_parser: |
| 1173 | svelte_parser = self._get_parser("vue") |
| 1174 | if not svelte_parser: |
| 1175 | return [], [] |
| 1176 | |
| 1177 | tree = svelte_parser.parse(source) |
| 1178 | file_path_str = str(path) |
| 1179 | test_file = _is_test_file(file_path_str) |
| 1180 | |
| 1181 | all_nodes: list[NodeInfo] = [NodeInfo( |
| 1182 | kind="File", |
| 1183 | name=file_path_str, |
| 1184 | file_path=file_path_str, |
| 1185 | line_start=1, |
| 1186 | line_end=source.count(b"\n") + 1, |
| 1187 | language="svelte", |
| 1188 | is_test=test_file, |
| 1189 | )] |
| 1190 | all_edges: list[EdgeInfo] = [] |
| 1191 | |
| 1192 | # Walk root children looking for script_element blocks |
| 1193 | for child in tree.root_node.children: |
| 1194 | if child.type != "script_element": |
| 1195 | continue |
| 1196 | |
| 1197 | script_lang = "javascript" |
| 1198 | start_tag = None |
| 1199 | raw_text_node = None |
| 1200 | for sub in child.children: |
| 1201 | if sub.type == "start_tag": |
| 1202 | start_tag = sub |
| 1203 | elif sub.type == "raw_text": |
| 1204 | raw_text_node = sub |
| 1205 | |
| 1206 | if start_tag: |
| 1207 | for attr in start_tag.children: |
| 1208 | if attr.type == "attribute": |
| 1209 | attr_name = None |
| 1210 | attr_value = None |
| 1211 | for a in attr.children: |
| 1212 | if a.type == "attribute_name": |
| 1213 | attr_name = a.text.decode( |
| 1214 | "utf-8", errors="replace", |
| 1215 | ) |
no test coverage detected