Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 29 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,44 @@ Demo http://repo.respo-mvc.org/markup/ .

### Usages

本次升级保留 Content 输入、Run、Reel 调试工具和原有本地存档格式。
旧页面升级后请完整刷新一次,以加载配对的运行时和正式模块。
这仍是现有 Demo,不新增 Markdown 解析或编辑功能。

当前 CLI/procs 配对正式 **0.32.1**,依赖固定到已发布的 Respo `0.17.1`、
UI `0.9.0`、Reel `0.7.0-alpha.5`、JS-FFI `0.2.9`,传递 Router `0.9.0-alpha.4`。
类型标注经官方 formatter 迁移;Snapshot 与原 main 经同一 formatter 规范化后的结果相同,
运行代码、公开合同、三项原测试、存档校验和 HUD 不变,不新增强转或放宽门禁。
本轮 all-defs 210 项、完整 strict、原三项 Node 回归、immutable/toolchain、文档与构建通过;
实际首屏/刷新无 warn/error,本轮未复验编辑、存档浏览器恢复或 HMR。
Reel/Router 仍为已发布 alpha,请重新安装完整依赖并生成 JS,避免混用旧缓存。
Content/Run、快捷键及存档 key 保持不变,UI 升级可能有样式差异。

0.31 迁移显式绑定 Respo 的入口事件类型,并在发送状态事件前检查游标确为 List。
本地 Store 保留原对象;旧存档中的同名外部 Struct 先转为 Map,经字段校验后重建本地 Store。
名称仅用于选择解码路径,不代表名义身份或可信来源。保留原三项业务测试。
启动仍先恢复存档,再渲染和注册保存;解析或解码失败会停止启动并保留原值。
解码失败和 reload 的 HUD 提示保持原行为,坏存档恢复 UI 尚未实现。

Caps 0.1.1、Node.js 24、Yarn 4.18.0。项目版本仍为尚未发布的 0.0.5 候选。
Canonical source and dependencies are `calcit.cirru` and `deps.cirru`;
retired compact/package snapshots are not used. Edit source with the Calcit CLI.
本次候选 **0.0.5** 配对正式 Calcit / `@calcit/procs` **0.34.2**。
消费者需重新安装完整依赖图、生成 JS 并完整刷新页面。Content 输入、Run、Reel 调试工具、
存档 key 和格式保持;Demo 不新增 Markdown 解析功能。UI/Reel 跨 minor 升级可能有样式差异。
0.0.5 尚未发布,正式 tag 出现前不要将本分支当作已发布依赖。

依赖使用已发布的 Respo **0.19.2**、UI **0.14.1**、Reel **0.9.0**、JS-FFI **0.2.10**,
传递 Router **0.11.2**;不再使用 Reel / Router 的旧 alpha 图。
两个 DOM 回调使用真实 RespoEvent 和单 Enum dispatch,输入值由公开 `event-value` 检查为 String。
原 Reel 的 `read-field` 已删除;此处直接读取数据,保留 Map/Struct 字段读取及缺失值语义。
两个间隔分别保持 8 / 8px,开发态子节点显式使用 Option。
根渲染和原 SSR 回归均按 Respo 的公开 managed memo frame 合同包住构造与渲染。

应用 Op 与 Store 仍为原名义类型。开放 Enum 分发入口必须检查后转为 Op;它也承载 Reel 控制事件。
Store.states 是应用与 Reel 共用的真实异构状态树,继续保留 Map Dynamic Dynamic;不以含 Dynamic
的 union 或伪泛型隐藏该边界。固定 Site 已是具体 Struct,不为本次升级引入无实际需要的 union。

启动仍先恢复成功,再渲染并注册保存。已有本地 Store 保留身份;旧同名外部 Struct 转为 Map,
验证后重建本地 Store,名称不代表来源或授权。游标只接受缺失或实际 List。
解析异常会停止启动并保留原存档,但不会显示此处的 HUD 提示;
只有 `decode-store` 返回 :none 时才显示原 HUD 错误,然后停止启动。坏存档恢复 UI 尚未实现。

使用 Node 24、Yarn 4.18.0、Caps 0.1.1:

```sh
caps --strict --ci
yarn install --immutable
caps verify --toolchain
calcit calcit.cirru --check-only --all-defs
calcit calcit.cirru fix --workflow strict --verify
calcit calcit.cirru js
node --test scripts/typed-reel-render.test.mjs
yarn vite
```

