@crouton-kit/crouter 0.3.17 → 0.3.19
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/dist/build-root.js +6 -0
- package/dist/builtin-memory/crouter-development/marketplaces.md +164 -0
- package/dist/builtin-memory/crouter-development/personas/base-prompt.md +58 -0
- package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +60 -0
- package/dist/builtin-memory/crouter-development/personas.md +117 -0
- package/dist/builtin-memory/crouter-development/plugins.md +163 -0
- package/dist/builtin-memory/design.md +60 -0
- package/dist/builtin-memory/development.md +116 -0
- package/dist/builtin-memory/planning.md +66 -0
- package/dist/builtin-memory/spec.md +99 -0
- package/dist/builtin-personas/design/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/design/orchestrator.md +1 -1
- package/dist/builtin-personas/developer/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/developer/orchestrator.md +1 -1
- package/dist/builtin-personas/explore/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/general/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/lifecycle/resident.md +1 -1
- package/dist/builtin-personas/lifecycle/terminal.md +5 -2
- package/dist/builtin-personas/orchestration-kernel.md +15 -24
- package/dist/builtin-personas/plan/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/plan/orchestrator.md +1 -1
- package/dist/builtin-personas/plan/reviewers/architecture-fit/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/code-smells/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/pattern-consistency/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/requirements-coverage/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/security/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/review/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/runtime-base.md +6 -3
- package/dist/builtin-personas/spec/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/spec/orchestrator.md +1 -1
- package/dist/builtin-personas/waiting.md +8 -0
- package/dist/builtin-skills/skills/crouter-development/personas/SKILL.md +24 -14
- package/dist/builtin-skills/skills/crouter-development/personas/base-prompt/SKILL.md +4 -4
- package/dist/builtin-skills/skills/crouter-development/personas/orchestrator-prompt/SKILL.md +1 -1
- package/dist/builtin-skills/skills/crouter-development/plugins/SKILL.md +2 -2
- package/dist/builtin-views/_lib/states.mjs +161 -0
- package/dist/builtin-views/canvas/client.mjs +303 -0
- package/dist/builtin-views/canvas/view.mjs +576 -0
- package/dist/builtin-views/git-pr/client.mjs +440 -0
- package/dist/builtin-views/git-pr/view.mjs +675 -0
- package/dist/builtin-views/inbox/_lib/render.mjs +177 -0
- package/dist/builtin-views/inbox/sources/gmail.mjs +965 -0
- package/dist/builtin-views/inbox/sources/linkedin.mjs +427 -0
- package/dist/builtin-views/inbox/view.mjs +889 -0
- package/dist/builtin-views/linkedin/client.mjs +610 -0
- package/dist/builtin-views/linkedin/view.mjs +1171 -0
- package/dist/clients/attach/attach-cmd.d.ts +2 -0
- package/dist/clients/attach/attach-cmd.js +354 -0
- package/dist/clients/attach/chat-view.d.ts +77 -0
- package/dist/clients/attach/chat-view.js +450 -0
- package/dist/clients/attach/clipboard-image.d.ts +16 -0
- package/dist/clients/attach/clipboard-image.js +113 -0
- package/dist/clients/attach/config-load.d.ts +31 -0
- package/dist/clients/attach/config-load.js +113 -0
- package/dist/clients/attach/extension-dialogs.d.ts +29 -0
- package/dist/clients/attach/extension-dialogs.js +101 -0
- package/dist/clients/attach/input-controller.d.ts +54 -0
- package/dist/clients/attach/input-controller.js +204 -0
- package/dist/clients/attach/slash-commands.d.ts +36 -0
- package/dist/clients/attach/slash-commands.js +200 -0
- package/dist/clients/attach/view-socket.d.ts +48 -0
- package/dist/clients/attach/view-socket.js +126 -0
- package/dist/commands/attention.js +3 -3
- package/dist/commands/canvas-prune.js +1 -1
- package/dist/commands/daemon.js +4 -3
- package/dist/commands/human/prompts.js +4 -10
- package/dist/commands/human/queue.js +43 -8
- package/dist/commands/human/shared.d.ts +28 -1
- package/dist/commands/human/shared.js +48 -10
- package/dist/commands/memory/find.d.ts +1 -0
- package/dist/commands/memory/find.js +180 -0
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +140 -0
- package/dist/commands/memory/list.d.ts +1 -0
- package/dist/commands/memory/list.js +79 -0
- package/dist/commands/memory/read.js +103 -0
- package/dist/commands/memory/shared.d.ts +30 -0
- package/dist/commands/memory/shared.js +122 -0
- package/dist/commands/memory/write.d.ts +1 -0
- package/dist/commands/memory/write.js +85 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +27 -0
- package/dist/commands/node.d.ts +3 -2
- package/dist/commands/node.js +660 -65
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/push.js +6 -6
- package/dist/commands/revive.js +1 -1
- package/dist/commands/skill/author.js +1 -1
- package/dist/commands/skill/shared.d.ts +1 -8
- package/dist/commands/skill/shared.js +2 -55
- package/dist/commands/skill.js +9 -14
- package/dist/commands/sys/doctor.js +1 -1
- package/dist/commands/sys/update.js +1 -1
- package/dist/commands/view-cycle.d.ts +2 -0
- package/dist/commands/view-cycle.js +125 -0
- package/dist/commands/view-list.d.ts +2 -0
- package/dist/commands/view-list.js +66 -0
- package/dist/commands/view-new.d.ts +2 -0
- package/dist/commands/view-new.js +70 -0
- package/dist/commands/view-pick.d.ts +2 -0
- package/dist/commands/view-pick.js +119 -0
- package/dist/commands/view-run.d.ts +2 -0
- package/dist/commands/view-run.js +191 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +29 -0
- package/dist/core/__tests__/broker-lifecycle.test.d.ts +1 -0
- package/dist/core/__tests__/broker-lifecycle.test.js +677 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.d.ts +1 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.js +166 -0
- package/dist/core/__tests__/cascade-close.test.js +12 -2
- package/dist/core/__tests__/child-death-wake.test.d.ts +1 -0
- package/dist/core/__tests__/child-death-wake.test.js +245 -0
- package/dist/core/__tests__/context-intro.test.js +76 -62
- package/dist/core/__tests__/daemon-boot.test.js +14 -5
- package/dist/core/__tests__/daemon-liveness.test.js +34 -9
- package/dist/core/__tests__/detach-focus.test.d.ts +1 -0
- package/dist/core/__tests__/detach-focus.test.js +206 -0
- package/dist/core/__tests__/draw-style.test.d.ts +1 -0
- package/dist/core/__tests__/draw-style.test.js +258 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +2 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +18 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +138 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +614 -0
- package/dist/core/__tests__/fixtures/fake-pi-host.js +1 -0
- package/dist/core/__tests__/flagship-lifecycle.test.js +7 -1
- package/dist/core/__tests__/frame-decoder-perf.test.d.ts +1 -0
- package/dist/core/__tests__/frame-decoder-perf.test.js +198 -0
- package/dist/core/__tests__/helpers/harness.d.ts +9 -0
- package/dist/core/__tests__/helpers/harness.js +111 -1
- package/dist/core/__tests__/home-session.test.js +41 -8
- package/dist/core/__tests__/human-new-window-regression.test.d.ts +1 -0
- package/dist/core/__tests__/human-new-window-regression.test.js +101 -0
- package/dist/core/__tests__/human-surface-target.test.d.ts +1 -0
- package/dist/core/__tests__/human-surface-target.test.js +98 -0
- package/dist/core/__tests__/kickoff.test.js +37 -3
- package/dist/core/__tests__/live-mutation.test.js +50 -33
- package/dist/core/__tests__/memory.test.js +23 -115
- package/dist/core/__tests__/persona-subkind.test.js +18 -15
- package/dist/core/__tests__/placement-focus.test.js +5 -0
- package/dist/core/__tests__/placement-teardown.test.js +54 -11
- package/dist/core/__tests__/relaunch.test.js +4 -3
- package/dist/core/__tests__/review-render-pane-regression.test.d.ts +1 -0
- package/dist/core/__tests__/review-render-pane-regression.test.js +133 -0
- package/dist/core/__tests__/spawn-root.test.js +10 -0
- package/dist/core/__tests__/spike-harness.test.js +1 -0
- package/dist/core/__tests__/wake-bearings.test.d.ts +1 -0
- package/dist/core/__tests__/wake-bearings.test.js +156 -0
- package/dist/core/__tests__/wake-origin.test.d.ts +1 -0
- package/dist/core/__tests__/wake-origin.test.js +110 -0
- package/dist/core/bootstrap.js +1 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.js +24 -2
- package/dist/core/canvas/browse/model.d.ts +38 -2
- package/dist/core/canvas/browse/model.js +134 -10
- package/dist/core/canvas/browse/render.d.ts +6 -12
- package/dist/core/canvas/browse/render.js +72 -104
- package/dist/core/canvas/canvas.js +15 -22
- package/dist/core/canvas/db.js +46 -0
- package/dist/core/canvas/index.d.ts +1 -0
- package/dist/core/canvas/index.js +1 -0
- package/dist/core/canvas/paths.d.ts +4 -1
- package/dist/core/canvas/paths.js +10 -4
- package/dist/core/canvas/pid.d.ts +4 -0
- package/dist/core/canvas/pid.js +23 -0
- package/dist/core/canvas/render.d.ts +11 -2
- package/dist/core/canvas/render.js +69 -0
- package/dist/core/canvas/types.d.ts +85 -3
- package/dist/core/canvas/types.js +2 -2
- package/dist/core/canvas/wakeups.d.ts +76 -0
- package/dist/core/canvas/wakeups.js +185 -0
- package/dist/core/config.js +4 -1
- package/dist/core/frontmatter.js +37 -124
- package/dist/core/help.d.ts +6 -0
- package/dist/core/help.js +7 -0
- package/dist/core/memory-resolver.d.ts +49 -0
- package/dist/core/memory-resolver.js +141 -0
- package/dist/core/personas/index.d.ts +4 -3
- package/dist/core/personas/index.js +3 -2
- package/dist/core/personas/loader.d.ts +41 -16
- package/dist/core/personas/loader.js +133 -29
- package/dist/core/personas/resolve.d.ts +4 -4
- package/dist/core/personas/resolve.js +28 -16
- package/dist/core/predicate.d.ts +63 -0
- package/dist/core/predicate.js +189 -0
- package/dist/core/resolver.js +26 -5
- package/dist/core/runtime/bearings.d.ts +53 -12
- package/dist/core/runtime/bearings.js +132 -59
- package/dist/core/runtime/broker-cli.d.ts +1 -0
- package/dist/core/runtime/broker-cli.js +46 -0
- package/dist/core/runtime/broker-protocol.d.ts +332 -0
- package/dist/core/runtime/broker-protocol.js +153 -0
- package/dist/core/runtime/broker-sdk.d.ts +48 -0
- package/dist/core/runtime/broker-sdk.js +72 -0
- package/dist/core/runtime/broker.d.ts +55 -0
- package/dist/core/runtime/broker.js +1128 -0
- package/dist/core/runtime/close.js +35 -6
- package/dist/core/runtime/host.d.ts +53 -0
- package/dist/core/runtime/host.js +186 -0
- package/dist/core/runtime/kickoff.d.ts +2 -1
- package/dist/core/runtime/kickoff.js +91 -5
- package/dist/core/runtime/launch.d.ts +45 -2
- package/dist/core/runtime/launch.js +65 -2
- package/dist/core/runtime/lifecycle.js +23 -6
- package/dist/core/runtime/memory.d.ts +2 -42
- package/dist/core/runtime/memory.js +11 -162
- package/dist/core/runtime/nodes.d.ts +33 -0
- package/dist/core/runtime/nodes.js +59 -1
- package/dist/core/runtime/persona.js +21 -11
- package/dist/core/runtime/pi-vendored.d.ts +18 -0
- package/dist/core/runtime/pi-vendored.js +49 -0
- package/dist/core/runtime/placement.d.ts +42 -14
- package/dist/core/runtime/placement.js +228 -38
- package/dist/core/runtime/promote.d.ts +0 -6
- package/dist/core/runtime/promote.js +1 -12
- package/dist/core/runtime/{demote.d.ts → recycle.d.ts} +5 -5
- package/dist/core/runtime/{demote.js → recycle.js} +27 -11
- package/dist/core/runtime/reset.js +8 -6
- package/dist/core/runtime/revive.d.ts +2 -0
- package/dist/core/runtime/revive.js +34 -34
- package/dist/core/runtime/spawn.d.ts +19 -0
- package/dist/core/runtime/spawn.js +75 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +6 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +28 -0
- package/dist/core/runtime/tmux.js +80 -6
- package/dist/core/scope.d.ts +11 -0
- package/dist/core/scope.js +39 -0
- package/dist/core/spawn.d.ts +25 -1
- package/dist/core/spawn.js +72 -7
- package/dist/core/substrate/gate.d.ts +13 -0
- package/dist/core/substrate/gate.js +21 -0
- package/dist/core/substrate/index.d.ts +7 -0
- package/dist/core/substrate/index.js +18 -0
- package/dist/core/substrate/on-read.d.ts +14 -0
- package/dist/core/substrate/on-read.js +292 -0
- package/dist/core/substrate/render.d.ts +25 -0
- package/dist/core/substrate/render.js +256 -0
- package/dist/core/substrate/schema.d.ts +76 -0
- package/dist/core/substrate/schema.js +124 -0
- package/dist/core/substrate/session-cache.d.ts +30 -0
- package/dist/core/substrate/session-cache.js +77 -0
- package/dist/core/substrate/subject.d.ts +41 -0
- package/dist/core/substrate/subject.js +54 -0
- package/dist/core/tui/contract.d.ts +83 -0
- package/dist/core/tui/contract.js +8 -0
- package/dist/core/tui/draw.d.ts +96 -0
- package/dist/core/tui/draw.js +339 -0
- package/dist/core/tui/host.d.ts +29 -0
- package/dist/core/tui/host.js +379 -0
- package/dist/core/tui/loader.d.ts +16 -0
- package/dist/core/tui/loader.js +94 -0
- package/dist/core/{canvas/browse → tui}/terminal.js +7 -6
- package/dist/core/wake.d.ts +86 -0
- package/dist/core/wake.js +308 -0
- package/dist/daemon/crtrd.d.ts +29 -4
- package/dist/daemon/crtrd.js +662 -46
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +171 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +19 -12
- package/dist/pi-extensions/canvas-commands.d.ts +3 -0
- package/dist/pi-extensions/canvas-commands.js +10 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +17 -0
- package/dist/pi-extensions/canvas-context-intro.js +55 -15
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +44 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +112 -0
- package/dist/pi-extensions/canvas-nav.d.ts +3 -0
- package/dist/pi-extensions/canvas-nav.js +145 -34
- package/dist/pi-extensions/canvas-stophook.js +17 -8
- package/dist/pi-extensions/canvas-view.d.ts +21 -0
- package/dist/pi-extensions/canvas-view.js +75 -0
- package/dist/prompts/skill.js +19 -26
- package/dist/prompts/view.d.ts +7 -0
- package/dist/prompts/view.js +101 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/package.json +9 -4
- package/dist/commands/skill/find.d.ts +0 -4
- package/dist/commands/skill/find.js +0 -257
- package/dist/commands/skill/read.js +0 -91
- /package/dist/commands/{skill → memory}/read.d.ts +0 -0
- /package/dist/core/{canvas/browse → tui}/terminal.d.ts +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* Shared render helpers for the combined `inbox` view.
|
|
4
|
+
*
|
|
5
|
+
* These are COPIED VERBATIM-IN-BEHAVIOR from `../../linkedin/view.mjs` so the
|
|
6
|
+
* standalone `linkedin` view stays untouched (the contract forbids refactoring
|
|
7
|
+
* it). Self-contained ESM, Node-builtins only, imports NOTHING from crtr — the
|
|
8
|
+
* `inbox` view + its source adapters import these RELATIVELY.
|
|
9
|
+
*
|
|
10
|
+
* Discipline (design §2): all hue is NUMERIC SGR codes; color never carries
|
|
11
|
+
* meaning alone — every colored element pairs hue with a glyph or weight so it
|
|
12
|
+
* survives NO_COLOR / dumb terminals.
|
|
13
|
+
*
|
|
14
|
+
* @module inbox/_lib/render
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** @typedef {import('../../../core/tui/draw.js').Draw} Draw */
|
|
18
|
+
/** @typedef {import('../../../core/tui/draw.js').Rect} Rect */
|
|
19
|
+
/** @typedef {import('../../../core/tui/draw.js').Span} Span */
|
|
20
|
+
|
|
21
|
+
/** Month abbreviations for the timestamp / day-divider ladder. */
|
|
22
|
+
export const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
23
|
+
|
|
24
|
+
/** @param {string} s @param {number} n @returns {string} */
|
|
25
|
+
export function truncate(s, n) {
|
|
26
|
+
const str = String(s == null ? '' : s);
|
|
27
|
+
return str.length > n ? str.slice(0, Math.max(0, n - 1)) + '…' : str;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** @param {string} s @param {number} n @returns {string} */
|
|
31
|
+
export function padEnd(s, n) {
|
|
32
|
+
const str = String(s == null ? '' : s);
|
|
33
|
+
return str.length >= n ? str.slice(0, n) : str + ' '.repeat(n - str.length);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @param {string|string[]|null|undefined} v @returns {string[]} */
|
|
37
|
+
export function toLinesArr(v) {
|
|
38
|
+
if (v == null) return [];
|
|
39
|
+
if (Array.isArray(v)) return v.map((s) => String(s == null ? '' : s));
|
|
40
|
+
return [String(v)];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Visible (column) width of a span group. @param {Span[]} spans @returns {number} */
|
|
44
|
+
export function spanWidth(spans) {
|
|
45
|
+
let n = 0;
|
|
46
|
+
for (const s of spans) n += Array.from(s.text).length;
|
|
47
|
+
return n;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Place a vertically + horizontally centered stack of span-lines in `rect`.
|
|
52
|
+
* @param {Draw} draw @param {Rect} rect @param {Span[][]} lines
|
|
53
|
+
*/
|
|
54
|
+
export function centeredStack(draw, rect, lines) {
|
|
55
|
+
if (!rect || rect.width <= 0 || rect.height <= 0 || lines.length === 0) return;
|
|
56
|
+
const start = rect.row + Math.max(0, Math.floor((rect.height - lines.length) / 2));
|
|
57
|
+
lines.forEach((spans, i) => {
|
|
58
|
+
const row = start + i;
|
|
59
|
+
if (row < rect.row || row >= rect.row + rect.height) return;
|
|
60
|
+
const w = spanWidth(spans);
|
|
61
|
+
const col = rect.col + Math.max(0, Math.floor((rect.width - w) / 2));
|
|
62
|
+
draw.spans(row, col, spans, rect.col + rect.width - col);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Split the content rect into the 1:2 two-pane layout, drawing the `vline` rule
|
|
68
|
+
* between the panes. Returns the inner list/thread rects.
|
|
69
|
+
* @param {Draw} draw @param {Rect} content
|
|
70
|
+
* @returns {{left: Rect, right: Rect}}
|
|
71
|
+
*/
|
|
72
|
+
export function splitPanes(draw, content) {
|
|
73
|
+
const cols = draw.columns(content, [1, 2]);
|
|
74
|
+
const l = cols[0];
|
|
75
|
+
const r = cols[1];
|
|
76
|
+
const vcol = r.col; // the boundary column carries the rule
|
|
77
|
+
draw.vline(vcol, content.row, content.row + content.height);
|
|
78
|
+
const left = { row: content.row, col: l.col, width: Math.max(0, vcol - l.col - 1), height: content.height };
|
|
79
|
+
const right = { row: content.row, col: vcol + 2, width: Math.max(0, r.col + r.width - (vcol + 2)), height: content.height };
|
|
80
|
+
return { left, right };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Relative-timestamp ladder, max ~5 cols: now / {m}m / {h}h / {d}d /
|
|
85
|
+
* `Mon D` (this year) / `Mon ʼYY` (prior year).
|
|
86
|
+
* @param {number} ts epoch ms (0 ⇒ '') @param {number} [now] @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
export function relTimestamp(ts, now = Date.now()) {
|
|
89
|
+
if (!ts) return '';
|
|
90
|
+
const s = Math.floor((now - ts) / 1000);
|
|
91
|
+
if (s < 60) return 'now';
|
|
92
|
+
const m = Math.floor(s / 60);
|
|
93
|
+
if (m < 60) return `${m}m`;
|
|
94
|
+
const h = Math.floor(m / 60);
|
|
95
|
+
if (h < 24) return `${h}h`;
|
|
96
|
+
const d = Math.floor(h / 24);
|
|
97
|
+
if (d < 7) return `${d}d`;
|
|
98
|
+
const dt = new Date(ts);
|
|
99
|
+
const mon = MONTHS[dt.getMonth()] || '';
|
|
100
|
+
const cur = new Date(now);
|
|
101
|
+
if (dt.getFullYear() === cur.getFullYear()) return `${mon} ${dt.getDate()}`;
|
|
102
|
+
return `${mon} ʼ${String(dt.getFullYear()).slice(-2)}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Calendar-day key for day-divider grouping. @param {number} ts @returns {string} */
|
|
106
|
+
export function dayKey(ts) {
|
|
107
|
+
if (!ts) return '';
|
|
108
|
+
const d = new Date(ts);
|
|
109
|
+
return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Human day label for the divider: Today / Yesterday / Mon D / Mon D, YYYY. */
|
|
113
|
+
export function dayLabel(ts, now = Date.now()) {
|
|
114
|
+
const d = new Date(ts);
|
|
115
|
+
const n = new Date(now);
|
|
116
|
+
const same = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
117
|
+
if (same(d, n)) return 'Today';
|
|
118
|
+
if (same(d, new Date(now - 86400000))) return 'Yesterday';
|
|
119
|
+
const mon = MONTHS[d.getMonth()] || '';
|
|
120
|
+
if (d.getFullYear() === n.getFullYear()) return `${mon} ${d.getDate()}`;
|
|
121
|
+
return `${mon} ${d.getDate()}, ${d.getFullYear()}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Word-wrap text to a width (also hard-splits over-long words). Preserves
|
|
126
|
+
* explicit newlines as paragraph breaks.
|
|
127
|
+
* @param {string} text @param {number} width @returns {string[]}
|
|
128
|
+
*/
|
|
129
|
+
export function wrapText(text, width) {
|
|
130
|
+
const w = Math.max(1, width | 0);
|
|
131
|
+
/** @type {string[]} */
|
|
132
|
+
const out = [];
|
|
133
|
+
const paragraphs = String(text == null ? '' : text).split('\n');
|
|
134
|
+
for (const para of paragraphs) {
|
|
135
|
+
if (para.trim() === '') {
|
|
136
|
+
out.push('');
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
let line = '';
|
|
140
|
+
for (const word of para.split(/\s+/).filter(Boolean)) {
|
|
141
|
+
let wd = word;
|
|
142
|
+
while (wd.length > w) {
|
|
143
|
+
if (line) {
|
|
144
|
+
out.push(line);
|
|
145
|
+
line = '';
|
|
146
|
+
}
|
|
147
|
+
out.push(wd.slice(0, w));
|
|
148
|
+
wd = wd.slice(w);
|
|
149
|
+
}
|
|
150
|
+
if (line === '') line = wd;
|
|
151
|
+
else if (line.length + 1 + wd.length <= w) line += ' ' + wd;
|
|
152
|
+
else {
|
|
153
|
+
out.push(line);
|
|
154
|
+
line = wd;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (line !== '') out.push(line);
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Decide whether a keystroke is a printable character to append to the draft.
|
|
164
|
+
* @param {{input:string, key:any}} k @returns {boolean}
|
|
165
|
+
*/
|
|
166
|
+
export function isPrintable(k) {
|
|
167
|
+
const key = k.key || {};
|
|
168
|
+
if (key.ctrl || key.meta) return false;
|
|
169
|
+
if (key.return || key.escape || key.backspace || key.tab || key.shiftTab) return false;
|
|
170
|
+
if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) return false;
|
|
171
|
+
const ch = k.input;
|
|
172
|
+
if (!ch || ch.length === 0) return false;
|
|
173
|
+
const code = ch.codePointAt(0);
|
|
174
|
+
if (code == null) return false;
|
|
175
|
+
if (code < 0x20 || code === 0x7f) return false; // C0 controls + DEL
|
|
176
|
+
return true;
|
|
177
|
+
}
|