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
28 changes: 4 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,18 @@ Text diff

### 使用者影响

CLI 与 `@calcit/procs` 配对正式 **0.34.2**,升级后需重新安装完整精确依赖图、
生成 JS 并完整刷新,不能跨工具链热重载保留旧 Reel 实例。目标为正式 Reel
**0.9.0**、UI **0.14.1**、Respo **0.19.2**、JS-FFI **0.2.10** 与 Markdown
**0.7.1**。已从正式 tag 完成根 Caps strict/toolchain,6 个模块的 Snapshot 与本轮
实际验收候选逐字节相同,不使用候选链接、main/hash 或关闭 strict 代替正式图。
升级到 Calcit 和 `@calcit/procs` **0.35.1** 后,请重新安装依赖、编译并刷新。文本输入、Run 输出、原 Map 存档和页面 HUD 继续适用。

保留已有 `CursorKey = Tag | String | Number` union,`:states` 的 Bool 等其他 key
仍按原合同拒绝,false/0 状态 payload、原 Map 存档格式及匿名 Enum/Reel 操作入口
保持。不为开放状态伪造有限 union,也不扩张公开 diff API。
Reel 使用 `State<Op, Store>`。旧操作在入口解码,业务更新器接收具名操作。状态路径沿用 `CursorKey = Tag | String | Number`,已有 Map 或 Struct 存档仍在恢复时校验。恢复成功后才注册离页保存。

textarea 回调现在接收真实 RespoEvent,读取 `:value` 后仍检查 String,缺失/非法
输入在修改状态前报错;根组件构建和实际渲染同处 managed memo frame。两处原
8px 宽度保留。恢复失败保护、HUD、存档 key 和部署路径保持。官方 AST 比较只有
两个业务代码体与两个 namespace import 改变,原 schema、CursorKey、updater
与三项测试断言保持,不放宽门禁或新增 checker。

Reel 保留 `State<Enum,Store>`,公共 updater 接受原 Enum,UI 输入经 Enum 检查后
派发。存档仍输出 Map;原 Map/Struct 输入通过已有 Store 边界恢复。恢复成功后
才注册 beforeunload 保存,解析/解码失败不会覆盖原存档;不吞错、不清空或替换数据。
此流程没有新增定时保存。npm 安装等待一小时,无单包例外。

当前源码只有示例 UI 和 Store updater;历史简介中的 diff 算法仍为 WIP,本迁移
不补写或验证不存在的算法。本轮普通可见 Chrome 使用独立回环来源与合成文本,
实际输入中文/emoji、多行、点击 run 输出当前内容、离页保存及刷新恢复通过,未见
应用 pageerror。未重新验收坏存档保护,不把正常恢复或历史结果当作本次完整证明。
正式依赖为 Respo **0.19.4**、Reel **0.9.2**、Markdown **0.8.1**、UI **0.15.1**、JS-FFI **0.2.13**,传递 Router **0.12.1**。

### Workflow

Use `calcit.cirru` and `deps.cirru`; do not restore the retired `compact.cirru`
or `package.cirru`. Generated `js-out/` is not committed.

