@suds-cli/markdown 0.1.0-alpha.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/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # @suds-cli/markdown
2
+
3
+ Markdown viewer component for Suds terminal UIs.
4
+
5
+ <img src="../../examples/markdown-demo.gif" width="950" alt="Markdown component demo" />
6
+
7
+ ## Features
8
+
9
+ - Renders markdown with beautiful terminal styling
10
+ - Scrollable viewport for long documents
11
+ - Automatic light/dark theme detection
12
+ - Support for headers, code blocks, lists, links, and more
13
+ - Word wrapping at viewport width
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @suds-cli/markdown
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```typescript
24
+ import { MarkdownModel } from '@suds-cli/markdown'
25
+ import { Program } from '@suds-cli/tea'
26
+
27
+ let model = MarkdownModel.new({ active: true })
28
+ const [updatedModel, cmd] = model.setFileName('README.md')
29
+ model = updatedModel
30
+
31
+ // Handle resize
32
+ const [resizedModel] = model.setSize(width, height)
33
+ model = resizedModel
34
+
35
+ // Render
36
+ const view = model.view()
37
+ ```
38
+
39
+ ## API
40
+
41
+ See the [API documentation](../../docs/markdown.md) for complete details.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Markdown viewer component for Suds terminal UIs.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { MarkdownModel, type MarkdownOptions } from "./model.js";
7
+ export { RenderMarkdownMsg, ErrorMsg } from "./messages.js";
8
+ export { renderMarkdown, type RenderMarkdownOptions } from "./renderer.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Markdown viewer component for Suds terminal UIs.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { MarkdownModel } from "./model.js";
7
+ export { RenderMarkdownMsg, ErrorMsg } from "./messages.js";
8
+ export { renderMarkdown } from "./renderer.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,cAAc,EAA8B,MAAM,eAAe,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Message types for the markdown component.
3
+ */
4
+ /**
5
+ * Message containing rendered markdown content.
6
+ * @public
7
+ */
8
+ export declare class RenderMarkdownMsg {
9
+ readonly content: string;
10
+ readonly _tag = "markdown-render";
11
+ constructor(content: string);
12
+ }
13
+ /**
14
+ * Message containing an error from file reading or rendering.
15
+ * @public
16
+ */
17
+ export declare class ErrorMsg {
18
+ readonly error: Error;
19
+ readonly _tag = "markdown-error";
20
+ constructor(error: Error);
21
+ }
22
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,qBAAa,iBAAiB;aAGA,OAAO,EAAE,MAAM;IAF3C,QAAQ,CAAC,IAAI,qBAAqB;gBAEN,OAAO,EAAE,MAAM;CAC5C;AAED;;;GAGG;AACH,qBAAa,QAAQ;aAGS,KAAK,EAAE,KAAK;IAFxC,QAAQ,CAAC,IAAI,oBAAoB;gBAEL,KAAK,EAAE,KAAK;CACzC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Message types for the markdown component.
3
+ */
4
+ /**
5
+ * Message containing rendered markdown content.
6
+ * @public
7
+ */
8
+ export class RenderMarkdownMsg {
9
+ content;
10
+ _tag = "markdown-render";
11
+ constructor(content) {
12
+ this.content = content;
13
+ }
14
+ }
15
+ /**
16
+ * Message containing an error from file reading or rendering.
17
+ * @public
18
+ */
19
+ export class ErrorMsg {
20
+ error;
21
+ _tag = "markdown-error";
22
+ constructor(error) {
23
+ this.error = error;
24
+ }
25
+ }
26
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAGA;IAFnB,IAAI,GAAG,iBAAiB,CAAC;IAElC,YAA4B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;CAChD;AAED;;;GAGG;AACH,MAAM,OAAO,QAAQ;IAGS;IAFnB,IAAI,GAAG,gBAAgB,CAAC;IAEjC,YAA4B,KAAY;QAAZ,UAAK,GAAL,KAAK,CAAO;IAAG,CAAC;CAC7C"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Markdown viewer component.
3
+ */
4
+ import { Style } from "@suds-cli/chapstick";
5
+ import { ViewportModel } from "@suds-cli/viewport";
6
+ import type { Cmd, Msg } from "@suds-cli/tea";
7
+ /**
8
+ * Options for creating a markdown model.
9
+ * @public
10
+ */
11
+ export interface MarkdownOptions {
12
+ /**
13
+ * Whether the component is active and should handle input.
14
+ * Defaults to true.
15
+ */
16
+ active?: boolean;
17
+ /**
18
+ * Initial width for the viewport.
19
+ * Defaults to 0.
20
+ */
21
+ width?: number;
22
+ /**
23
+ * Initial height for the viewport.
24
+ * Defaults to 0.
25
+ */
26
+ height?: number;
27
+ /**
28
+ * Style for the viewport.
29
+ */
30
+ style?: Style;
31
+ }
32
+ /**
33
+ * Markdown viewer model that renders markdown files with terminal styling
34
+ * in a scrollable viewport.
35
+ * @public
36
+ */
37
+ export declare class MarkdownModel {
38
+ readonly viewport: ViewportModel;
39
+ readonly active: boolean;
40
+ readonly fileName: string;
41
+ private constructor();
42
+ /**
43
+ * Create a new markdown model.
44
+ * @param options - Configuration options
45
+ */
46
+ static new(options?: MarkdownOptions): MarkdownModel;
47
+ /**
48
+ * Tea init hook (no-op).
49
+ */
50
+ init(): Cmd<Msg>;
51
+ /**
52
+ * Set the filename to render. Returns a command that will read and render the file.
53
+ * @param fileName - Path to the markdown file
54
+ */
55
+ setFileName(fileName: string): [MarkdownModel, Cmd<Msg>];
56
+ /**
57
+ * Set the size of the viewport and re-render if a file is set.
58
+ * @param width - New width
59
+ * @param height - New height
60
+ */
61
+ setSize(width: number, height: number): [MarkdownModel, Cmd<Msg>];
62
+ /**
63
+ * Set whether the component is active and should handle input.
64
+ * @param active - Active state
65
+ */
66
+ setIsActive(active: boolean): MarkdownModel;
67
+ /**
68
+ * Scroll to the top of the viewport.
69
+ */
70
+ gotoTop(): MarkdownModel;
71
+ /**
72
+ * Handle messages. Processes viewport scrolling and markdown rendering.
73
+ * @param msg - The message to handle
74
+ */
75
+ update(msg: Msg): [MarkdownModel, Cmd<Msg>];
76
+ /**
77
+ * Render the markdown viewport.
78
+ */
79
+ view(): string;
80
+ private with;
81
+ }
82
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAI9C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,OAAO;IAUP;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,OAAO,GAAE,eAAoB,GAAG,aAAa;IAcxD;;OAEG;IACH,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC;IAIhB;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAMxD;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAYjE;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa;IAK3C;;OAEG;IACH,OAAO,IAAI,aAAa;IAMxB;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAsC3C;;OAEG;IACH,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,IAAI;CAOb"}
package/dist/model.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Markdown viewer component.
3
+ */
4
+ import { Style } from "@suds-cli/chapstick";
5
+ import { readFileContent } from "@suds-cli/filesystem";
6
+ import { ViewportModel } from "@suds-cli/viewport";
7
+ import { RenderMarkdownMsg, ErrorMsg } from "./messages.js";
8
+ import { renderMarkdown } from "./renderer.js";
9
+ /**
10
+ * Markdown viewer model that renders markdown files with terminal styling
11
+ * in a scrollable viewport.
12
+ * @public
13
+ */
14
+ export class MarkdownModel {
15
+ viewport;
16
+ active;
17
+ fileName;
18
+ constructor(options) {
19
+ this.viewport = options.viewport;
20
+ this.active = options.active;
21
+ this.fileName = options.fileName;
22
+ }
23
+ /**
24
+ * Create a new markdown model.
25
+ * @param options - Configuration options
26
+ */
27
+ static new(options = {}) {
28
+ const viewport = ViewportModel.new({
29
+ width: options.width ?? 0,
30
+ height: options.height ?? 0,
31
+ style: options.style,
32
+ });
33
+ return new MarkdownModel({
34
+ viewport,
35
+ active: options.active ?? true,
36
+ fileName: "",
37
+ });
38
+ }
39
+ /**
40
+ * Tea init hook (no-op).
41
+ */
42
+ init() {
43
+ return null;
44
+ }
45
+ /**
46
+ * Set the filename to render. Returns a command that will read and render the file.
47
+ * @param fileName - Path to the markdown file
48
+ */
49
+ setFileName(fileName) {
50
+ const updated = this.with({ fileName });
51
+ const cmd = renderMarkdownCmd(this.viewport.width, fileName);
52
+ return [updated, cmd];
53
+ }
54
+ /**
55
+ * Set the size of the viewport and re-render if a file is set.
56
+ * @param width - New width
57
+ * @param height - New height
58
+ */
59
+ setSize(width, height) {
60
+ const updatedViewport = this.viewport.setWidth(width).setHeight(height);
61
+ const updated = this.with({ viewport: updatedViewport });
62
+ if (this.fileName !== "") {
63
+ const cmd = renderMarkdownCmd(width, this.fileName);
64
+ return [updated, cmd];
65
+ }
66
+ return [updated, null];
67
+ }
68
+ /**
69
+ * Set whether the component is active and should handle input.
70
+ * @param active - Active state
71
+ */
72
+ setIsActive(active) {
73
+ if (active === this.active)
74
+ return this;
75
+ return this.with({ active });
76
+ }
77
+ /**
78
+ * Scroll to the top of the viewport.
79
+ */
80
+ gotoTop() {
81
+ const updatedViewport = this.viewport.scrollToTop();
82
+ if (updatedViewport === this.viewport)
83
+ return this;
84
+ return this.with({ viewport: updatedViewport });
85
+ }
86
+ /**
87
+ * Handle messages. Processes viewport scrolling and markdown rendering.
88
+ * @param msg - The message to handle
89
+ */
90
+ update(msg) {
91
+ // Handle markdown rendering
92
+ if (msg instanceof RenderMarkdownMsg) {
93
+ // Apply width for word wrapping and left-align to pad lines to consistent width
94
+ // Viewport handles height/scrolling
95
+ const styled = new Style()
96
+ .width(this.viewport.width)
97
+ .alignHorizontal('left')
98
+ .render(msg.content);
99
+ const updatedViewport = this.viewport.setContent(styled);
100
+ return [this.with({ viewport: updatedViewport }), null];
101
+ }
102
+ // Handle errors
103
+ if (msg instanceof ErrorMsg) {
104
+ const errorContent = msg.error.message;
105
+ const updatedViewport = this.viewport.setContent(errorContent);
106
+ return [
107
+ this.with({
108
+ fileName: "",
109
+ viewport: updatedViewport,
110
+ }),
111
+ null,
112
+ ];
113
+ }
114
+ // Handle viewport updates if active
115
+ if (this.active) {
116
+ const [updatedViewport, cmd] = this.viewport.update(msg);
117
+ if (updatedViewport !== this.viewport) {
118
+ return [this.with({ viewport: updatedViewport }), cmd];
119
+ }
120
+ }
121
+ return [this, null];
122
+ }
123
+ /**
124
+ * Render the markdown viewport.
125
+ */
126
+ view() {
127
+ return this.viewport.view();
128
+ }
129
+ with(patch) {
130
+ return new MarkdownModel({
131
+ viewport: patch.viewport ?? this.viewport,
132
+ active: patch.active ?? this.active,
133
+ fileName: patch.fileName ?? this.fileName,
134
+ });
135
+ }
136
+ }
137
+ /**
138
+ * Command to read and render a markdown file.
139
+ */
140
+ function renderMarkdownCmd(width, fileName) {
141
+ return async () => {
142
+ try {
143
+ const content = await readFileContent(fileName);
144
+ const rendered = renderMarkdown(content, { width });
145
+ return new RenderMarkdownMsg(rendered);
146
+ }
147
+ catch (error) {
148
+ return new ErrorMsg(error instanceof Error ? error : new Error(String(error)));
149
+ }
150
+ };
151
+ }
152
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Markdown rendering utilities.
3
+ */
4
+ /**
5
+ * Options for rendering markdown.
6
+ * @public
7
+ */
8
+ export interface RenderMarkdownOptions {
9
+ /**
10
+ * Width for word wrapping. Defaults to 80.
11
+ */
12
+ width?: number;
13
+ }
14
+ /**
15
+ * Renders markdown content with terminal styling.
16
+ * Detects terminal background (light/dark) and applies appropriate styling.
17
+ *
18
+ * @param content - The markdown string to render
19
+ * @param options - Rendering options
20
+ * @returns The styled markdown output
21
+ * @public
22
+ */
23
+ export declare function renderMarkdown(content: string, options?: RenderMarkdownOptions): string;
24
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAsCR"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Markdown rendering utilities.
3
+ */
4
+ import { Marked } from "marked";
5
+ import { markedTerminal } from "marked-terminal";
6
+ import { getTerminalBackground } from "@suds-cli/chapstick";
7
+ import chalk from "chalk";
8
+ /**
9
+ * Renders markdown content with terminal styling.
10
+ * Detects terminal background (light/dark) and applies appropriate styling.
11
+ *
12
+ * @param content - The markdown string to render
13
+ * @param options - Rendering options
14
+ * @returns The styled markdown output
15
+ * @public
16
+ */
17
+ export function renderMarkdown(content, options = {}) {
18
+ const width = options.width ?? 80;
19
+ const background = getTerminalBackground();
20
+ // Use appropriate colors for terminal background
21
+ const isDark = background !== 'light';
22
+ // Create marked instance with terminal renderer
23
+ const marked = new Marked(markedTerminal({
24
+ // Wrap text at specified width
25
+ width,
26
+ reflowText: true,
27
+ // Headings - brighter on dark backgrounds
28
+ firstHeading: isDark ? chalk.cyan.bold : chalk.blue.bold,
29
+ heading: isDark ? chalk.cyan.bold : chalk.blue.bold,
30
+ // Code blocks
31
+ code: isDark ? chalk.white : chalk.gray,
32
+ blockquote: isDark ? chalk.white : chalk.gray,
33
+ // Emphasis
34
+ strong: chalk.bold,
35
+ em: chalk.italic,
36
+ // Lists
37
+ listitem: chalk.reset,
38
+ // Links
39
+ link: isDark ? chalk.blueBright : chalk.blue,
40
+ // Other elements
41
+ hr: chalk.gray,
42
+ paragraph: chalk.reset,
43
+ }));
44
+ try {
45
+ const rendered = marked.parse(content);
46
+ return rendered.trim();
47
+ }
48
+ catch (error) {
49
+ throw new Error(`Failed to render markdown: ${error instanceof Error ? error.message : String(error)}`);
50
+ }
51
+ }
52
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,UAAiC,EAAE;IAEnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAE3C,iDAAiD;IACjD,MAAM,MAAM,GAAG,UAAU,KAAK,OAAO,CAAC;IAEtC,gDAAgD;IAChD,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,cAAc,CAAC;QACb,+BAA+B;QAC/B,KAAK;QACL,UAAU,EAAE,IAAI;QAChB,0CAA0C;QAC1C,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI;QACxD,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI;QACnD,cAAc;QACd,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QACvC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QAC7C,WAAW;QACX,MAAM,EAAE,KAAK,CAAC,IAAI;QAClB,EAAE,EAAE,KAAK,CAAC,MAAM;QAChB,QAAQ;QACR,QAAQ,EAAE,KAAK,CAAC,KAAK;QACrB,QAAQ;QACR,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QAC5C,iBAAiB;QACjB,EAAE,EAAE,KAAK,CAAC,IAAI;QACd,SAAS,EAAE,KAAK,CAAC,KAAK;KACvB,CAAC,CACH,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC;QACjD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@suds-cli/markdown",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Markdown viewer component for Suds terminal UIs",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "dependencies": {
12
+ "chalk": "^5.4.1",
13
+ "marked": "^15.0.0",
14
+ "marked-terminal": "^7.3.0",
15
+ "@suds-cli/chapstick": "0.1.0-alpha.0",
16
+ "@suds-cli/filesystem": "0.0.0",
17
+ "@suds-cli/tea": "0.0.0",
18
+ "@suds-cli/viewport": "0.0.1-alpha.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "5.8.2",
22
+ "vitest": "^4.0.15"
23
+ },
24
+ "engines": {
25
+ "node": ">=20.0.0"
26
+ },
27
+ "scripts": {
28
+ "clean": "rm -rf dist",
29
+ "build": "pnpm run clean && tsc -p ./tsconfig.json",
30
+ "test": "vitest run",
31
+ "generate:api-report": "api-extractor run --local",
32
+ "check:api-report": "pnpm run generate:api-report",
33
+ "check:eslint": "pnpm run lint",
34
+ "lint": "eslint \"{src,test}/**/*.{ts,tsx}\""
35
+ }
36
+ }