CI retains strict dependency resolution, entry/type checks and the existing
typed Reel rendering tests, and checks all definitions with all-defs plus the full strict workflow.
重复的手写CLI版本断言和namespace清单已移除,保留Caps工具链配对门禁,
不添加校验脚本、concurrently、质量预算或兼容强转。
开放的 Reel/UI 状态保留真实 Dynamic 边界;操作载荷经过检查并构造成具名 Op,
存档验证后恢复为 Store,不再依赖类型强转。DOM 挂载使用 Respo 的公开接口。
恢复时仅接受缺失游标或真实 List 游标;旧 Struct 定义恢复到当前 Store,
已是当前 Store 的值保留原对象。既有测试文件包含由迁移前 0.27.0 格式化器生成的
固定合成存档,经过实际 `:hydrate-storage` / Reel / Content 渲染路径,未使用用户存档。
完整 strict workflow 同时检查渲染入口的 Enum 守卫与 reload 的实际 Unit 返回。
只维护 calcit.cirru / deps.cirru,不提交 compact.cirru、package.cirru 或 js-out。
编辑 Snapshot 使用官方 CLI 的受保护事务;原完整 strict 与 dynamic-method 门禁保留。
原三项回归及其中固定的 0.27.0 合成存档保持,SSR 仅增加公开 memo frame 入口,不改断言。
本地已验收合成中文/emoji 输入、Run、Reel 历史展示与刷新恢复;未声称所有 HMR 或坏存档 UI 已验收。

### Deployment

