@jefuriiij/synthra 0.1.20 → 0.1.21
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.
- package/CHANGELOG.md +23 -0
- package/dist/cli/index.js +56 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/index.js +1 -1
- package/dist/dashboard/index.js.map +1 -1
- package/dist/server/index.js +55 -1
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ For older versions, see [GitHub Releases](https://github.com/jefuriiij/synthra/r
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.1.21] — 2026-06-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **HubL (HubSpot CMS) symbol extraction for `.html` and `.hubl` files.**
|
|
15
|
+
Previously `.html` files were content-indexed only — keyword search and
|
|
16
|
+
whole-file reads, no symbol-level granularity. On HubSpot projects this
|
|
17
|
+
meant the graph contributed nothing: zero `graph_continue`/`graph_read`
|
|
18
|
+
calls resolved to symbol slices all session. Now `.html` and `.hubl` files
|
|
19
|
+
run through a new **regex-based** parser (`parsers/hubl.ts`; there is no
|
|
20
|
+
tree-sitter grammar for HubL):
|
|
21
|
+
- `{% macro name(args) %}` → extracted as a `function` symbol
|
|
22
|
+
- `{% block name %}` → extracted as a `component` symbol
|
|
23
|
+
- `{% include / extends / import / from "path" %}` → import edges (relative
|
|
24
|
+
paths resolve to local templates; `.html`/`.hubl` added to the resolver's
|
|
25
|
+
extension list)
|
|
26
|
+
|
|
27
|
+
Plain HTML with no HubL tags is unaffected — the parser yields zero symbols
|
|
28
|
+
and zero imports, identical to before. No API, protocol, or policy-block
|
|
29
|
+
change. Roadmap item #12.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
10
33
|
## [0.1.20] — 2026-06-06
|
|
11
34
|
|
|
12
35
|
### Fixed
|
package/dist/cli/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var init_package = __esm({
|
|
|
18
18
|
"package.json"() {
|
|
19
19
|
package_default = {
|
|
20
20
|
name: "@jefuriiij/synthra",
|
|
21
|
-
version: "0.1.
|
|
21
|
+
version: "0.1.21",
|
|
22
22
|
publishConfig: {
|
|
23
23
|
access: "public"
|
|
24
24
|
},
|
|
@@ -2170,7 +2170,7 @@ function extractKeywords(content, _ext) {
|
|
|
2170
2170
|
}
|
|
2171
2171
|
|
|
2172
2172
|
// src/scanner/extract.ts
|
|
2173
|
-
var RESOLVE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".svelte", ".vue", ".dart"];
|
|
2173
|
+
var RESOLVE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".svelte", ".vue", ".dart", ".html", ".hubl"];
|
|
2174
2174
|
var INDEX_FILES = ["index.ts", "index.tsx", "index.js", "index.jsx", "__init__.py"];
|
|
2175
2175
|
function fileId(relPath) {
|
|
2176
2176
|
return `file:${relPath}`;
|
|
@@ -2574,6 +2574,57 @@ async function parseGo(f, source) {
|
|
|
2574
2574
|
);
|
|
2575
2575
|
}
|
|
2576
2576
|
|
|
2577
|
+
// src/scanner/parsers/hubl.ts
|
|
2578
|
+
var MACRO_RE = /\{%-?\s*macro\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/g;
|
|
2579
|
+
var ENDMACRO_RE = /\{%-?\s*endmacro\b/g;
|
|
2580
|
+
var BLOCK_RE = /\{%-?\s*block\s+([A-Za-z_]\w*)/g;
|
|
2581
|
+
var ENDBLOCK_RE = /\{%-?\s*endblock\b/g;
|
|
2582
|
+
var IMPORT_RE = /\{%-?\s*(?:include|extends|import|from)\s+["']([^"']+)["']/g;
|
|
2583
|
+
function lineAt(source, index) {
|
|
2584
|
+
return source.slice(0, index).split(/\r?\n/).length;
|
|
2585
|
+
}
|
|
2586
|
+
function endLineAfter(source, fromIndex, endRe, startLine) {
|
|
2587
|
+
endRe.lastIndex = fromIndex;
|
|
2588
|
+
const m = endRe.exec(source);
|
|
2589
|
+
return m ? lineAt(source, m.index) : startLine;
|
|
2590
|
+
}
|
|
2591
|
+
function parseHubL(f, source) {
|
|
2592
|
+
const symbols = [];
|
|
2593
|
+
const imports = [];
|
|
2594
|
+
for (const m of source.matchAll(MACRO_RE)) {
|
|
2595
|
+
const name = m[1];
|
|
2596
|
+
if (!name) continue;
|
|
2597
|
+
const args = (m[2] ?? "").trim();
|
|
2598
|
+
const start = m.index ?? 0;
|
|
2599
|
+
const startLine = lineAt(source, start);
|
|
2600
|
+
symbols.push({
|
|
2601
|
+
name,
|
|
2602
|
+
kind: "function",
|
|
2603
|
+
startLine,
|
|
2604
|
+
endLine: endLineAfter(source, start + m[0].length, ENDMACRO_RE, startLine),
|
|
2605
|
+
signature: `macro ${name}(${args})`
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
for (const m of source.matchAll(BLOCK_RE)) {
|
|
2609
|
+
const name = m[1];
|
|
2610
|
+
if (!name) continue;
|
|
2611
|
+
const start = m.index ?? 0;
|
|
2612
|
+
const startLine = lineAt(source, start);
|
|
2613
|
+
symbols.push({
|
|
2614
|
+
name,
|
|
2615
|
+
kind: "component",
|
|
2616
|
+
startLine,
|
|
2617
|
+
endLine: endLineAfter(source, start + m[0].length, ENDBLOCK_RE, startLine),
|
|
2618
|
+
signature: `block ${name}`
|
|
2619
|
+
});
|
|
2620
|
+
}
|
|
2621
|
+
for (const m of source.matchAll(IMPORT_RE)) {
|
|
2622
|
+
const spec = m[1];
|
|
2623
|
+
if (spec) imports.push(spec);
|
|
2624
|
+
}
|
|
2625
|
+
return { file: f, source, symbols, imports: Array.from(new Set(imports)), calls: [] };
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2577
2628
|
// src/scanner/parsers/java.ts
|
|
2578
2629
|
var QUERY6 = `
|
|
2579
2630
|
(class_declaration name: (identifier) @class.name) @class
|
|
@@ -3012,6 +3063,9 @@ async function parseFile(f) {
|
|
|
3012
3063
|
return parseSvelte(f, source);
|
|
3013
3064
|
case ".vue":
|
|
3014
3065
|
return parseVue(f, source);
|
|
3066
|
+
case ".html":
|
|
3067
|
+
case ".hubl":
|
|
3068
|
+
return parseHubL(f, source);
|
|
3015
3069
|
case ".go":
|
|
3016
3070
|
return parseGo(f, source);
|
|
3017
3071
|
case ".rs":
|