@alashi/cli 0.8.1 → 0.9.0

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/assets/v1/chat.js CHANGED
@@ -1,4 +1,4 @@
1
- /* alashi chat component v1
1
+ /* alashi chat + markdown components v1
2
2
  *
3
3
  * The system chat UI, served by the host. Apps drop in:
4
4
  *
@@ -9,6 +9,10 @@
9
9
  * and cost display. Renders into light DOM using system.css classes, so it
10
10
  * inherits the app's theme tokens.
11
11
  *
12
+ * The same script also registers <alashi-markdown>, the markdown renderer on
13
+ * its own for apps that display prose outside a conversation (see the bottom
14
+ * of this file). One renderer, one place formatting bugs get fixed.
15
+ *
12
16
  * Attributes:
13
17
  * app app name (default: derived from /app/<name>/ in the URL)
14
18
  * placeholder input placeholder text
@@ -31,7 +35,8 @@
31
35
  * Breaking changes ship as /assets/v2/chat.js. */
32
36
 
33
37
  (() => {
34
- if (customElements.get('alashi-chat')) return;
38
+ // Loading the script twice is a no-op for every element it defines.
39
+ if (customElements.get('alashi-chat') || customElements.get('alashi-markdown')) return;
35
40
 
36
41
  const escapeHtml = (s) =>
37
42
  s
@@ -357,5 +362,40 @@
357
362
  }
358
363
  }
359
364
 
365
+ /* <alashi-markdown> — the same renderMarkdown() as chat bubbles, as a
366
+ * standalone display primitive. No fetching, no SSE, no conversations.
367
+ *
368
+ * <alashi-markdown text="**hi**"></alashi-markdown> // static markup
369
+ * node.text = card.description; // re-renders
370
+ *
371
+ * The `text` property is the primary path: apps pass model-derived,
372
+ * multi-line strings that do not belong in an attribute. Renders into light
373
+ * DOM (like _setMsgText) so it inherits the app's theme tokens, and carries
374
+ * the `markdown` class so system.css can style its children. */
375
+ class AlashiMarkdown extends HTMLElement {
376
+ connectedCallback() {
377
+ this.classList.add('markdown');
378
+ // A property set before connect wins; the attribute is the static path.
379
+ if (this._text === undefined) this._text = this.getAttribute('text') ?? '';
380
+ this._render();
381
+ }
382
+
383
+ get text() {
384
+ return this._text ?? '';
385
+ }
386
+
387
+ set text(value) {
388
+ this._text = String(value ?? '');
389
+ this._render();
390
+ }
391
+
392
+ _render() {
393
+ // Escape-first pipeline: renderMarkdown escapes before rebuilding a
394
+ // known-safe subset of tags, so untrusted markdown stays inert.
395
+ this.innerHTML = renderMarkdown(String(this._text ?? ''));
396
+ }
397
+ }
398
+
360
399
  customElements.define('alashi-chat', AlashiChat);
400
+ customElements.define('alashi-markdown', AlashiMarkdown);
361
401
  })();
@@ -578,41 +578,39 @@ input[type="checkbox"] {
578
578
  /* assistant bubbles hold rendered markdown (chat.js), not preformatted text */
579
579
  white-space: normal;
580
580
  }
581
- .msg.assistant p,
582
- .msg.assistant ul,
583
- .msg.assistant ol,
584
- .msg.assistant pre,
585
- .msg.assistant h3,
586
- .msg.assistant h4,
587
- .msg.assistant h5,
588
- .msg.assistant h6 {
581
+ /* Rendered-markdown prose. Shared by assistant chat bubbles and the
582
+ * <alashi-markdown> element (or any `.markdown` container) — chat.js renders
583
+ * both with the same renderMarkdown(), so the styling lives in one place too.
584
+ * Headings stay h3..h6 because that is what renderMarkdown emits. */
585
+ alashi-markdown {
586
+ /* unknown element to CSS, same as <alashi-chat> in consumer apps */
587
+ display: block;
588
+ }
589
+ :is(.msg.assistant, alashi-markdown, .markdown) :is(p, ul, ol, pre, h3, h4, h5, h6) {
589
590
  margin: 0 0 0.6rem;
590
591
  }
591
- .msg.assistant > :last-child {
592
+ :is(.msg.assistant, alashi-markdown, .markdown) > :last-child {
592
593
  margin-bottom: 0;
593
594
  }
594
- .msg.assistant ul,
595
- .msg.assistant ol {
595
+ :is(.msg.assistant, alashi-markdown, .markdown) :is(ul, ol) {
596
596
  padding-left: 1.3rem;
597
597
  }
598
- .msg.assistant li {
598
+ :is(.msg.assistant, alashi-markdown, .markdown) li {
599
599
  margin: 0.15rem 0;
600
600
  }
601
- .msg.assistant img {
601
+ :is(.msg.assistant, alashi-markdown, .markdown) img {
602
602
  max-width: 100%;
603
603
  border-radius: var(--radius-sm);
604
604
  border: 1px solid var(--border);
605
605
  }
606
- .msg.assistant pre {
606
+ :is(.msg.assistant, alashi-markdown, .markdown) pre {
607
607
  background: var(--panel);
608
608
  padding: 0.6rem 0.75rem;
609
609
  }
610
- .msg.assistant h3 {
610
+ :is(.msg.assistant, alashi-markdown, .markdown) h3 {
611
611
  font-size: 1rem;
612
612
  }
613
- .msg.assistant h4,
614
- .msg.assistant h5,
615
- .msg.assistant h6 {
613
+ :is(.msg.assistant, alashi-markdown, .markdown) :is(h4, h5, h6) {
616
614
  font-size: 0.92rem;
617
615
  }
618
616
  .msg.assistant.pending {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alashi/cli",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "alashi host: install, manage, and run Claude Code-powered apps",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -73,6 +73,10 @@ the connection before calling `runMigrations`.
73
73
  with `openConversation`/`adoptSession`). Methods: `adoptSession(sessionId, title?)`,
74
74
  `openConversation(id)`, `newChat()`. Bubbling events: `alashi-chat:turn`
75
75
  (`{ok, costUsd, error, conversationId}`), `alashi-chat:conversation`.
76
+ The same script also registers `<alashi-markdown>` — the host's markdown
77
+ renderer as a standalone display primitive, for prose outside a conversation
78
+ (`node.text = card.description` re-renders on assignment; `text="**hi**"` is
79
+ honoured on connect for static markup). No fetching, no conversation logic.
76
80
  Never vendor or fork system UI; breaking changes ship as `/assets/v2/`.
77
81
 
78
82
  ## App routes
@@ -84,7 +88,8 @@ the connection before calling `runMigrations`.
84
88
 
85
89
  - Never `innerHTML` external or model-derived data in the UI — build DOM via
86
90
  the `el()` helper / `textContent`. Markdown rendering belongs to
87
- `<alashi-chat>`, which is escape-first.
91
+ `<alashi-chat>` / `<alashi-markdown>`, the sanctioned exception because the
92
+ host's renderer is escape-first. Never bundle a markdown library.
88
93
  - Validate at boundaries (webhooks, user input): JSON only, cap body sizes,
89
94
  4xx on garbage. Model output is a boundary too — parse defensively.
90
95
  - Secrets come from declared `config` keys (`secret: true`), referenced as