@barefootjs/mojolicious 0.1.0

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,219 @@
1
+ /**
2
+ * BarefootJS Mojolicious EP Template Adapter
3
+ *
4
+ * Generates Mojolicious EP template files (.html.ep) from BarefootJS IR.
5
+ */
6
+ import type { ComponentIR, IRNode, IRElement, IRText, IRExpression, IRConditional, IRLoop, IRComponent, IRFragment, IRSlot, IRIfStatement, IRProvider, IRAsync, TemplatePrimitiveRegistry } from '@barefootjs/jsx';
7
+ import { BaseAdapter, type AdapterOutput, type AdapterGenerateOptions, type IRNodeEmitter, type EmitIRNode } from '@barefootjs/jsx';
8
+ /**
9
+ * Mojo adapter's IRNode render context. Mojo's lowering currently
10
+ * doesn't consume any render-position flags (`isRootOfClientComponent`
11
+ * is handled differently here than in Hono/Go), so the Ctx is empty.
12
+ * Kept as a named alias so future flags can extend it without changing
13
+ * the `IRNodeEmitter` interface.
14
+ */
15
+ type MojoRenderCtx = Record<string, never>;
16
+ import type { ParsedExpr } from '@barefootjs/jsx';
17
+ export interface MojoAdapterOptions {
18
+ /** Base path for client JS files (default: '/static/components/') */
19
+ clientJsBasePath?: string;
20
+ /** Path to barefoot.js runtime (default: '/static/components/barefoot.js') */
21
+ barefootJsPath?: string;
22
+ }
23
+ export declare class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRenderCtx> {
24
+ name: string;
25
+ extension: string;
26
+ templatesPerComponent: boolean;
27
+ /**
28
+ * Identifier-path callees the Mojo runtime can render in template
29
+ * scope. The relocate pass consults this map to mark matching
30
+ * calls as template-safe so the surrounding expression stays
31
+ * inlinable; the SSR template emitter substitutes the JS call
32
+ * with the registered Perl helper invocation.
33
+ *
34
+ * The per-callee arity is read directly off `MOJO_TEMPLATE_PRIMITIVES`
35
+ * at substitution time, so this exposed shape stays as the
36
+ * `TemplateAdapter` interface expects (`emit`-only) without
37
+ * carrying a parallel arity map.
38
+ */
39
+ templatePrimitives: TemplatePrimitiveRegistry;
40
+ private componentName;
41
+ private options;
42
+ private errors;
43
+ private inLoop;
44
+ /**
45
+ * Re-entry guard for `convertHigherOrderExpr` (#1421).
46
+ *
47
+ * `MojoTopLevelEmitter.unsupported` falls back to the regex pipeline
48
+ * via `_convertExpressionToPerlPublic`, which re-detects the
49
+ * `.filter|every|some` short-circuit and re-enters
50
+ * `convertHigherOrderExpr` with the same raw text. When the parser
51
+ * carries the full original expression down to every nested
52
+ * `unsupported` node (e.g. an array-literal callee that the AST
53
+ * can't classify), the cycle has no terminator and the JS stack
54
+ * blows. The guard records the expression on entry, emits BF101 on
55
+ * second visit, and bails out — so the user sees an actionable
56
+ * diagnostic instead of `RangeError: Maximum call stack size`.
57
+ */
58
+ private higherOrderInFlight;
59
+ /**
60
+ * SolidJS-style props identifier (`function(props: P)`) and the
61
+ * analyzer-extracted prop names. Stashed at `generate()` entry so
62
+ * the per-attribute `emitSpread` callback can build a propsObject
63
+ * spread bag as an inline Perl hashref literal without re-walking
64
+ * the IR (#1407 follow-up).
65
+ */
66
+ private propsObjectName;
67
+ private propsParams;
68
+ constructor(options?: MojoAdapterOptions);
69
+ generate(ir: ComponentIR, options?: AdapterGenerateOptions): AdapterOutput;
70
+ private generateScriptRegistrations;
71
+ private hasClientInteractivity;
72
+ /**
73
+ * Public entry point for node rendering. Delegates to the shared
74
+ * `IRNodeEmitter` dispatcher (#1290 step 1); per-kind logic lives in
75
+ * the `IRNodeEmitter` methods below.
76
+ */
77
+ renderNode(node: IRNode): string;
78
+ emitElement(node: IRElement, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
79
+ emitText(node: IRText): string;
80
+ emitExpression(node: IRExpression): string;
81
+ emitConditional(node: IRConditional, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
82
+ emitLoop(node: IRLoop, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
83
+ emitComponent(node: IRComponent, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
84
+ emitFragment(node: IRFragment, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
85
+ emitSlot(node: IRSlot): string;
86
+ emitIfStatement(node: IRIfStatement, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
87
+ emitProvider(node: IRProvider, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
88
+ emitAsync(node: IRAsync, _ctx: MojoRenderCtx, _emit: EmitIRNode<MojoRenderCtx>): string;
89
+ renderElement(element: IRElement): string;
90
+ renderExpression(expr: IRExpression): string;
91
+ renderConditional(cond: IRConditional): string;
92
+ private renderNodeOrNull;
93
+ /**
94
+ * Add bf-c attribute to the first HTML element in a branch.
95
+ * If no element found, wrap with comment markers.
96
+ */
97
+ private addCondMarkerToFirstElement;
98
+ /**
99
+ * Push a `BF103` diagnostic for every component reference inside a
100
+ * loop body whose name is imported from a relative-path module.
101
+ * Mirror of the Go adapter's check — the Mojo adapter has the same
102
+ * cross-template-registration constraint at request time.
103
+ */
104
+ private checkImportedLoopChildComponents;
105
+ renderLoop(loop: IRLoop): string;
106
+ /**
107
+ * AttrValue lowering for component invocation props (Mojo / Perl
108
+ * named-arg form). Routed through the shared dispatcher so a new
109
+ * AttrValue kind becomes a TS compile error here (#1290 step 2).
110
+ *
111
+ * `jsx-children` returns empty — children are captured via Mojo's
112
+ * `begin %>…<% end` block below, not threaded through the
113
+ * `render_child` named-arg list.
114
+ */
115
+ private readonly componentPropEmitter;
116
+ renderComponent(comp: IRComponent): string;
117
+ private childrenCaptureCounter;
118
+ private toTemplateName;
119
+ private renderIfStatement;
120
+ private renderFragment;
121
+ private renderSlot;
122
+ renderAsync(node: IRAsync): string;
123
+ /**
124
+ * AttrValue lowering for intrinsic-element attributes (Mojo / EP
125
+ * template). Routed through the shared dispatcher (#1290 step 2).
126
+ */
127
+ private readonly elementAttrEmitter;
128
+ private renderAttributes;
129
+ renderScopeMarker(_instanceIdExpr: string): string;
130
+ renderSlotMarker(slotId: string): string;
131
+ renderCondMarker(condId: string): string;
132
+ /**
133
+ * Convert a ParsedExpr AST to Perl expression string for filter
134
+ * predicates. Wraps the shared ParsedExpr dispatcher with a
135
+ * `MojoFilterEmitter` carrying the predicate's loop param and
136
+ * any block-body local var aliases (#1250 phase 1B).
137
+ */
138
+ private renderPerlFilterExpr;
139
+ /**
140
+ * Render a complex block body filter into a Perl condition.
141
+ * Handles patterns like: filter(t => { const f = filter(); if (...) return ...; })
142
+ */
143
+ private renderBlockBodyCondition;
144
+ private collectReturnPaths;
145
+ private buildSinglePathCondition;
146
+ private renderConditionsAnd;
147
+ private convertTemplateLiteralPartsToPerl;
148
+ /**
149
+ * Translate `${EXPR}` interpolations in a static template-part string
150
+ * into Perl variable references and concatenate them with the
151
+ * surrounding literal text. Used by `convertTemplateLiteralPartsToPerl`
152
+ * when a `string` part still carries unresolved interpolations (e.g.
153
+ * `${className}` from a destructured prop the IR analyzer couldn't
154
+ * inline statically).
155
+ */
156
+ private substituteJsInterpolationsToPerl;
157
+ /**
158
+ * Refuse JS expression shapes that have no idiomatic Mojo template
159
+ * representation (#1322). Currently catches:
160
+ *
161
+ * - Object literals (`style={{ background: bg(), color: fg() }}`):
162
+ * the regex pipeline strips signal calls but leaves the
163
+ * surrounding `{ k: v, ... }` syntax intact, producing invalid
164
+ * Perl inside `<%= ... %>`.
165
+ * - Tagged-template-literal call expressions
166
+ * (`className={cn\`base \${tone()}\`}`): regex translation
167
+ * produces malformed Perl with no callable target.
168
+ *
169
+ * Records `BF101` with the same shape the Go adapter emits via
170
+ * `convertExpressionToGo`, so cross-adapter diagnostics stay
171
+ * consistent. Returns `true` when the shape was rejected (caller
172
+ * should drop the attribute / skip the emit).
173
+ */
174
+ private refuseUnsupportedAttrExpression;
175
+ private convertExpressionToPerl;
176
+ /**
177
+ * Walk the parsed AST of `expr` and substitute each registered
178
+ * primitive call (e.g. `JSON.stringify(props.config)`) with its
179
+ * Mojo helper-call equivalent (e.g. `bf->json($config)`). All
180
+ * other shapes round-trip back to source text via
181
+ * `stringifyParsedExpr`, so the result is still a JS-shaped
182
+ * string that the existing regex pipeline in
183
+ * `convertExpressionToPerl` can finish translating.
184
+ *
185
+ * Bails out (returns the input unchanged) when:
186
+ * - the expression doesn't parse cleanly,
187
+ * - no primitive call is found in the AST, or
188
+ * - a primitive's arity doesn't match the registered shape
189
+ * (BF101 is recorded so the user sees the diagnostic).
190
+ *
191
+ * Identifier-path-only matching (#1187 R1) — same constraint the
192
+ * Go adapter applies in #1188.
193
+ */
194
+ private rewriteTemplatePrimitives;
195
+ /**
196
+ * Convert expressions containing higher-order array methods to Perl.
197
+ * Parses the full expression as AST and renders recursively.
198
+ *
199
+ * Handles patterns like:
200
+ * - todos().filter(t => !t.done).length → scalar(grep { !$_->{done} } @{$todos})
201
+ * - todos().every(t => t.done) → !(grep { !$_->{done} } @{$todos})
202
+ * - todos().filter(t => t.done).length > 0 → scalar(grep { $_->{done} } @{$todos}) > 0
203
+ */
204
+ private convertHigherOrderExpr;
205
+ /**
206
+ * Render a full ParsedExpr tree to Perl for top-level (non-filter)
207
+ * expressions where identifiers are signals / stash vars. Delegates
208
+ * to the shared ParsedExpr dispatcher with `MojoTopLevelEmitter`
209
+ * (#1250 phase 1B).
210
+ */
211
+ private renderParsedExprToPerl;
212
+ /** Internal hook exposed to the top-level emitter for unsupported nodes. */
213
+ _convertExpressionToPerlPublic(raw: string): string;
214
+ /** Internal hook for higher-order: predicate body re-uses the filter emitter. */
215
+ _renderPerlFilterExprPublic(expr: ParsedExpr, param: string): string;
216
+ }
217
+ export declare const mojoAdapter: MojoAdapter;
218
+ export {};
219
+ //# sourceMappingURL=mojo-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mojo-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/mojo-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { BuildOptions } from '@barefootjs/jsx';
2
+ import { MojoAdapter } from './adapter';
3
+ import type { MojoAdapterOptions } from './adapter';
4
+ export interface MojoBuildOptions extends BuildOptions {
5
+ /** Adapter-specific options passed to MojoAdapter */
6
+ adapterOptions?: MojoAdapterOptions;
7
+ }
8
+ /**
9
+ * Create a BarefootBuildConfig for Mojolicious EP template projects.
10
+ *
11
+ * Uses structural typing — does not import BarefootBuildConfig to avoid a
12
+ * circular dependency between @barefootjs/mojolicious and @barefootjs/cli.
13
+ */
14
+ export declare function createConfig(options?: MojoBuildOptions): {
15
+ adapter: MojoAdapter;
16
+ paths: import("@barefootjs/jsx").BarefootPaths | undefined;
17
+ components: string[] | undefined;
18
+ outDir: string | undefined;
19
+ minify: boolean | undefined;
20
+ contentHash: boolean | undefined;
21
+ externals: Record<string, import("@barefootjs/jsx").ExternalSpec> | undefined;
22
+ externalsBasePath: string | undefined;
23
+ bundleEntries: import("@barefootjs/jsx").BundleEntry[] | undefined;
24
+ localImportPrefixes: string[] | undefined;
25
+ outputLayout: import("@barefootjs/jsx").OutputLayout;
26
+ postBuild: ((ctx: import("@barefootjs/jsx").PostBuildContext) => Promise<void> | void) | undefined;
27
+ };
28
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAEnD,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,qDAAqD;IACrD,cAAc,CAAC,EAAE,kBAAkB,CAAA;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB;IAEvD,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;IACT,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;IAKZ,SAAS;EAEZ"}