Phase 4: LiquidJS 模板渲染集成 #40

Closed
opened 2026-05-31 03:37:26 +00:00 by xiaoju · 1 comment
Owner

目标

集成 LiquidJS 引擎,支持自定义模板渲染 + render tag 递归。

交付物

4.1 LiquidJS 依赖引入

  • 添加 liquidjspackages/json-cas 依赖
  • 配置 Liquid 引擎实例

4.2 自定义 render tag

  • 注册自定义 Liquid tag,支持递归渲染子节点
  • {% render child, decay: 0.7 %} — 按指定衰减渲染子节点
  • 未指定 decay 时使用 CLI --decay 或引擎默认值

4.3 模板上下文变量

  • resolution — 当前节点分辨率
  • epsilon — 剪枝阈值
  • hash — 当前节点 hash
  • payload — 节点 payload
  • type — 节点 type hash
  • timestamp — 节点时间戳

4.4 Render 流程整合

  • ucas render <hash> 时按 node type 查找 @ucas/template/text/<type>
  • 找到 → LiquidJS 渲染
  • 没找到 → Phase 3 的默认 YAML 渲染

4.5 Decay 优先级链

  • 模板显式 decay: 0.7 > CLI --decay > 引擎默认 0.5

验证

# 注册 Liquid 模板
ucas template set <schema-hash> workflow.liquid

# 渲染(使用模板)
ucas render <node-hash>                  # 用 Liquid 模板渲染
ucas render <node-hash> --decay 0.8      # 覆盖默认衰减

# 无模板的 node 仍然用 YAML
ucas render <unregistered-type-hash>     # 回退到 YAML

依赖

Phase 2(模板注册)+ Phase 3(render 核心)

Refs #36


小橘 🍊(NEKO Team)

## 目标 集成 LiquidJS 引擎,支持自定义模板渲染 + `render` tag 递归。 ## 交付物 ### 4.1 LiquidJS 依赖引入 - 添加 `liquidjs` 到 `packages/json-cas` 依赖 - 配置 Liquid 引擎实例 ### 4.2 自定义 `render` tag - 注册自定义 Liquid tag,支持递归渲染子节点 - `{% render child, decay: 0.7 %}` — 按指定衰减渲染子节点 - 未指定 decay 时使用 CLI --decay 或引擎默认值 ### 4.3 模板上下文变量 - `resolution` — 当前节点分辨率 - `epsilon` — 剪枝阈值 - `hash` — 当前节点 hash - `payload` — 节点 payload - `type` — 节点 type hash - `timestamp` — 节点时间戳 ### 4.4 Render 流程整合 - `ucas render <hash>` 时按 node type 查找 `@ucas/template/text/<type>` - 找到 → LiquidJS 渲染 - 没找到 → Phase 3 的默认 YAML 渲染 ### 4.5 Decay 优先级链 - 模板显式 `decay: 0.7` > CLI `--decay` > 引擎默认 `0.5` ## 验证 ```bash # 注册 Liquid 模板 ucas template set <schema-hash> workflow.liquid # 渲染(使用模板) ucas render <node-hash> # 用 Liquid 模板渲染 ucas render <node-hash> --decay 0.8 # 覆盖默认衰减 # 无模板的 node 仍然用 YAML ucas render <unregistered-type-hash> # 回退到 YAML ``` ## 依赖 Phase 2(模板注册)+ Phase 3(render 核心) Refs #36 --- 小橘 🍊(NEKO Team)
Author
Owner

🔍 Post-Merge Review: PR #45 — LiquidJS Template Rendering Integration

Summary

PR #45 merged 3 commits adding LiquidJS template rendering to json-cas. Files changed: liquid-render.ts, liquid-render.test.ts, render.ts, index.ts (json-cas), index.ts, cli.test.ts (cli-json-cas), package.json, bun.lock.

What's Good

  • Clean architecture: liquid-render.ts (293 lines) is well-structured with clear separation — engine creation, node rendering, template discovery, and fallback rendering
  • Custom {% render %} tag properly implements variable resolution with dot-path support and explicit decay syntax ({% render payload.child, decay: 0.7 %})
  • Decay priority chain correctly implemented: template explicit > CLI/options > engine default (0.5). Verified by tests 5.1–5.3
  • Template discovery via @ucas/template/text/<type-hash> variable convention works cleanly through VariableStore
  • renderAsync() in render.ts elegantly bridges sync YAML rendering with async template rendering, with proper fallback
  • No dynamic imports in source code — liquidjs is statically imported
  • TypeScript strict mode: no any usage, proper import type for type-only imports, .js extensions in import paths
  • Biome passes: biome check . clean
  • Build passes: tsc --build clean
  • Naming conventions: kebab-case files, camelCase functions, PascalCase types, UPPER_SNAKE constants
  • Excellent test coverage: 32 tests across 8 suites covering setup, custom tag, context variables, render flow, decay priority, recursion (10-level deep), cycle detection, array refs, error handling, Unicode, and performance (100 children fan-out). All pass
  • CLI integration: ucas render now passes varStore to renderAsync() for template-aware rendering. 5 CLI integration tests (Suite 6) covering default params, custom decay, all params, YAML fallback, and error handling

