@timber-js/app 0.2.0-alpha.102 → 0.2.0-alpha.103
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/LICENSE +8 -0
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/index.js +53 -39
- package/dist/index.js.map +1 -1
- package/package.json +6 -7
- package/src/cli.ts +0 -0
- package/src/fonts/ast.ts +64 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timber-js/app",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.103",
|
|
4
4
|
"description": "Vite-native React framework built for Servers and Serverless Platforms — correct HTTP semantics, real status codes, pages that work without JavaScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare-workers",
|
|
@@ -110,11 +110,6 @@
|
|
|
110
110
|
"publishConfig": {
|
|
111
111
|
"access": "public"
|
|
112
112
|
},
|
|
113
|
-
"scripts": {
|
|
114
|
-
"build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
|
|
115
|
-
"typecheck": "tsgo --noEmit",
|
|
116
|
-
"prepublishOnly": "pnpm run build"
|
|
117
|
-
},
|
|
118
113
|
"dependencies": {
|
|
119
114
|
"@opentelemetry/api": "^1.9.1",
|
|
120
115
|
"@opentelemetry/context-async-hooks": "^2.6.1",
|
|
@@ -158,5 +153,9 @@
|
|
|
158
153
|
},
|
|
159
154
|
"engines": {
|
|
160
155
|
"node": ">=22.12.0"
|
|
156
|
+
},
|
|
157
|
+
"scripts": {
|
|
158
|
+
"build": "vite build --config vite.lib.config.ts && tsc --emitDeclarationOnly --project tsconfig.json --outDir dist",
|
|
159
|
+
"typecheck": "tsgo --noEmit"
|
|
161
160
|
}
|
|
162
|
-
}
|
|
161
|
+
}
|
package/src/cli.ts
CHANGED
|
File without changes
|
package/src/fonts/ast.ts
CHANGED
|
@@ -590,8 +590,8 @@ interface CallExpressionNode extends PositionedNode {
|
|
|
590
590
|
|
|
591
591
|
interface VariableDeclaratorNode extends PositionedNode {
|
|
592
592
|
type: 'VariableDeclarator';
|
|
593
|
-
id:
|
|
594
|
-
init:
|
|
593
|
+
id: PositionedNode;
|
|
594
|
+
init: PositionedNode | null;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
597
|
interface VariableDeclarationNode extends PositionedNode {
|
|
@@ -601,7 +601,43 @@ interface VariableDeclarationNode extends PositionedNode {
|
|
|
601
601
|
|
|
602
602
|
interface ExpressionStatementNode extends PositionedNode {
|
|
603
603
|
type: 'ExpressionStatement';
|
|
604
|
-
expression:
|
|
604
|
+
expression: PositionedNode;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
interface ExportNamedDeclarationNode extends PositionedNode {
|
|
608
|
+
type: 'ExportNamedDeclaration';
|
|
609
|
+
declaration: VariableDeclarationNode | ExpressionStatementNode | null;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// ── Type guards for AST narrowing ────────────────────────────────────────────
|
|
613
|
+
//
|
|
614
|
+
// OXC's parsed nodes all share the base `PositionedNode` shape with
|
|
615
|
+
// `type: string`. TypeScript can't narrow a union that includes a
|
|
616
|
+
// `string`-typed catch-all, so we use explicit type guards instead of
|
|
617
|
+
// bare `.type ===` checks.
|
|
618
|
+
|
|
619
|
+
function isImportDeclaration(node: PositionedNode): node is ImportDeclarationNode {
|
|
620
|
+
return node.type === 'ImportDeclaration';
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
function isVariableDeclaration(node: PositionedNode): node is VariableDeclarationNode {
|
|
624
|
+
return node.type === 'VariableDeclaration';
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function isExpressionStatement(node: PositionedNode): node is ExpressionStatementNode {
|
|
628
|
+
return node.type === 'ExpressionStatement';
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function isExportNamedDeclaration(node: PositionedNode): node is ExportNamedDeclarationNode {
|
|
632
|
+
return node.type === 'ExportNamedDeclaration';
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function isCallExpression(node: PositionedNode): node is CallExpressionNode {
|
|
636
|
+
return node.type === 'CallExpression';
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function isIdentifier(node: AstNode): node is IdentifierNode {
|
|
640
|
+
return node.type === 'Identifier';
|
|
605
641
|
}
|
|
606
642
|
|
|
607
643
|
interface ProgramNode extends PositionedNode {
|
|
@@ -627,8 +663,8 @@ export function findFontCallSites(source: string): FontAnalysis | null {
|
|
|
627
663
|
const importNodesToRemove: Array<{ start: number; end: number }> = [];
|
|
628
664
|
|
|
629
665
|
for (const stmt of program.body) {
|
|
630
|
-
if (stmt
|
|
631
|
-
const importDecl = stmt
|
|
666
|
+
if (!isImportDeclaration(stmt)) continue;
|
|
667
|
+
const importDecl = stmt;
|
|
632
668
|
const specSource = importDecl.source.value;
|
|
633
669
|
|
|
634
670
|
let provider: 'google' | 'local' | null = null;
|
|
@@ -658,7 +694,7 @@ export function findFontCallSites(source: string): FontAnalysis | null {
|
|
|
658
694
|
// member expressions in the call-site walk.
|
|
659
695
|
}
|
|
660
696
|
|
|
661
|
-
importNodesToRemove.push({ start:
|
|
697
|
+
importNodesToRemove.push({ start: stmt.start, end: stmt.end });
|
|
662
698
|
}
|
|
663
699
|
|
|
664
700
|
if (bindings.length === 0) return null;
|
|
@@ -669,27 +705,30 @@ export function findFontCallSites(source: string): FontAnalysis | null {
|
|
|
669
705
|
let dynamicCall: string | null = null;
|
|
670
706
|
|
|
671
707
|
for (const stmt of program.body) {
|
|
708
|
+
// Unwrap `export const roboto = Roboto(...)` — the AST wraps the
|
|
709
|
+
// VariableDeclaration inside an ExportNamedDeclaration node.
|
|
710
|
+
const effectiveStmt =
|
|
711
|
+
isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
|
|
712
|
+
|
|
672
713
|
// VariableDeclaration: `const inter = Inter({ ... })`
|
|
673
|
-
if (
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
if (!declarator.init
|
|
677
|
-
const call = declarator.init
|
|
714
|
+
if (isVariableDeclaration(effectiveStmt)) {
|
|
715
|
+
for (const declarator of effectiveStmt.declarations) {
|
|
716
|
+
if (!declarator.init) continue;
|
|
717
|
+
if (!isCallExpression(declarator.init)) continue;
|
|
718
|
+
const call = declarator.init;
|
|
678
719
|
const site = matchCallExpression(call, bindingsByName, source);
|
|
679
720
|
if (!site) continue;
|
|
680
721
|
|
|
681
722
|
if (site === 'dynamic') {
|
|
682
|
-
if (!dynamicCall) {
|
|
683
|
-
const calleeName = (call.callee as IdentifierNode).name;
|
|
723
|
+
if (!dynamicCall && isIdentifier(call.callee)) {
|
|
684
724
|
const argStart = call.arguments[0].start;
|
|
685
725
|
const argEnd = call.arguments[0].end;
|
|
686
|
-
dynamicCall = `${
|
|
726
|
+
dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;
|
|
687
727
|
}
|
|
688
728
|
continue;
|
|
689
729
|
}
|
|
690
730
|
|
|
691
|
-
const assignedName =
|
|
692
|
-
declarator.id.type === 'Identifier' ? (declarator.id as IdentifierNode).name : null;
|
|
731
|
+
const assignedName = isIdentifier(declarator.id) ? declarator.id.name : null;
|
|
693
732
|
|
|
694
733
|
const { line, column } = offsetToLineColumn(source, call.start);
|
|
695
734
|
callSites.push({
|
|
@@ -705,10 +744,9 @@ export function findFontCallSites(source: string): FontAnalysis | null {
|
|
|
705
744
|
}
|
|
706
745
|
|
|
707
746
|
// ExpressionStatement: `Inter({ ... })` as a bare call
|
|
708
|
-
if (
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
const call = exprStmt.expression as unknown as CallExpressionNode;
|
|
747
|
+
if (isExpressionStatement(effectiveStmt)) {
|
|
748
|
+
if (isCallExpression(effectiveStmt.expression)) {
|
|
749
|
+
const call = effectiveStmt.expression;
|
|
712
750
|
const site = matchCallExpression(call, bindingsByName, source);
|
|
713
751
|
if (site && site !== 'dynamic') {
|
|
714
752
|
const { line, column } = offsetToLineColumn(source, call.start);
|
|
@@ -716,16 +754,15 @@ export function findFontCallSites(source: string): FontAnalysis | null {
|
|
|
716
754
|
binding: site.binding,
|
|
717
755
|
assignedName: null,
|
|
718
756
|
configNode: site.configNode,
|
|
719
|
-
replaceStart:
|
|
720
|
-
replaceEnd:
|
|
757
|
+
replaceStart: effectiveStmt.start,
|
|
758
|
+
replaceEnd: effectiveStmt.end,
|
|
721
759
|
line,
|
|
722
760
|
column,
|
|
723
761
|
});
|
|
724
|
-
} else if (site === 'dynamic' && !dynamicCall) {
|
|
725
|
-
const calleeName = (call.callee as IdentifierNode).name;
|
|
762
|
+
} else if (site === 'dynamic' && !dynamicCall && isIdentifier(call.callee)) {
|
|
726
763
|
const argStart = call.arguments[0].start;
|
|
727
764
|
const argEnd = call.arguments[0].end;
|
|
728
|
-
dynamicCall = `${
|
|
765
|
+
dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;
|
|
729
766
|
}
|
|
730
767
|
}
|
|
731
768
|
}
|
|
@@ -817,8 +854,8 @@ function matchCallExpression(
|
|
|
817
854
|
bindings: Map<string, FontBinding>,
|
|
818
855
|
_source: string
|
|
819
856
|
): { binding: FontBinding; configNode: AstNode } | 'dynamic' | null {
|
|
820
|
-
if (call.callee
|
|
821
|
-
const calleeName =
|
|
857
|
+
if (!isIdentifier(call.callee)) return null;
|
|
858
|
+
const calleeName = call.callee.name;
|
|
822
859
|
const binding = bindings.get(calleeName);
|
|
823
860
|
if (!binding) return null;
|
|
824
861
|
|