Use Node 24 and Yarn 4.18.0. Install Calcit 0.34.2 and Caps 0.1.1 separately
Use Node 24 and Yarn 4.18.0. Install Calcit 0.35.1 and Caps 0.1.1 separately
(the latter follows [the official Caps installation](https://github.com/calcit-lang/caps)); Corepack/Yarn does not install Caps. Strict dependency installation and the original type/test gates are retained.
Browser and production acceptance remain separate from successful compilation.

Expand Down
100 changes: 59 additions & 41 deletions calcit.cirru
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
:style $ .merge ui/expand ui/textarea $ {} (:height 320)
:on-input $ fn (e d!)
hint-fn $ Fn respo.schema/RespoEvent
Fn Enum $ -> Unit
Fn AnyEnum $ -> Unit
-> Unit
let
value $ :value e
if (string? value)
d! $ :: :content value
d! $ text-diff.schema/Op :content value
raise |Expected-string-input-value
space-x 8
div
Expand All @@ -39,14 +39,14 @@
:inner-text $ str |run
:on-click $ fn (e d!)
hint-fn $ Fn respo.schema/RespoEvent
Fn Enum $ -> Unit
Fn AnyEnum $ -> Unit
-> Unit
println $ :content store
if dev?
Option :some $ comp-typed-reel (>> states :reel) reel $ {}
Option :none
:examples $ []
:schema $ quote $ Fn (reel.typed/State Enum text-diff.schema/Store) (-> respo.schema/Component)
:schema $ quote $ Fn (reel.typed/State text-diff.schema/Op text-diff.schema/Store) (-> respo.schema/Component)
:ns $ %{} 'NsEntry (:doc |)
:code $ quote $ ns text-diff.comp.container
:require (respo-ui.core :as ui)
Expand Down Expand Up @@ -91,30 +91,30 @@
'text-diff.main $ %{} 'FileEntry
:defs $ {}
'*reel $ %{} 'CodeEntry (:doc |)
:code $ quote $ defref *reel (typed/new-reel schema/store)
:code $ quote $ defref *reel
typed/State :base schema/store :store schema/store :records ([]) :pointer (Option :none) :stopped? false :display? false :merged? false
:examples $ []
:schema $ quote $ Ref (reel.typed/State Enum text-diff.schema/Store)
:schema $ quote $ Ref (reel.typed/State text-diff.schema/Op text-diff.schema/Store)
'dispatch! $ %{} 'CodeEntry (:doc |)
:code $ quote $ defn dispatch! (op)
if (enum? op)
do
when config/dev? $ println |Dispatch: op
match (typed/decode-control op)
(:some control)
reset! *reel $ typed/apply-control updater @*reel control
(:none)
reset! *reel $ typed/record-op updater @*reel op (generate-id!)
:timestamp $ shared/date-now-snapshot
, &unit
raise "|Expected an operation enum"
:examples $ []
:schema $ quote $ Fn Dynamic (-> Unit) (:features :js-ffi)
when config/dev? $ println |Dispatch: op
match (typed/decode-control op)
(:some control)
reset! *reel $ typed/apply-control updater @*reel control
(:none)
match (schema/decode-op op)
(:some action)
reset! *reel $ typed/record-op updater @*reel action (generate-id!) (shared/now-ms)
(:none) &unit
, &unit
:examples $ []
:schema $ quote $ Fn AnyEnum (-> Unit) (:features :js-ffi)
'main! $ %{} 'CodeEntry (:doc |)
:code $ quote $ defn main! ()
println "|Running mode:" $ if config/dev? |dev |release
render-app!
add-watch! *reel :changes $ fn (r p)
hint-fn $ Fn (reel.typed/State Enum text-diff.schema/Store) (reel.typed/State Enum text-diff.schema/Store) (-> Unit)
hint-fn $ Fn (reel.typed/State text-diff.schema/Op text-diff.schema/Store) (reel.typed/State text-diff.schema/Op text-diff.schema/Store) (-> Unit)
render-app!
, &unit
listen-devtools! |a dispatch!
Expand Down Expand Up @@ -145,7 +145,7 @@
if (nil? build-errors)
do (remove-watch! *reel :changes) (clear-cache!)
add-watch! *reel :changes $ fn (reel prev)
hint-fn $ Fn (reel.typed/State Enum text-diff.schema/Store) (reel.typed/State Enum text-diff.schema/Store) (-> Unit)
hint-fn $ Fn (reel.typed/State text-diff.schema/Op text-diff.schema/Store) (reel.typed/State text-diff.schema/Op text-diff.schema/Store) (-> Unit)
render-app!
, &unit
reset! *reel $ typed/refresh updater @*reel schema/store
Expand All @@ -156,7 +156,9 @@
:schema $ quote $ Fn (-> Unit) (:features :js-ffi)
'render-app! $ %{} 'CodeEntry (:doc |)
:code $ quote $ defn render-app! ()
with-memo-frame $ fn () $ render! (mount-target) (comp-container @*reel) dispatch!
render-with! (mount-target)
fn () $ comp-container @*reel
, dispatch!
:examples $ []
:schema $ quote $ Fn (-> Unit) (:features :js-ffi)
'snippets $ %{} 'CodeEntry (:doc |)
Expand All @@ -166,7 +168,7 @@
:ns $ %{} 'NsEntry (:doc |)
:code $ quote $ ns text-diff.main
:require
respo.core :refer $ render! clear-cache! realize-ssr!
respo.core :refer $ render-with! clear-cache!
text-diff.comp.container :refer $ comp-container
text-diff.updater :refer $ updater
text-diff.schema :as schema
Expand All @@ -178,7 +180,6 @@
reel.typed :as typed
js-ffi.shared :as shared
reel.util :refer $ listen-devtools!
respo.memo :refer $ with-memo-frame
'text-diff.schema $ %{} 'FileEntry
:defs $ {}
'CursorKey $ %{} 'CodeEntry
Expand All @@ -187,16 +188,40 @@
:examples $ []
:schema $ quote UnionDef
'DispatchOp $ %{} 'CodeEntry
:doc "|Open Enum alias for Respo dispatch-op: application operations and Reel controls retain their existing tags and payloads. This representative value is not dispatched; the explicit Enum schema supplies the slot contract. dispatch! and updater keep their existing runtime checks."
:doc "|Respo dispatch slot accepts application operations and Reel controls."
:code $ quote $ def DispatchOp (:: :unhandled)
:examples $ []
:schema $ quote Enum
:schema $ quote AnyEnum
'Op $ %{} 'CodeEntry (:doc |)
:code $ quote $ defenum Op
:states (List text-diff.schema/CursorKey) Dynamic
:content String
:hydrate-storage text-diff.schema/Store
:examples $ []
:schema $ quote EnumDef
'Store $ %{} 'CodeEntry (:doc |)
:code $ quote $ defstruct Store
:states $ quote $ Map Tag Dynamic
:states $ Map Tag Dynamic
:content String
:examples $ []
:schema $ quote StructDef
'decode-op $ %{} 'CodeEntry (:doc |)
:code $ quote $ defn decode-op (op)
match op
(:states cursor data)
Option :some $ Op :states
decode-map-as cursor $ List text-diff.schema/CursorKey
, data
(:content content)
Option :some $ Op :content $ decode-map-as content String
(:hydrate-storage data)
Option :some $ Op :hydrate-storage $ decode-map-as
if (struct? data) (&struct:to-map data) data
, text-diff.schema/Store
_ $ do (eprintln "|Unknown op:" op) (Option :none)
:examples $ []
:schema $ quote $ Fn AnyEnum
-> $ Option text-diff.schema/Op
'store $ %{} 'CodeEntry (:doc |)
:code $ quote $ def store
Store :states ({}) :content |
Expand All @@ -209,21 +234,14 @@
%{} 'CodeEntry (:doc |)
:code $ quote $ defn updater (store op op-id op-time)
match op
(:states cursor s)
(:states cursor data)
assoc store :states $ decode-map-as
update-state-tree (:states store)
decode-map-as cursor $ quote $ List text-diff.schema/CursorKey
, s
quote $ Map Tag Dynamic
(:content c)
assoc store :content $ decode-map-as c 'String
(:hydrate-storage d)
decode-map-as
if (struct? d) (&struct:to-map d) d
, 'text-diff.schema/Store
_ $ do (eprintln "|Unknown op:" op) store
:examples $ []
:schema $ quote $ Fn text-diff.schema/Store Enum String Number (-> text-diff.schema/Store)
update-state-tree (:states store) cursor data
Map Tag Dynamic
(:content content) (assoc store :content content)
(:hydrate-storage stored) stored
:examples $ []
:schema $ quote $ Fn text-diff.schema/Store text-diff.schema/Op String Number (-> text-diff.schema/Store)
:ns $ %{} 'NsEntry (:doc |)
:code $ quote $ ns text-diff.updater
:require $ respo.cursor :refer $ update-state-tree
14 changes: 7 additions & 7 deletions deps.cirru
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

{} (:calcit-version |0.34.2)
:version |0.1.3
:dependencies $ {} (|Respo/reel.calcit |0.9.0)
|Respo/respo-markdown.calcit |0.7.1
|Respo/respo-ui.calcit |0.14.1
|Respo/respo.calcit |0.19.2
|calcit-lang/js-ffi |0.2.10
{} (:calcit-version |0.35.1)
:version |0.1.4
:dependencies $ {} (|Respo/reel.calcit |0.9.2)
|Respo/respo-markdown.calcit |0.8.1
|Respo/respo-ui.calcit |0.15.1
|Respo/respo.calcit |0.19.4
|calcit-lang/js-ffi |0.2.13
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "calcit-workflow",
"version": "0.1.3",
"version": "0.1.4",
"description": "ClojureScript workflow using Calcit Editor",
"main": "index.js",
"packageManager": "yarn@4.18.0",
Expand All @@ -20,7 +20,7 @@
"vite": "^8.3.1"
},
"dependencies": {
"@calcit/procs": "0.34.2",
"@calcit/procs": "0.35.1",
"cirru-color": "^0.2.4",
"copy-text-to-clipboard": "^3.2.2",
"dayjs": "^1.11.20",
Expand Down
4 changes: 2 additions & 2 deletions scripts/upgrade.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import assert from 'node:assert/strict';
import test from 'node:test';
import * as c from '../js-out/calcit.core.mjs';
import { updater } from '../js-out/text-diff.updater.mjs';
import { store } from '../js-out/text-diff.schema.mjs';
import { decode_op, store } from '../js-out/text-diff.schema.mjs';

const tags = c.init_tags(['content', 'states']);
const read = (value, key) => c.option_$o_unwrap(c.get(value, key));
const apply = (source, op) => updater(source, c.parse_cirru_edn(op), 'test-op', 0);
const apply = (source, op) => updater(source, c.option_$o_unwrap(decode_op(c.parse_cirru_edn(op))), 'test-op', 0);

test('content update preserves cursor state and leaves original store unchanged', () => {
const updated = apply(store, ':: :content |hello');
Expand Down
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.