⚠️ Minor Observations

  1. Duplicate RenderOptions type: Both liquid-render.ts and render.ts define RenderOptions. The one in render.ts has an extra varStore? field. Only render.ts's version is exported. Consider having liquid-render.ts import from render.ts or extract to a shared types file to avoid drift.

  2. _globalDecay unused parameter: In renderNode() (liquid-render.ts:170), _globalDecay is passed through but never used — the engine closure already captures globalDecay. The underscore prefix correctly signals intent but the parameter could be removed.

  3. engine variable in render tag: The custom render tag's render() method (line 143) references engine from the outer createLiquidEngine closure — this works but creates a tight coupling. Acceptable for now.

  4. Test file uses await import("liquidjs"): Tests 1.1–1.3 use dynamic imports for basic LiquidJS verification. Not a project rule violation (rule applies to source, not tests), but static imports would be more consistent.

  5. CLI test failures are pre-existing: 25 CLI test failures exist but are unrelated to this PR (they fail on runCliAlias which uses bun run — likely a path/environment issue).

  6. Missing test suites 4.2, 4.3, 7.3, 9.x: Test numbering has gaps (e.g., Suite 4 jumps from 4.1 to 4.4). Not a bug, but suggests some planned tests were deferred.

📊 Verdict

Solid merge. Clean code, thorough tests, follows all CLAUDE.md conventions. The duplicate RenderOptions type is the only thing worth addressing in a follow-up.


小橘 🍊(NEKO Team)

## 🔍 Post-Merge Review: PR #45 — LiquidJS Template Rendering Integration ### Summary PR #45 merged 3 commits adding LiquidJS template rendering to json-cas. Files changed: `liquid-render.ts`, `liquid-render.test.ts`, `render.ts`, `index.ts` (json-cas), `index.ts`, `cli.test.ts` (cli-json-cas), `package.json`, `bun.lock`. ### ✅ What's Good - **Clean architecture**: `liquid-render.ts` (293 lines) is well-structured with clear separation — engine creation, node rendering, template discovery, and fallback rendering - **Custom `{% render %}` tag** properly implements variable resolution with dot-path support and explicit decay syntax (`{% render payload.child, decay: 0.7 %}`) - **Decay priority chain** correctly implemented: template explicit > CLI/options > engine default (0.5). Verified by tests 5.1–5.3 - **Template discovery** via `@ucas/template/text/<type-hash>` variable convention works cleanly through `VariableStore` - **`renderAsync()`** in `render.ts` elegantly bridges sync YAML rendering with async template rendering, with proper fallback - **No dynamic imports** in source code — `liquidjs` is statically imported ✅ - **TypeScript strict mode**: no `any` usage, proper `import type` for type-only imports, `.js` extensions in import paths ✅ - **Biome passes**: `biome check .` clean ✅ - **Build passes**: `tsc --build` clean ✅ - **Naming conventions**: kebab-case files, camelCase functions, PascalCase types, UPPER_SNAKE constants ✅ - **Excellent test coverage**: 32 tests across 8 suites covering setup, custom tag, context variables, render flow, decay priority, recursion (10-level deep), cycle detection, array refs, error handling, Unicode, and performance (100 children fan-out). All pass ✅ - **CLI integration**: `ucas render` now passes `varStore` to `renderAsync()` for template-aware rendering. 5 CLI integration tests (Suite 6) covering default params, custom decay, all params, YAML fallback, and error handling ### ⚠️ Minor Observations 1. **Duplicate `RenderOptions` type**: Both `liquid-render.ts` and `render.ts` define `RenderOptions`. The one in `render.ts` has an extra `varStore?` field. Only `render.ts`'s version is exported. Consider having `liquid-render.ts` import from `render.ts` or extract to a shared types file to avoid drift. 2. **`_globalDecay` unused parameter**: In `renderNode()` (liquid-render.ts:170), `_globalDecay` is passed through but never used — the `engine` closure already captures `globalDecay`. The underscore prefix correctly signals intent but the parameter could be removed. 3. **`engine` variable in render tag**: The custom render tag's `render()` method (line 143) references `engine` from the outer `createLiquidEngine` closure — this works but creates a tight coupling. Acceptable for now. 4. **Test file uses `await import("liquidjs")`**: Tests 1.1–1.3 use dynamic imports for basic LiquidJS verification. Not a project rule violation (rule applies to source, not tests), but static imports would be more consistent. 5. **CLI test failures are pre-existing**: 25 CLI test failures exist but are unrelated to this PR (they fail on `runCliAlias` which uses `bun run` — likely a path/environment issue). 6. **Missing test suites 4.2, 4.3, 7.3, 9.x**: Test numbering has gaps (e.g., Suite 4 jumps from 4.1 to 4.4). Not a bug, but suggests some planned tests were deferred. ### 📊 Verdict **Solid merge.** Clean code, thorough tests, follows all CLAUDE.md conventions. The duplicate `RenderOptions` type is the only thing worth addressing in a follow-up. --- 小橘 🍊(NEKO Team)
This repo is archived. You cannot comment on issues.
No Label
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/json-cas#40