@cmodjs/core 0.1.10 → 0.1.11

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/docs/testing.md CHANGED
@@ -145,6 +145,7 @@ Waits until the work a hook started without awaiting it has run, such as a `void
145
145
  ### lines
146
146
 
147
147
  - `lines(paneId)` draws an open pane and returns its rows of text. It rejects a pane that is not open: open it first with `tested.type('/<command>')` or `pane.open()` in the mod. The render gets the props `title`, `isFocused`, true once an `open` or `toggle` with `{ focus: true }` opened it, `bodyColumns`, `placement: 'dock'`, `scroll: { offset: 0, bodyRows: 24 }`, and `view: {}`, the main conversation's view.
148
+ - A `Button` draws as Claude Code draws it: `[ Save ]`, or `1: Save` when it is `plain` with a `hotkey`, or `Save` when it is `plain` alone. Borders and colors are not drawn.
148
149
  - `lines(slot, props, requestId?)` draws a slot render with `props` and returns its rows. `Default` draws a plain listing of the props it gets, so a test sees what the render changed. Draw `slots.AssistantMessage` with a reply's `text` to test a markdown slot render. Draws that pass one `requestId` grow one streamed reply.
149
150
 
150
151
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmodjs/core",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Build Claude Code mods: hooks, panes, permissions, checks, and an install that just works.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -53,7 +53,7 @@ export function textOf(node: RenderNode): string {
53
53
  const { type, props, children = [] } = insideOf(node)
54
54
  const inner = children.map(textOf).join('')
55
55
  if (type === 'Box') return rowsOf(node, Number.POSITIVE_INFINITY).join('\n')
56
- if (type === 'Button') return String(props['label'] ?? inner)
56
+ if (type === 'Button') return buttonText(String(props['label'] ?? inner), props)
57
57
  if (type === 'Link') return inner === '' ? String(props['label'] ?? props['href']) : inner
58
58
  if (type === 'Code') return String(props['source'])
59
59
  if (type === 'Markdown') return String(props['text'])
@@ -67,6 +67,11 @@ export function textOf(node: RenderNode): string {
67
67
  return inner
68
68
  }
69
69
 
70
+ function buttonText(label: string, props: Drawn['props']): string {
71
+ if (props['plain'] !== true) return `[ ${label} ]`
72
+ return props['hotkey'] === undefined ? label : `${String(props['hotkey'])}: ${label}`
73
+ }
74
+
70
75
  function insideOf(node: RenderElement): Drawn {
71
76
  const drawn = boxInsides.get(node) ?? (node as unknown as Partial<Drawn>)
72
77
  return { type: String(drawn.type), props: drawn.props ?? {}, ...(drawn.children === undefined ? {} : { children: drawn.children }) }
@@ -52,7 +52,7 @@ export function textOf(node) {
52
52
  if (type === 'Box')
53
53
  return rowsOf(node, Number.POSITIVE_INFINITY).join('\n');
54
54
  if (type === 'Button')
55
- return String(props['label'] ?? inner);
55
+ return buttonText(String(props['label'] ?? inner), props);
56
56
  if (type === 'Link')
57
57
  return inner === '' ? String(props['label'] ?? props['href']) : inner;
58
58
  if (type === 'Code')
@@ -70,6 +70,11 @@ export function textOf(node) {
70
70
  }
71
71
  return inner;
72
72
  }
73
+ function buttonText(label, props) {
74
+ if (props['plain'] !== true)
75
+ return `[ ${label} ]`;
76
+ return props['hotkey'] === undefined ? label : `${String(props['hotkey'])}: ${label}`;
77
+ }
73
78
  function insideOf(node) {
74
79
  const drawn = boxInsides.get(node) ?? node;
75
80
  return { type: String(drawn.type), props: drawn.props ?? {}, ...(drawn.children === undefined ? {} : { children: drawn.children }) };