@oh-my-pi/pi-tui 18.1.5 → 18.1.8

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.1.6] - 2026-09-03
6
+
7
+ ### Fixed
8
+
9
+ - Fixed the band composer layout so the status line remains visible and no longer causes the prompt to shift unexpectedly when the top border is empty.
10
+
5
11
  ## [18.1.5] - 2026-09-03
6
12
 
7
13
  ### Fixed
@@ -12,6 +12,20 @@ export declare let fastTailSplices: number;
12
12
  export declare function resetFastTailSplices(): void;
13
13
  /** @internal exported for tests — the grown-line-start block-kind gate. */
14
14
  export declare function fastLineStartHazard(grownLine: string): boolean;
15
+ /** A hyperlink as the renderer sees it: inline `[text](href)`, `<autolink>`, bare GFM URL, or reference link. */
16
+ export interface MarkdownLink {
17
+ /** Visible link text (equals `href` for autolinks and bare URLs). */
18
+ text: string;
19
+ /** Destination exactly as marked resolved it (references resolved, no normalization). */
20
+ href: string;
21
+ }
22
+ /**
23
+ * Every link token in `text`, in document order, from the same configured
24
+ * lexer the renderer uses — so fenced code, code spans, escapes, reference
25
+ * definitions and the GFM autolink rules agree with what is drawn on screen.
26
+ * Duplicate hrefs are kept; callers decide how to fold them.
27
+ */
28
+ export declare function extractMarkdownLinks(text: string): MarkdownLink[];
15
29
  /** Drop all L2 cache entries. Call on theme change to prevent stale styled output. */
16
30
  export declare function clearRenderCache(): void;
17
31
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-tui",
4
- "version": "18.1.5",
4
+ "version": "18.1.8",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Stencil Labs, Inc.",
@@ -37,8 +37,8 @@
37
37
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
38
38
  },
39
39
  "dependencies": {
40
- "@oh-my-pi/pi-natives": "18.1.5",
41
- "@oh-my-pi/pi-utils": "18.1.5"
40
+ "@oh-my-pi/pi-natives": "18.1.8",
41
+ "@oh-my-pi/pi-utils": "18.1.8"
42
42
  },
43
43
  "devDependencies": {
44
44
  "kitty-vt-wasm": "^0.2.0"
@@ -24,9 +24,13 @@ export const bandComposerStyle: ComposerStyle = {
24
24
  return 0;
25
25
  },
26
26
 
27
- renderTop(ctx: ComposerChromeContext): string | undefined {
27
+ renderTop(ctx: ComposerChromeContext): string {
28
28
  const { topBorder, width } = ctx;
29
- if (!topBorder?.content) return undefined;
29
+ // The band always owns one chrome row (`verticalChrome: 1`): keep it
30
+ // reserved while the status line has nothing to show yet — the startup
31
+ // prepaint mounts the editor before the session-aware status line
32
+ // attaches — so the band fills in later without shifting the layout.
33
+ if (!topBorder?.content) return "";
30
34
  // The band builder already sizes its groups + gauge to the full width;
31
35
  // truncation only guards against a stale provider during resize.
32
36
  return topBorder.width > width ? truncateToWidth(topBorder.content, width) : topBorder.content;
@@ -1254,6 +1254,52 @@ function lexDocument(text: string): Token[] {
1254
1254
  return lexWindowed(text);
1255
1255
  }
1256
1256
 
1257
+ /** A hyperlink as the renderer sees it: inline `[text](href)`, `<autolink>`, bare GFM URL, or reference link. */
1258
+ export interface MarkdownLink {
1259
+ /** Visible link text (equals `href` for autolinks and bare URLs). */
1260
+ text: string;
1261
+ /** Destination exactly as marked resolved it (references resolved, no normalization). */
1262
+ href: string;
1263
+ }
1264
+
1265
+ /**
1266
+ * Every link token in `text`, in document order, from the same configured
1267
+ * lexer the renderer uses — so fenced code, code spans, escapes, reference
1268
+ * definitions and the GFM autolink rules agree with what is drawn on screen.
1269
+ * Duplicate hrefs are kept; callers decide how to fold them.
1270
+ */
1271
+ export function extractMarkdownLinks(text: string): MarkdownLink[] {
1272
+ const links: MarkdownLink[] = [];
1273
+ const walk = (tokens: readonly Token[] | undefined): void => {
1274
+ if (!tokens) return;
1275
+ for (const token of tokens) {
1276
+ if (token.type === "link") {
1277
+ const link = token as Tokens.Link;
1278
+ if (typeof link.href === "string" && link.href.length > 0) {
1279
+ links.push({
1280
+ text: typeof link.text === "string" && link.text.length > 0 ? link.text : link.href,
1281
+ href: link.href,
1282
+ });
1283
+ }
1284
+ continue;
1285
+ }
1286
+ // Containers: paragraphs, emphasis, lists, blockquotes, table cells.
1287
+ const any = token as {
1288
+ tokens?: Token[];
1289
+ items?: Token[];
1290
+ header?: Array<{ tokens?: Token[] }>;
1291
+ rows?: Array<Array<{ tokens?: Token[] }>>;
1292
+ };
1293
+ walk(any.tokens);
1294
+ walk(any.items);
1295
+ if (any.header) for (const cell of any.header) walk(cell.tokens);
1296
+ if (any.rows) for (const row of any.rows) for (const cell of row) walk(cell.tokens);
1297
+ }
1298
+ };
1299
+ walk(lexDocument(text));
1300
+ return links;
1301
+ }
1302
+
1257
1303
  /** Drop all L2 cache entries. Call on theme change to prevent stale styled output. */
1258
1304
  export function clearRenderCache(): void {
1259
1305
  renderCache.clear();