Expand Down
50 changes: 28 additions & 22 deletions calcit.cirru
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,53 @@
(:none) ([])
(:some value)
if (list? value) value $ raise "|Expected List cursor"
state $ or (reel-schema/read-field states :data)
state $ or
.unwrap-or (get states :data) nil
{} $ :content |
content $ .unwrap-or
get
if (struct? state) (&struct:to-map state) (decode-map-as state 'Map)
, :content
, nil
div
{} $ :class-name $ str-spaced css/global css/row
textarea $ {}
:value $ reel-schema/read-field state :content
:placeholder |Content
textarea $ {} (:value content) (:placeholder |Content)
:class-name $ str-spaced css/expand css/textarea
:style $ {} $ :height |320px
:on-input $ fn (e d!)
hint-fn $ Fn (Map Tag Dynamic)
Fn Dynamic & Dynamic $ -> Unit
hint-fn $ Fn respo.schema/RespoEvent
Fn Enum $ -> Unit
-> Unit
d! $ schema/Op :states cursor $ assoc state :content (reel-schema/read-field e :value)
=< 8 $ {}
d! $ schema/Op :states cursor $ assoc state :content (event-value e)
space-x 8
div
{} $ :class-name css/expand
<> "|This is some content with `code`"
=< |8px $ {}
space-x |8px
button $ {} (:class-name css/button) (:inner-text |Run)
:on-click $ fn (e d!)
hint-fn $ Fn (Map Tag Dynamic)
Fn Dynamic & Dynamic $ -> Unit
hint-fn $ Fn respo.schema/RespoEvent
Fn Enum $ -> Unit
-> Unit
println $ reel-schema/read-field state :content
when dev? $ comp-typed-reel (>> states :reel) reel $ {}
println content
if dev?
Option :some $ comp-typed-reel (>> states :reel) reel $ {}
Option :none
:examples $ []
:schema $ quote $ Fn (reel.typed/State app.schema/Op app.schema/Store) (-> respo.schema/Component)
:ns $ %{} 'NsEntry (:doc |)
:code $ quote $ ns app.comp.container
:require (respo-ui.css :as css)
respo.css :refer $ defstyle
respo.core :refer $ defcomp defeffect <> >> div button textarea span input
respo.comp.space :refer $ =<
respo.core :refer $ defcomp defeffect <> >> div button textarea span input event-value
respo.comp.space :refer $ space-x
reel.comp.reel :refer $ comp-typed-reel
reel.schema :as reel-schema
app.config :refer $ dev?
app.schema :as schema
'app.config $ %{} 'FileEntry
:defs $ {}
'Site $ %{} 'CodeEntry (:doc |)
:code $ quote $ defstruct Site (:storage-key 'String)
:code $ quote $ defstruct Site (:storage-key String)
:examples $ []
:schema $ quote StructDef
'dev? $ %{} 'CodeEntry (:doc |)
Expand Down Expand Up @@ -150,7 +155,7 @@
:schema $ quote $ Fn (-> Unit) (:features :js-ffi)
'render-app! $ %{} 'CodeEntry (:doc |)
:code $ quote $ defn render-app! ()
render! mount-target (comp-container @*reel)
with-memo-frame $ fn () $ render! mount-target (comp-container @*reel)
fn (op)
hint-fn $ Fn Dynamic $ -> Unit
if (enum? op) (dispatch! op) (raise "|Expected Markup operation Enum")
Expand All @@ -171,6 +176,7 @@
reel.typed :as typed
js-ffi.browser :refer $ add-event-listener! set-before-unload! set-interval! storage-get storage-set! visibility-state
respo.ffi.browser :refer $ query-selector
respo.memo :refer $ with-memo-frame
'app.schema $ %{} 'FileEntry
:defs $ {}
'DispatchOp $ %{} 'CodeEntry (:doc "|Respo 入口事件合同,容纳应用和 Reel 控制事件;代表值不发送。")
Expand All @@ -181,8 +187,8 @@
:code $ quote $ defenum Op
:states
quote $ List Dynamic
, 'Dynamic
:hydrate-storage 'app.schema/Store
, Dynamic
:hydrate-storage app.schema/Store
:examples $ []
:schema $ quote EnumDef
'Store $ %{} 'CodeEntry (:doc |)
Expand All @@ -196,7 +202,7 @@
match op
(:states cursor data)
Op :states
decode-map-as cursor $ :: 'List 'Dynamic
decode-map-as cursor $ quote $ List Dynamic
, data
(:hydrate-storage data)
match (decode-store data)
Expand Down Expand Up @@ -242,7 +248,7 @@
(:states cursor s)
assoc store :states $ decode-map-as
update-state-tree (:states store) cursor s
:: 'Map 'Dynamic 'Dynamic
quote $ Map Dynamic Dynamic
(:hydrate-storage data) data
:examples $ []
:schema $ quote $ Fn app.schema/Store app.schema/Op String Number (-> app.schema/Store)
Expand Down
10 changes: 5 additions & 5 deletions deps.cirru
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

{} (:calcit-version |0.32.1)
{} (:calcit-version |0.34.2)
:version |0.0.5
:dependencies $ {} (|Respo/reel.calcit |0.7.0-alpha.5)
|Respo/respo-ui.calcit |0.9.0
|Respo/respo.calcit |0.17.1
|calcit-lang/js-ffi |0.2.9
:dependencies $ {} (|Respo/reel.calcit |0.9.0)
|Respo/respo-ui.calcit |0.14.1
|Respo/respo.calcit |0.19.2
|calcit-lang/js-ffi |0.2.10
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"packageManager": "yarn@4.18.0",
"dependencies": {
"@calcit/procs": "0.32.1"
"@calcit/procs": "0.34.2"
},
"devDependencies": {
"bottom-tip": "^0.1.5",
Expand Down
8 changes: 5 additions & 3 deletions scripts/typed-reel-render.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const { store, decode_op, decode_store } = await import('../js-out/app.schema.mj
const { updater } = await import('../js-out/app.updater.mjs');
const { new_reel, toggle_display, record_op, refresh } = await import('../js-out/reel.typed.mjs');
const { make_string } = await import('../js-out/respo.render.html.mjs');
const { with_memo_frame } = await import('../js-out/respo.memo.mjs');
const renderHtml = (reel) => with_memo_frame(() => make_string(comp_container(reel)));
const clt = await import('../js-out/calcit.core.mjs');

// Fixed synthetic archive produced by the clean 0.27.0 tag's native formatter,
Expand All @@ -20,7 +22,7 @@ const PRE_031_ARCHIVE = `

test('renders the typed Reel devtools with an empty history', () => {
const reel = toggle_display(new_reel(store));
const html = make_string(comp_container(reel));
const html = renderHtml(reel);

assert.match(html, /placeholder="Content"/);
assert.match(html, /Merge/);
Expand All @@ -33,7 +35,7 @@ test('content edits survive Reel replay and the existing saved-state format', ()
const reel = record_op(updater, new_reel(store), decode_op(wire), 'edit', 1);
const current = field(reel, 'store');
assert.equal(field(field(field(current, 'states'), 'data'), 'content'), '中文🐈');
assert.match(make_string(comp_container(reel)), /中文🐈/);
assert.match(renderHtml(reel), /中文🐈/);
const restored = clt.option_$o_unwrap(decode_store(clt.parse_cirru_edn(clt.format_cirru_edn(current))));
assert.equal(clt.format_cirru_edn(restored), clt.format_cirru_edn(current));
assert.equal(clt.option_$o_unwrap(decode_store(current)), current);
Expand All @@ -53,5 +55,5 @@ test('hydrates the fixed pre-upgrade archive through the typed Reel update path'
assert.equal(clt._$n__$e_(restored, expected), true);
assert.equal(field(field(field(restored, 'states'), 'data'), 'content'), '旧版合成存档🐈');
assert.equal(clt.format_cirru_edn(field(field(restored, 'states'), 'cursor')), clt.format_cirru_edn(clt.parse_cirru_edn('[]')));
assert.match(make_string(comp_container(reel)), /旧版合成存档🐈/);
assert.match(renderHtml(reel), /旧版合成存档🐈/);
});
10 changes: 5 additions & 5 deletions yarn.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.