@suds-cli/markdown 0.1.0-alpha.0 → 0.1.0-alpha.1
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/index.cjs +200 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +146 -0
- package/dist/index.d.ts +143 -6
- package/dist/index.js +194 -8
- package/dist/index.js.map +1 -1
- package/package.json +31 -18
- package/dist/index.d.ts.map +0 -1
- package/dist/messages.d.ts +0 -22
- package/dist/messages.d.ts.map +0 -1
- package/dist/messages.js +0 -26
- package/dist/messages.js.map +0 -1
- package/dist/model.d.ts +0 -82
- package/dist/model.d.ts.map +0 -1
- package/dist/model.js +0 -152
- package/dist/model.js.map +0 -1
- package/dist/renderer.d.ts +0 -24
- package/dist/renderer.d.ts.map +0 -1
- package/dist/renderer.js +0 -52
- package/dist/renderer.js.map +0 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chapstick = require('@suds-cli/chapstick');
|
|
4
|
+
var filesystem = require('@suds-cli/filesystem');
|
|
5
|
+
var viewport = require('@suds-cli/viewport');
|
|
6
|
+
var marked = require('marked');
|
|
7
|
+
var markedTerminal = require('marked-terminal');
|
|
8
|
+
var machine = require('@suds-cli/machine');
|
|
9
|
+
|
|
10
|
+
// src/model.ts
|
|
11
|
+
|
|
12
|
+
// src/messages.ts
|
|
13
|
+
var RenderMarkdownMsg = class {
|
|
14
|
+
constructor(content) {
|
|
15
|
+
this.content = content;
|
|
16
|
+
}
|
|
17
|
+
_tag = "markdown-render";
|
|
18
|
+
};
|
|
19
|
+
var ErrorMsg = class {
|
|
20
|
+
constructor(error) {
|
|
21
|
+
this.error = error;
|
|
22
|
+
}
|
|
23
|
+
_tag = "markdown-error";
|
|
24
|
+
};
|
|
25
|
+
function renderMarkdown(content, options = {}) {
|
|
26
|
+
const width = options.width ?? 80;
|
|
27
|
+
const background = options.background ?? options.env?.getTerminalBackground() ?? "dark";
|
|
28
|
+
const isDark = background !== "light";
|
|
29
|
+
const style = machine.createAlwaysEnabledStyle();
|
|
30
|
+
const marked$1 = new marked.Marked(
|
|
31
|
+
markedTerminal.markedTerminal({
|
|
32
|
+
// Wrap text at specified width
|
|
33
|
+
width,
|
|
34
|
+
reflowText: true,
|
|
35
|
+
// Headings - brighter on dark backgrounds
|
|
36
|
+
firstHeading: isDark ? style.cyan.bold : style.blue.bold,
|
|
37
|
+
heading: isDark ? style.cyan.bold : style.blue.bold,
|
|
38
|
+
// Code blocks
|
|
39
|
+
code: isDark ? style.white : style.gray,
|
|
40
|
+
blockquote: isDark ? style.white : style.gray,
|
|
41
|
+
// Emphasis
|
|
42
|
+
strong: style.bold,
|
|
43
|
+
em: style.italic,
|
|
44
|
+
// Lists
|
|
45
|
+
listitem: style,
|
|
46
|
+
// Links
|
|
47
|
+
link: isDark ? style.blueBright : style.blue,
|
|
48
|
+
// Other elements
|
|
49
|
+
hr: style.gray,
|
|
50
|
+
paragraph: style
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
try {
|
|
54
|
+
const rendered = marked$1.parse(content);
|
|
55
|
+
return rendered.trim();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Failed to render markdown: ${error instanceof Error ? error.message : String(error)}`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/model.ts
|
|
64
|
+
var MarkdownModel = class _MarkdownModel {
|
|
65
|
+
viewport;
|
|
66
|
+
active;
|
|
67
|
+
fileName;
|
|
68
|
+
filesystem;
|
|
69
|
+
constructor(options) {
|
|
70
|
+
this.viewport = options.viewport;
|
|
71
|
+
this.active = options.active;
|
|
72
|
+
this.fileName = options.fileName;
|
|
73
|
+
this.filesystem = options.filesystem;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a new markdown model.
|
|
77
|
+
* @param options - Configuration options
|
|
78
|
+
*/
|
|
79
|
+
static new(options) {
|
|
80
|
+
const viewport$1 = viewport.ViewportModel.new({
|
|
81
|
+
width: options.width ?? 0,
|
|
82
|
+
height: options.height ?? 0,
|
|
83
|
+
style: options.style
|
|
84
|
+
});
|
|
85
|
+
return new _MarkdownModel({
|
|
86
|
+
viewport: viewport$1,
|
|
87
|
+
active: options.active ?? true,
|
|
88
|
+
fileName: "",
|
|
89
|
+
filesystem: options.filesystem
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Tea init hook (no-op).
|
|
94
|
+
*/
|
|
95
|
+
init() {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Set the filename to render. Returns a command that will read and render the file.
|
|
100
|
+
* @param fileName - Path to the markdown file
|
|
101
|
+
*/
|
|
102
|
+
setFileName(fileName) {
|
|
103
|
+
const updated = this.with({ fileName });
|
|
104
|
+
const cmd = renderMarkdownCmd(this.filesystem, this.viewport.width, fileName);
|
|
105
|
+
return [updated, cmd];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Set the size of the viewport and re-render if a file is set.
|
|
109
|
+
* @param width - New width
|
|
110
|
+
* @param height - New height
|
|
111
|
+
*/
|
|
112
|
+
setSize(width, height) {
|
|
113
|
+
const updatedViewport = this.viewport.setWidth(width).setHeight(height);
|
|
114
|
+
const updated = this.with({ viewport: updatedViewport });
|
|
115
|
+
if (this.fileName !== "") {
|
|
116
|
+
const cmd = renderMarkdownCmd(this.filesystem, width, this.fileName);
|
|
117
|
+
return [updated, cmd];
|
|
118
|
+
}
|
|
119
|
+
return [updated, null];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Set whether the component is active and should handle input.
|
|
123
|
+
* @param active - Active state
|
|
124
|
+
*/
|
|
125
|
+
setIsActive(active) {
|
|
126
|
+
if (active === this.active) return this;
|
|
127
|
+
return this.with({ active });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Scroll to the top of the viewport.
|
|
131
|
+
*/
|
|
132
|
+
gotoTop() {
|
|
133
|
+
const updatedViewport = this.viewport.scrollToTop();
|
|
134
|
+
if (updatedViewport === this.viewport) return this;
|
|
135
|
+
return this.with({ viewport: updatedViewport });
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Handle messages. Processes viewport scrolling and markdown rendering.
|
|
139
|
+
* @param msg - The message to handle
|
|
140
|
+
*/
|
|
141
|
+
update(msg) {
|
|
142
|
+
if (msg instanceof RenderMarkdownMsg) {
|
|
143
|
+
const styled = new chapstick.Style().width(this.viewport.width).alignHorizontal("left").render(msg.content);
|
|
144
|
+
const updatedViewport = this.viewport.setContent(styled);
|
|
145
|
+
return [this.with({ viewport: updatedViewport }), null];
|
|
146
|
+
}
|
|
147
|
+
if (msg instanceof ErrorMsg) {
|
|
148
|
+
const errorContent = msg.error.message;
|
|
149
|
+
const updatedViewport = this.viewport.setContent(errorContent);
|
|
150
|
+
return [
|
|
151
|
+
this.with({
|
|
152
|
+
fileName: "",
|
|
153
|
+
viewport: updatedViewport
|
|
154
|
+
}),
|
|
155
|
+
null
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
if (this.active) {
|
|
159
|
+
const [updatedViewport, cmd] = this.viewport.update(msg);
|
|
160
|
+
if (updatedViewport !== this.viewport) {
|
|
161
|
+
return [this.with({ viewport: updatedViewport }), cmd];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return [this, null];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Render the markdown viewport.
|
|
168
|
+
*/
|
|
169
|
+
view() {
|
|
170
|
+
return this.viewport.view();
|
|
171
|
+
}
|
|
172
|
+
with(patch) {
|
|
173
|
+
return new _MarkdownModel({
|
|
174
|
+
viewport: patch.viewport ?? this.viewport,
|
|
175
|
+
active: patch.active ?? this.active,
|
|
176
|
+
fileName: patch.fileName ?? this.fileName,
|
|
177
|
+
filesystem: patch.filesystem ?? this.filesystem
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
function renderMarkdownCmd(fs, width, fileName) {
|
|
182
|
+
return async () => {
|
|
183
|
+
try {
|
|
184
|
+
const content = await filesystem.readFileContent(fs, fileName);
|
|
185
|
+
const rendered = renderMarkdown(content, { width });
|
|
186
|
+
return new RenderMarkdownMsg(rendered);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return new ErrorMsg(
|
|
189
|
+
error instanceof Error ? error : new Error(String(error))
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
exports.ErrorMsg = ErrorMsg;
|
|
196
|
+
exports.MarkdownModel = MarkdownModel;
|
|
197
|
+
exports.RenderMarkdownMsg = RenderMarkdownMsg;
|
|
198
|
+
exports.renderMarkdown = renderMarkdown;
|
|
199
|
+
//# sourceMappingURL=index.cjs.map
|
|
200
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/messages.ts","../src/renderer.ts","../src/model.ts"],"names":["createAlwaysEnabledStyle","marked","Marked","markedTerminal","viewport","ViewportModel","Style","readFileContent"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Message types for the markdown component.\n */\n\n/**\n * Message containing rendered markdown content.\n * @public\n */\nexport class RenderMarkdownMsg {\n readonly _tag = 'markdown-render'\n\n constructor(public readonly content: string) {}\n}\n\n/**\n * Message containing an error from file reading or rendering.\n * @public\n */\nexport class ErrorMsg {\n readonly _tag = 'markdown-error'\n\n constructor(public readonly error: Error) {}\n}\n","/**\n * Markdown rendering utilities.\n */\n\nimport { Marked } from 'marked'\nimport { markedTerminal } from 'marked-terminal'\nimport type { EnvironmentAdapter, TerminalBackground } from '@suds-cli/machine'\nimport { createAlwaysEnabledStyle } from '@suds-cli/machine'\n\n/**\n * Options for rendering markdown.\n * @public\n */\nexport interface RenderMarkdownOptions {\n /**\n * Width for word wrapping. Defaults to 80.\n */\n width?: number\n /**\n * Terminal background mode. Defaults to 'dark'.\n */\n background?: TerminalBackground\n /**\n * Environment adapter for detecting terminal capabilities.\n */\n env?: EnvironmentAdapter\n}\n\n/**\n * Renders markdown content with terminal styling.\n * Detects terminal background (light/dark) and applies appropriate styling.\n *\n * @param content - The markdown string to render\n * @param options - Rendering options\n * @returns The styled markdown output\n * @public\n */\nexport function renderMarkdown(\n content: string,\n options: RenderMarkdownOptions = {},\n): string {\n const width = options.width ?? 80\n const background = options.background ?? options.env?.getTerminalBackground() ?? 'dark'\n\n // Use appropriate colors for terminal background\n const isDark = background !== 'light'\n\n // Create a style function with full color support for markdown rendering\n const style = createAlwaysEnabledStyle()\n\n // Create marked instance with terminal renderer\n const marked = new Marked(\n markedTerminal({\n // Wrap text at specified width\n width,\n reflowText: true,\n // Headings - brighter on dark backgrounds\n firstHeading: isDark ? style.cyan.bold : style.blue.bold,\n heading: isDark ? style.cyan.bold : style.blue.bold,\n // Code blocks\n code: isDark ? style.white : style.gray,\n blockquote: isDark ? style.white : style.gray,\n // Emphasis\n strong: style.bold,\n em: style.italic,\n // Lists\n listitem: style,\n // Links\n link: isDark ? style.blueBright : style.blue,\n // Other elements\n hr: style.gray,\n paragraph: style,\n }),\n )\n\n try {\n const rendered = marked.parse(content) as string\n return rendered.trim()\n } catch (error) {\n throw new Error(\n `Failed to render markdown: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n","/**\n * Markdown viewer component.\n */\n\nimport { Style } from '@suds-cli/chapstick'\nimport { readFileContent } from '@suds-cli/filesystem'\nimport { ViewportModel } from '@suds-cli/viewport'\nimport type { Cmd, Msg } from '@suds-cli/tea'\nimport type { FileSystemAdapter } from '@suds-cli/machine'\nimport { RenderMarkdownMsg, ErrorMsg } from './messages.js'\nimport { renderMarkdown } from './renderer.js'\n\n/**\n * Options for creating a markdown model.\n * @public\n */\nexport interface MarkdownOptions {\n /**\n * Filesystem adapter for file operations.\n */\n filesystem: FileSystemAdapter\n /**\n * Whether the component is active and should handle input.\n * Defaults to true.\n */\n active?: boolean\n /**\n * Initial width for the viewport.\n * Defaults to 0.\n */\n width?: number\n /**\n * Initial height for the viewport.\n * Defaults to 0.\n */\n height?: number\n /**\n * Style for the viewport.\n */\n style?: Style\n}\n\n/**\n * Markdown viewer model that renders markdown files with terminal styling\n * in a scrollable viewport.\n * @public\n */\nexport class MarkdownModel {\n readonly viewport: ViewportModel\n readonly active: boolean\n readonly fileName: string\n readonly filesystem: FileSystemAdapter\n\n private constructor(options: {\n viewport: ViewportModel\n active: boolean\n fileName: string\n filesystem: FileSystemAdapter\n }) {\n this.viewport = options.viewport\n this.active = options.active\n this.fileName = options.fileName\n this.filesystem = options.filesystem\n }\n\n /**\n * Create a new markdown model.\n * @param options - Configuration options\n */\n static new(options: MarkdownOptions): MarkdownModel {\n const viewport = ViewportModel.new({\n width: options.width ?? 0,\n height: options.height ?? 0,\n style: options.style,\n })\n\n return new MarkdownModel({\n viewport,\n active: options.active ?? true,\n fileName: '',\n filesystem: options.filesystem,\n })\n }\n\n /**\n * Tea init hook (no-op).\n */\n init(): Cmd<Msg> {\n return null\n }\n\n /**\n * Set the filename to render. Returns a command that will read and render the file.\n * @param fileName - Path to the markdown file\n */\n setFileName(fileName: string): [MarkdownModel, Cmd<Msg>] {\n const updated = this.with({ fileName })\n const cmd = renderMarkdownCmd(this.filesystem, this.viewport.width, fileName)\n return [updated, cmd]\n }\n\n /**\n * Set the size of the viewport and re-render if a file is set.\n * @param width - New width\n * @param height - New height\n */\n setSize(width: number, height: number): [MarkdownModel, Cmd<Msg>] {\n const updatedViewport = this.viewport.setWidth(width).setHeight(height)\n const updated = this.with({ viewport: updatedViewport })\n\n if (this.fileName !== '') {\n const cmd = renderMarkdownCmd(this.filesystem, width, this.fileName)\n return [updated, cmd]\n }\n\n return [updated, null]\n }\n\n /**\n * Set whether the component is active and should handle input.\n * @param active - Active state\n */\n setIsActive(active: boolean): MarkdownModel {\n if (active === this.active) return this\n return this.with({ active })\n }\n\n /**\n * Scroll to the top of the viewport.\n */\n gotoTop(): MarkdownModel {\n const updatedViewport = this.viewport.scrollToTop()\n if (updatedViewport === this.viewport) return this\n return this.with({ viewport: updatedViewport })\n }\n\n /**\n * Handle messages. Processes viewport scrolling and markdown rendering.\n * @param msg - The message to handle\n */\n update(msg: Msg): [MarkdownModel, Cmd<Msg>] {\n // Handle markdown rendering\n if (msg instanceof RenderMarkdownMsg) {\n // Apply width for word wrapping and left-align to pad lines to consistent width\n // Viewport handles height/scrolling\n const styled = new Style()\n .width(this.viewport.width)\n .alignHorizontal('left')\n .render(msg.content)\n\n const updatedViewport = this.viewport.setContent(styled)\n return [this.with({ viewport: updatedViewport }), null]\n }\n\n // Handle errors\n if (msg instanceof ErrorMsg) {\n const errorContent = msg.error.message\n const updatedViewport = this.viewport.setContent(errorContent)\n return [\n this.with({\n fileName: '',\n viewport: updatedViewport,\n }),\n null,\n ]\n }\n\n // Handle viewport updates if active\n if (this.active) {\n const [updatedViewport, cmd] = this.viewport.update(msg)\n if (updatedViewport !== this.viewport) {\n return [this.with({ viewport: updatedViewport }), cmd]\n }\n }\n\n return [this, null]\n }\n\n /**\n * Render the markdown viewport.\n */\n view(): string {\n return this.viewport.view()\n }\n\n private with(patch: Partial<MarkdownModel>): MarkdownModel {\n return new MarkdownModel({\n viewport: patch.viewport ?? this.viewport,\n active: patch.active ?? this.active,\n fileName: patch.fileName ?? this.fileName,\n filesystem: patch.filesystem ?? this.filesystem,\n })\n }\n}\n\n/**\n * Command to read and render a markdown file.\n */\nfunction renderMarkdownCmd(\n fs: FileSystemAdapter,\n width: number,\n fileName: string,\n): Cmd<Msg> {\n return async () => {\n try {\n const content = await readFileContent(fs, fileName)\n const rendered = renderMarkdown(content, { width })\n return new RenderMarkdownMsg(rendered)\n } catch (error) {\n return new ErrorMsg(\n error instanceof Error ? error : new Error(String(error)),\n )\n }\n }\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Style } from '@suds-cli/chapstick';
|
|
2
|
+
import { ViewportModel } from '@suds-cli/viewport';
|
|
3
|
+
import { Cmd, Msg } from '@suds-cli/tea';
|
|
4
|
+
import { FileSystemAdapter, TerminalBackground, EnvironmentAdapter } from '@suds-cli/machine';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Markdown viewer component.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for creating a markdown model.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
interface MarkdownOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Filesystem adapter for file operations.
|
|
17
|
+
*/
|
|
18
|
+
filesystem: FileSystemAdapter;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the component is active and should handle input.
|
|
21
|
+
* Defaults to true.
|
|
22
|
+
*/
|
|
23
|
+
active?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Initial width for the viewport.
|
|
26
|
+
* Defaults to 0.
|
|
27
|
+
*/
|
|
28
|
+
width?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Initial height for the viewport.
|
|
31
|
+
* Defaults to 0.
|
|
32
|
+
*/
|
|
33
|
+
height?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Style for the viewport.
|
|
36
|
+
*/
|
|
37
|
+
style?: Style;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Markdown viewer model that renders markdown files with terminal styling
|
|
41
|
+
* in a scrollable viewport.
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
declare class MarkdownModel {
|
|
45
|
+
readonly viewport: ViewportModel;
|
|
46
|
+
readonly active: boolean;
|
|
47
|
+
readonly fileName: string;
|
|
48
|
+
readonly filesystem: FileSystemAdapter;
|
|
49
|
+
private constructor();
|
|
50
|
+
/**
|
|
51
|
+
* Create a new markdown model.
|
|
52
|
+
* @param options - Configuration options
|
|
53
|
+
*/
|
|
54
|
+
static new(options: MarkdownOptions): MarkdownModel;
|
|
55
|
+
/**
|
|
56
|
+
* Tea init hook (no-op).
|
|
57
|
+
*/
|
|
58
|
+
init(): Cmd<Msg>;
|
|
59
|
+
/**
|
|
60
|
+
* Set the filename to render. Returns a command that will read and render the file.
|
|
61
|
+
* @param fileName - Path to the markdown file
|
|
62
|
+
*/
|
|
63
|
+
setFileName(fileName: string): [MarkdownModel, Cmd<Msg>];
|
|
64
|
+
/**
|
|
65
|
+
* Set the size of the viewport and re-render if a file is set.
|
|
66
|
+
* @param width - New width
|
|
67
|
+
* @param height - New height
|
|
68
|
+
*/
|
|
69
|
+
setSize(width: number, height: number): [MarkdownModel, Cmd<Msg>];
|
|
70
|
+
/**
|
|
71
|
+
* Set whether the component is active and should handle input.
|
|
72
|
+
* @param active - Active state
|
|
73
|
+
*/
|
|
74
|
+
setIsActive(active: boolean): MarkdownModel;
|
|
75
|
+
/**
|
|
76
|
+
* Scroll to the top of the viewport.
|
|
77
|
+
*/
|
|
78
|
+
gotoTop(): MarkdownModel;
|
|
79
|
+
/**
|
|
80
|
+
* Handle messages. Processes viewport scrolling and markdown rendering.
|
|
81
|
+
* @param msg - The message to handle
|
|
82
|
+
*/
|
|
83
|
+
update(msg: Msg): [MarkdownModel, Cmd<Msg>];
|
|
84
|
+
/**
|
|
85
|
+
* Render the markdown viewport.
|
|
86
|
+
*/
|
|
87
|
+
view(): string;
|
|
88
|
+
private with;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Message types for the markdown component.
|
|
93
|
+
*/
|
|
94
|
+
/**
|
|
95
|
+
* Message containing rendered markdown content.
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
declare class RenderMarkdownMsg {
|
|
99
|
+
readonly content: string;
|
|
100
|
+
readonly _tag = "markdown-render";
|
|
101
|
+
constructor(content: string);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Message containing an error from file reading or rendering.
|
|
105
|
+
* @public
|
|
106
|
+
*/
|
|
107
|
+
declare class ErrorMsg {
|
|
108
|
+
readonly error: Error;
|
|
109
|
+
readonly _tag = "markdown-error";
|
|
110
|
+
constructor(error: Error);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Markdown rendering utilities.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Options for rendering markdown.
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
interface RenderMarkdownOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Width for word wrapping. Defaults to 80.
|
|
124
|
+
*/
|
|
125
|
+
width?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Terminal background mode. Defaults to 'dark'.
|
|
128
|
+
*/
|
|
129
|
+
background?: TerminalBackground;
|
|
130
|
+
/**
|
|
131
|
+
* Environment adapter for detecting terminal capabilities.
|
|
132
|
+
*/
|
|
133
|
+
env?: EnvironmentAdapter;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Renders markdown content with terminal styling.
|
|
137
|
+
* Detects terminal background (light/dark) and applies appropriate styling.
|
|
138
|
+
*
|
|
139
|
+
* @param content - The markdown string to render
|
|
140
|
+
* @param options - Rendering options
|
|
141
|
+
* @returns The styled markdown output
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
declare function renderMarkdown(content: string, options?: RenderMarkdownOptions): string;
|
|
145
|
+
|
|
146
|
+
export { ErrorMsg, MarkdownModel, type MarkdownOptions, RenderMarkdownMsg, type RenderMarkdownOptions, renderMarkdown };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,146 @@
|
|
|
1
|
+
import { Style } from '@suds-cli/chapstick';
|
|
2
|
+
import { ViewportModel } from '@suds-cli/viewport';
|
|
3
|
+
import { Cmd, Msg } from '@suds-cli/tea';
|
|
4
|
+
import { FileSystemAdapter, TerminalBackground, EnvironmentAdapter } from '@suds-cli/machine';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
|
-
* Markdown viewer component
|
|
7
|
+
* Markdown viewer component.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for creating a markdown model.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
interface MarkdownOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Filesystem adapter for file operations.
|
|
17
|
+
*/
|
|
18
|
+
filesystem: FileSystemAdapter;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the component is active and should handle input.
|
|
21
|
+
* Defaults to true.
|
|
22
|
+
*/
|
|
23
|
+
active?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Initial width for the viewport.
|
|
26
|
+
* Defaults to 0.
|
|
27
|
+
*/
|
|
28
|
+
width?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Initial height for the viewport.
|
|
31
|
+
* Defaults to 0.
|
|
32
|
+
*/
|
|
33
|
+
height?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Style for the viewport.
|
|
36
|
+
*/
|
|
37
|
+
style?: Style;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Markdown viewer model that renders markdown files with terminal styling
|
|
41
|
+
* in a scrollable viewport.
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
declare class MarkdownModel {
|
|
45
|
+
readonly viewport: ViewportModel;
|
|
46
|
+
readonly active: boolean;
|
|
47
|
+
readonly fileName: string;
|
|
48
|
+
readonly filesystem: FileSystemAdapter;
|
|
49
|
+
private constructor();
|
|
50
|
+
/**
|
|
51
|
+
* Create a new markdown model.
|
|
52
|
+
* @param options - Configuration options
|
|
53
|
+
*/
|
|
54
|
+
static new(options: MarkdownOptions): MarkdownModel;
|
|
55
|
+
/**
|
|
56
|
+
* Tea init hook (no-op).
|
|
57
|
+
*/
|
|
58
|
+
init(): Cmd<Msg>;
|
|
59
|
+
/**
|
|
60
|
+
* Set the filename to render. Returns a command that will read and render the file.
|
|
61
|
+
* @param fileName - Path to the markdown file
|
|
62
|
+
*/
|
|
63
|
+
setFileName(fileName: string): [MarkdownModel, Cmd<Msg>];
|
|
64
|
+
/**
|
|
65
|
+
* Set the size of the viewport and re-render if a file is set.
|
|
66
|
+
* @param width - New width
|
|
67
|
+
* @param height - New height
|
|
68
|
+
*/
|
|
69
|
+
setSize(width: number, height: number): [MarkdownModel, Cmd<Msg>];
|
|
70
|
+
/**
|
|
71
|
+
* Set whether the component is active and should handle input.
|
|
72
|
+
* @param active - Active state
|
|
73
|
+
*/
|
|
74
|
+
setIsActive(active: boolean): MarkdownModel;
|
|
75
|
+
/**
|
|
76
|
+
* Scroll to the top of the viewport.
|
|
77
|
+
*/
|
|
78
|
+
gotoTop(): MarkdownModel;
|
|
79
|
+
/**
|
|
80
|
+
* Handle messages. Processes viewport scrolling and markdown rendering.
|
|
81
|
+
* @param msg - The message to handle
|
|
82
|
+
*/
|
|
83
|
+
update(msg: Msg): [MarkdownModel, Cmd<Msg>];
|
|
84
|
+
/**
|
|
85
|
+
* Render the markdown viewport.
|
|
86
|
+
*/
|
|
87
|
+
view(): string;
|
|
88
|
+
private with;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Message types for the markdown component.
|
|
93
|
+
*/
|
|
94
|
+
/**
|
|
95
|
+
* Message containing rendered markdown content.
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
declare class RenderMarkdownMsg {
|
|
99
|
+
readonly content: string;
|
|
100
|
+
readonly _tag = "markdown-render";
|
|
101
|
+
constructor(content: string);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Message containing an error from file reading or rendering.
|
|
105
|
+
* @public
|
|
106
|
+
*/
|
|
107
|
+
declare class ErrorMsg {
|
|
108
|
+
readonly error: Error;
|
|
109
|
+
readonly _tag = "markdown-error";
|
|
110
|
+
constructor(error: Error);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Markdown rendering utilities.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Options for rendering markdown.
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
interface RenderMarkdownOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Width for word wrapping. Defaults to 80.
|
|
124
|
+
*/
|
|
125
|
+
width?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Terminal background mode. Defaults to 'dark'.
|
|
128
|
+
*/
|
|
129
|
+
background?: TerminalBackground;
|
|
130
|
+
/**
|
|
131
|
+
* Environment adapter for detecting terminal capabilities.
|
|
132
|
+
*/
|
|
133
|
+
env?: EnvironmentAdapter;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Renders markdown content with terminal styling.
|
|
137
|
+
* Detects terminal background (light/dark) and applies appropriate styling.
|
|
3
138
|
*
|
|
4
|
-
* @
|
|
139
|
+
* @param content - The markdown string to render
|
|
140
|
+
* @param options - Rendering options
|
|
141
|
+
* @returns The styled markdown output
|
|
142
|
+
* @public
|
|
5
143
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
//# sourceMappingURL=index.d.ts.map
|
|
144
|
+
declare function renderMarkdown(content: string, options?: RenderMarkdownOptions): string;
|
|
145
|
+
|
|
146
|
+
export { ErrorMsg, MarkdownModel, type MarkdownOptions, RenderMarkdownMsg, type RenderMarkdownOptions, renderMarkdown };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,195 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { Style } from '@suds-cli/chapstick';
|
|
2
|
+
import { readFileContent } from '@suds-cli/filesystem';
|
|
3
|
+
import { ViewportModel } from '@suds-cli/viewport';
|
|
4
|
+
import { Marked } from 'marked';
|
|
5
|
+
import { markedTerminal } from 'marked-terminal';
|
|
6
|
+
import { createAlwaysEnabledStyle } from '@suds-cli/machine';
|
|
7
|
+
|
|
8
|
+
// src/model.ts
|
|
9
|
+
|
|
10
|
+
// src/messages.ts
|
|
11
|
+
var RenderMarkdownMsg = class {
|
|
12
|
+
constructor(content) {
|
|
13
|
+
this.content = content;
|
|
14
|
+
}
|
|
15
|
+
_tag = "markdown-render";
|
|
16
|
+
};
|
|
17
|
+
var ErrorMsg = class {
|
|
18
|
+
constructor(error) {
|
|
19
|
+
this.error = error;
|
|
20
|
+
}
|
|
21
|
+
_tag = "markdown-error";
|
|
22
|
+
};
|
|
23
|
+
function renderMarkdown(content, options = {}) {
|
|
24
|
+
const width = options.width ?? 80;
|
|
25
|
+
const background = options.background ?? options.env?.getTerminalBackground() ?? "dark";
|
|
26
|
+
const isDark = background !== "light";
|
|
27
|
+
const style = createAlwaysEnabledStyle();
|
|
28
|
+
const marked = new Marked(
|
|
29
|
+
markedTerminal({
|
|
30
|
+
// Wrap text at specified width
|
|
31
|
+
width,
|
|
32
|
+
reflowText: true,
|
|
33
|
+
// Headings - brighter on dark backgrounds
|
|
34
|
+
firstHeading: isDark ? style.cyan.bold : style.blue.bold,
|
|
35
|
+
heading: isDark ? style.cyan.bold : style.blue.bold,
|
|
36
|
+
// Code blocks
|
|
37
|
+
code: isDark ? style.white : style.gray,
|
|
38
|
+
blockquote: isDark ? style.white : style.gray,
|
|
39
|
+
// Emphasis
|
|
40
|
+
strong: style.bold,
|
|
41
|
+
em: style.italic,
|
|
42
|
+
// Lists
|
|
43
|
+
listitem: style,
|
|
44
|
+
// Links
|
|
45
|
+
link: isDark ? style.blueBright : style.blue,
|
|
46
|
+
// Other elements
|
|
47
|
+
hr: style.gray,
|
|
48
|
+
paragraph: style
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
try {
|
|
52
|
+
const rendered = marked.parse(content);
|
|
53
|
+
return rendered.trim();
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Failed to render markdown: ${error instanceof Error ? error.message : String(error)}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/model.ts
|
|
62
|
+
var MarkdownModel = class _MarkdownModel {
|
|
63
|
+
viewport;
|
|
64
|
+
active;
|
|
65
|
+
fileName;
|
|
66
|
+
filesystem;
|
|
67
|
+
constructor(options) {
|
|
68
|
+
this.viewport = options.viewport;
|
|
69
|
+
this.active = options.active;
|
|
70
|
+
this.fileName = options.fileName;
|
|
71
|
+
this.filesystem = options.filesystem;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a new markdown model.
|
|
75
|
+
* @param options - Configuration options
|
|
76
|
+
*/
|
|
77
|
+
static new(options) {
|
|
78
|
+
const viewport = ViewportModel.new({
|
|
79
|
+
width: options.width ?? 0,
|
|
80
|
+
height: options.height ?? 0,
|
|
81
|
+
style: options.style
|
|
82
|
+
});
|
|
83
|
+
return new _MarkdownModel({
|
|
84
|
+
viewport,
|
|
85
|
+
active: options.active ?? true,
|
|
86
|
+
fileName: "",
|
|
87
|
+
filesystem: options.filesystem
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Tea init hook (no-op).
|
|
92
|
+
*/
|
|
93
|
+
init() {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Set the filename to render. Returns a command that will read and render the file.
|
|
98
|
+
* @param fileName - Path to the markdown file
|
|
99
|
+
*/
|
|
100
|
+
setFileName(fileName) {
|
|
101
|
+
const updated = this.with({ fileName });
|
|
102
|
+
const cmd = renderMarkdownCmd(this.filesystem, this.viewport.width, fileName);
|
|
103
|
+
return [updated, cmd];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Set the size of the viewport and re-render if a file is set.
|
|
107
|
+
* @param width - New width
|
|
108
|
+
* @param height - New height
|
|
109
|
+
*/
|
|
110
|
+
setSize(width, height) {
|
|
111
|
+
const updatedViewport = this.viewport.setWidth(width).setHeight(height);
|
|
112
|
+
const updated = this.with({ viewport: updatedViewport });
|
|
113
|
+
if (this.fileName !== "") {
|
|
114
|
+
const cmd = renderMarkdownCmd(this.filesystem, width, this.fileName);
|
|
115
|
+
return [updated, cmd];
|
|
116
|
+
}
|
|
117
|
+
return [updated, null];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Set whether the component is active and should handle input.
|
|
121
|
+
* @param active - Active state
|
|
122
|
+
*/
|
|
123
|
+
setIsActive(active) {
|
|
124
|
+
if (active === this.active) return this;
|
|
125
|
+
return this.with({ active });
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Scroll to the top of the viewport.
|
|
129
|
+
*/
|
|
130
|
+
gotoTop() {
|
|
131
|
+
const updatedViewport = this.viewport.scrollToTop();
|
|
132
|
+
if (updatedViewport === this.viewport) return this;
|
|
133
|
+
return this.with({ viewport: updatedViewport });
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Handle messages. Processes viewport scrolling and markdown rendering.
|
|
137
|
+
* @param msg - The message to handle
|
|
138
|
+
*/
|
|
139
|
+
update(msg) {
|
|
140
|
+
if (msg instanceof RenderMarkdownMsg) {
|
|
141
|
+
const styled = new Style().width(this.viewport.width).alignHorizontal("left").render(msg.content);
|
|
142
|
+
const updatedViewport = this.viewport.setContent(styled);
|
|
143
|
+
return [this.with({ viewport: updatedViewport }), null];
|
|
144
|
+
}
|
|
145
|
+
if (msg instanceof ErrorMsg) {
|
|
146
|
+
const errorContent = msg.error.message;
|
|
147
|
+
const updatedViewport = this.viewport.setContent(errorContent);
|
|
148
|
+
return [
|
|
149
|
+
this.with({
|
|
150
|
+
fileName: "",
|
|
151
|
+
viewport: updatedViewport
|
|
152
|
+
}),
|
|
153
|
+
null
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
if (this.active) {
|
|
157
|
+
const [updatedViewport, cmd] = this.viewport.update(msg);
|
|
158
|
+
if (updatedViewport !== this.viewport) {
|
|
159
|
+
return [this.with({ viewport: updatedViewport }), cmd];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return [this, null];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Render the markdown viewport.
|
|
166
|
+
*/
|
|
167
|
+
view() {
|
|
168
|
+
return this.viewport.view();
|
|
169
|
+
}
|
|
170
|
+
with(patch) {
|
|
171
|
+
return new _MarkdownModel({
|
|
172
|
+
viewport: patch.viewport ?? this.viewport,
|
|
173
|
+
active: patch.active ?? this.active,
|
|
174
|
+
fileName: patch.fileName ?? this.fileName,
|
|
175
|
+
filesystem: patch.filesystem ?? this.filesystem
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
function renderMarkdownCmd(fs, width, fileName) {
|
|
180
|
+
return async () => {
|
|
181
|
+
try {
|
|
182
|
+
const content = await readFileContent(fs, fileName);
|
|
183
|
+
const rendered = renderMarkdown(content, { width });
|
|
184
|
+
return new RenderMarkdownMsg(rendered);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return new ErrorMsg(
|
|
187
|
+
error instanceof Error ? error : new Error(String(error))
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export { ErrorMsg, MarkdownModel, RenderMarkdownMsg, renderMarkdown };
|
|
194
|
+
//# sourceMappingURL=index.js.map
|
|
9
195
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"sources":["../src/messages.ts","../src/renderer.ts","../src/model.ts"],"names":[],"mappings":";;;;;;;;;;AAQO,IAAM,oBAAN,MAAwB;AAAA,EAG7B,YAA4B,OAAA,EAAiB;AAAjB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAkB;AAAA,EAFrC,IAAA,GAAO,iBAAA;AAGlB;AAMO,IAAM,WAAN,MAAe;AAAA,EAGpB,YAA4B,KAAA,EAAc;AAAd,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAe;AAAA,EAFlC,IAAA,GAAO,gBAAA;AAGlB;ACeO,SAAS,cAAA,CACd,OAAA,EACA,OAAA,GAAiC,EAAC,EAC1B;AACR,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,EAAA;AAC/B,EAAA,MAAM,aAAa,OAAA,CAAQ,UAAA,IAAc,OAAA,CAAQ,GAAA,EAAK,uBAAsB,IAAK,MAAA;AAGjF,EAAA,MAAM,SAAS,UAAA,KAAe,OAAA;AAG9B,EAAA,MAAM,QAAQ,wBAAA,EAAyB;AAGvC,EAAA,MAAM,SAAS,IAAI,MAAA;AAAA,IACjB,cAAA,CAAe;AAAA;AAAA,MAEb,KAAA;AAAA,MACA,UAAA,EAAY,IAAA;AAAA;AAAA,MAEZ,cAAc,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA;AAAA,MACpD,SAAS,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA;AAAA;AAAA,MAE/C,IAAA,EAAM,MAAA,GAAS,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,IAAA;AAAA,MACnC,UAAA,EAAY,MAAA,GAAS,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,IAAA;AAAA;AAAA,MAEzC,QAAQ,KAAA,CAAM,IAAA;AAAA,MACd,IAAI,KAAA,CAAM,MAAA;AAAA;AAAA,MAEV,QAAA,EAAU,KAAA;AAAA;AAAA,MAEV,IAAA,EAAM,MAAA,GAAS,KAAA,CAAM,UAAA,GAAa,KAAA,CAAM,IAAA;AAAA;AAAA,MAExC,IAAI,KAAA,CAAM,IAAA;AAAA,MACV,SAAA,EAAW;AAAA,KACZ;AAAA,GACH;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA;AACrC,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,8BAA8B,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,KACtF;AAAA,EACF;AACF;;;ACpCO,IAAM,aAAA,GAAN,MAAM,cAAA,CAAc;AAAA,EAChB,QAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EAED,YAAY,OAAA,EAKjB;AACD,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AACxB,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AACxB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,IAAI,OAAA,EAAyC;AAClD,IAAA,MAAM,QAAA,GAAW,cAAc,GAAA,CAAI;AAAA,MACjC,KAAA,EAAO,QAAQ,KAAA,IAAS,CAAA;AAAA,MACxB,MAAA,EAAQ,QAAQ,MAAA,IAAU,CAAA;AAAA,MAC1B,OAAO,OAAA,CAAQ;AAAA,KAChB,CAAA;AAED,IAAA,OAAO,IAAI,cAAA,CAAc;AAAA,MACvB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAQ,MAAA,IAAU,IAAA;AAAA,MAC1B,QAAA,EAAU,EAAA;AAAA,MACV,YAAY,OAAA,CAAQ;AAAA,KACrB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,GAAiB;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,QAAA,EAA6C;AACvD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,EAAE,UAAU,CAAA;AACtC,IAAA,MAAM,MAAM,iBAAA,CAAkB,IAAA,CAAK,YAAY,IAAA,CAAK,QAAA,CAAS,OAAO,QAAQ,CAAA;AAC5E,IAAA,OAAO,CAAC,SAAS,GAAG,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAA,CAAQ,OAAe,MAAA,EAA2C;AAChE,IAAA,MAAM,kBAAkB,IAAA,CAAK,QAAA,CAAS,SAAS,KAAK,CAAA,CAAE,UAAU,MAAM,CAAA;AACtE,IAAA,MAAM,UAAU,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,iBAAiB,CAAA;AAEvD,IAAA,IAAI,IAAA,CAAK,aAAa,EAAA,EAAI;AACxB,MAAA,MAAM,MAAM,iBAAA,CAAkB,IAAA,CAAK,UAAA,EAAY,KAAA,EAAO,KAAK,QAAQ,CAAA;AACnE,MAAA,OAAO,CAAC,SAAS,GAAG,CAAA;AAAA,IACtB;AAEA,IAAA,OAAO,CAAC,SAAS,IAAI,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,MAAA,EAAgC;AAC1C,IAAA,IAAI,MAAA,KAAW,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA;AACnC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAyB;AACvB,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,QAAA,CAAS,WAAA,EAAY;AAClD,IAAA,IAAI,eAAA,KAAoB,IAAA,CAAK,QAAA,EAAU,OAAO,IAAA;AAC9C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,iBAAiB,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,GAAA,EAAqC;AAE1C,IAAA,IAAI,eAAe,iBAAA,EAAmB;AAGpC,MAAA,MAAM,MAAA,GAAS,IAAI,KAAA,EAAM,CACtB,MAAM,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,CACzB,eAAA,CAAgB,MAAM,CAAA,CACtB,MAAA,CAAO,IAAI,OAAO,CAAA;AAErB,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA;AACvD,MAAA,OAAO,CAAC,KAAK,IAAA,CAAK,EAAE,UAAU,eAAA,EAAiB,GAAG,IAAI,CAAA;AAAA,IACxD;AAGA,IAAA,IAAI,eAAe,QAAA,EAAU;AAC3B,MAAA,MAAM,YAAA,GAAe,IAAI,KAAA,CAAM,OAAA;AAC/B,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,YAAY,CAAA;AAC7D,MAAA,OAAO;AAAA,QACL,KAAK,IAAA,CAAK;AAAA,UACR,QAAA,EAAU,EAAA;AAAA,UACV,QAAA,EAAU;AAAA,SACX,CAAA;AAAA,QACD;AAAA,OACF;AAAA,IACF;AAGA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,CAAC,eAAA,EAAiB,GAAG,IAAI,IAAA,CAAK,QAAA,CAAS,OAAO,GAAG,CAAA;AACvD,MAAA,IAAI,eAAA,KAAoB,KAAK,QAAA,EAAU;AACrC,QAAA,OAAO,CAAC,KAAK,IAAA,CAAK,EAAE,UAAU,eAAA,EAAiB,GAAG,GAAG,CAAA;AAAA,MACvD;AAAA,IACF;AAEA,IAAA,OAAO,CAAC,MAAM,IAAI,CAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,GAAe;AACb,IAAA,OAAO,IAAA,CAAK,SAAS,IAAA,EAAK;AAAA,EAC5B;AAAA,EAEQ,KAAK,KAAA,EAA8C;AACzD,IAAA,OAAO,IAAI,cAAA,CAAc;AAAA,MACvB,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,MACjC,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,MAC7B,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,MACjC,UAAA,EAAY,KAAA,CAAM,UAAA,IAAc,IAAA,CAAK;AAAA,KACtC,CAAA;AAAA,EACH;AACF;AAKA,SAAS,iBAAA,CACP,EAAA,EACA,KAAA,EACA,QAAA,EACU;AACV,EAAA,OAAO,YAAY;AACjB,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,EAAA,EAAI,QAAQ,CAAA;AAClD,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,OAAA,EAAS,EAAE,OAAO,CAAA;AAClD,MAAA,OAAO,IAAI,kBAAkB,QAAQ,CAAA;AAAA,IACvC,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,IAAI,QAAA;AAAA,QACT,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,OAC1D;AAAA,IACF;AAAA,EACF,CAAA;AACF","file":"index.js","sourcesContent":["/**\n * Message types for the markdown component.\n */\n\n/**\n * Message containing rendered markdown content.\n * @public\n */\nexport class RenderMarkdownMsg {\n readonly _tag = 'markdown-render'\n\n constructor(public readonly content: string) {}\n}\n\n/**\n * Message containing an error from file reading or rendering.\n * @public\n */\nexport class ErrorMsg {\n readonly _tag = 'markdown-error'\n\n constructor(public readonly error: Error) {}\n}\n","/**\n * Markdown rendering utilities.\n */\n\nimport { Marked } from 'marked'\nimport { markedTerminal } from 'marked-terminal'\nimport type { EnvironmentAdapter, TerminalBackground } from '@suds-cli/machine'\nimport { createAlwaysEnabledStyle } from '@suds-cli/machine'\n\n/**\n * Options for rendering markdown.\n * @public\n */\nexport interface RenderMarkdownOptions {\n /**\n * Width for word wrapping. Defaults to 80.\n */\n width?: number\n /**\n * Terminal background mode. Defaults to 'dark'.\n */\n background?: TerminalBackground\n /**\n * Environment adapter for detecting terminal capabilities.\n */\n env?: EnvironmentAdapter\n}\n\n/**\n * Renders markdown content with terminal styling.\n * Detects terminal background (light/dark) and applies appropriate styling.\n *\n * @param content - The markdown string to render\n * @param options - Rendering options\n * @returns The styled markdown output\n * @public\n */\nexport function renderMarkdown(\n content: string,\n options: RenderMarkdownOptions = {},\n): string {\n const width = options.width ?? 80\n const background = options.background ?? options.env?.getTerminalBackground() ?? 'dark'\n\n // Use appropriate colors for terminal background\n const isDark = background !== 'light'\n\n // Create a style function with full color support for markdown rendering\n const style = createAlwaysEnabledStyle()\n\n // Create marked instance with terminal renderer\n const marked = new Marked(\n markedTerminal({\n // Wrap text at specified width\n width,\n reflowText: true,\n // Headings - brighter on dark backgrounds\n firstHeading: isDark ? style.cyan.bold : style.blue.bold,\n heading: isDark ? style.cyan.bold : style.blue.bold,\n // Code blocks\n code: isDark ? style.white : style.gray,\n blockquote: isDark ? style.white : style.gray,\n // Emphasis\n strong: style.bold,\n em: style.italic,\n // Lists\n listitem: style,\n // Links\n link: isDark ? style.blueBright : style.blue,\n // Other elements\n hr: style.gray,\n paragraph: style,\n }),\n )\n\n try {\n const rendered = marked.parse(content) as string\n return rendered.trim()\n } catch (error) {\n throw new Error(\n `Failed to render markdown: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n}\n","/**\n * Markdown viewer component.\n */\n\nimport { Style } from '@suds-cli/chapstick'\nimport { readFileContent } from '@suds-cli/filesystem'\nimport { ViewportModel } from '@suds-cli/viewport'\nimport type { Cmd, Msg } from '@suds-cli/tea'\nimport type { FileSystemAdapter } from '@suds-cli/machine'\nimport { RenderMarkdownMsg, ErrorMsg } from './messages.js'\nimport { renderMarkdown } from './renderer.js'\n\n/**\n * Options for creating a markdown model.\n * @public\n */\nexport interface MarkdownOptions {\n /**\n * Filesystem adapter for file operations.\n */\n filesystem: FileSystemAdapter\n /**\n * Whether the component is active and should handle input.\n * Defaults to true.\n */\n active?: boolean\n /**\n * Initial width for the viewport.\n * Defaults to 0.\n */\n width?: number\n /**\n * Initial height for the viewport.\n * Defaults to 0.\n */\n height?: number\n /**\n * Style for the viewport.\n */\n style?: Style\n}\n\n/**\n * Markdown viewer model that renders markdown files with terminal styling\n * in a scrollable viewport.\n * @public\n */\nexport class MarkdownModel {\n readonly viewport: ViewportModel\n readonly active: boolean\n readonly fileName: string\n readonly filesystem: FileSystemAdapter\n\n private constructor(options: {\n viewport: ViewportModel\n active: boolean\n fileName: string\n filesystem: FileSystemAdapter\n }) {\n this.viewport = options.viewport\n this.active = options.active\n this.fileName = options.fileName\n this.filesystem = options.filesystem\n }\n\n /**\n * Create a new markdown model.\n * @param options - Configuration options\n */\n static new(options: MarkdownOptions): MarkdownModel {\n const viewport = ViewportModel.new({\n width: options.width ?? 0,\n height: options.height ?? 0,\n style: options.style,\n })\n\n return new MarkdownModel({\n viewport,\n active: options.active ?? true,\n fileName: '',\n filesystem: options.filesystem,\n })\n }\n\n /**\n * Tea init hook (no-op).\n */\n init(): Cmd<Msg> {\n return null\n }\n\n /**\n * Set the filename to render. Returns a command that will read and render the file.\n * @param fileName - Path to the markdown file\n */\n setFileName(fileName: string): [MarkdownModel, Cmd<Msg>] {\n const updated = this.with({ fileName })\n const cmd = renderMarkdownCmd(this.filesystem, this.viewport.width, fileName)\n return [updated, cmd]\n }\n\n /**\n * Set the size of the viewport and re-render if a file is set.\n * @param width - New width\n * @param height - New height\n */\n setSize(width: number, height: number): [MarkdownModel, Cmd<Msg>] {\n const updatedViewport = this.viewport.setWidth(width).setHeight(height)\n const updated = this.with({ viewport: updatedViewport })\n\n if (this.fileName !== '') {\n const cmd = renderMarkdownCmd(this.filesystem, width, this.fileName)\n return [updated, cmd]\n }\n\n return [updated, null]\n }\n\n /**\n * Set whether the component is active and should handle input.\n * @param active - Active state\n */\n setIsActive(active: boolean): MarkdownModel {\n if (active === this.active) return this\n return this.with({ active })\n }\n\n /**\n * Scroll to the top of the viewport.\n */\n gotoTop(): MarkdownModel {\n const updatedViewport = this.viewport.scrollToTop()\n if (updatedViewport === this.viewport) return this\n return this.with({ viewport: updatedViewport })\n }\n\n /**\n * Handle messages. Processes viewport scrolling and markdown rendering.\n * @param msg - The message to handle\n */\n update(msg: Msg): [MarkdownModel, Cmd<Msg>] {\n // Handle markdown rendering\n if (msg instanceof RenderMarkdownMsg) {\n // Apply width for word wrapping and left-align to pad lines to consistent width\n // Viewport handles height/scrolling\n const styled = new Style()\n .width(this.viewport.width)\n .alignHorizontal('left')\n .render(msg.content)\n\n const updatedViewport = this.viewport.setContent(styled)\n return [this.with({ viewport: updatedViewport }), null]\n }\n\n // Handle errors\n if (msg instanceof ErrorMsg) {\n const errorContent = msg.error.message\n const updatedViewport = this.viewport.setContent(errorContent)\n return [\n this.with({\n fileName: '',\n viewport: updatedViewport,\n }),\n null,\n ]\n }\n\n // Handle viewport updates if active\n if (this.active) {\n const [updatedViewport, cmd] = this.viewport.update(msg)\n if (updatedViewport !== this.viewport) {\n return [this.with({ viewport: updatedViewport }), cmd]\n }\n }\n\n return [this, null]\n }\n\n /**\n * Render the markdown viewport.\n */\n view(): string {\n return this.viewport.view()\n }\n\n private with(patch: Partial<MarkdownModel>): MarkdownModel {\n return new MarkdownModel({\n viewport: patch.viewport ?? this.viewport,\n active: patch.active ?? this.active,\n fileName: patch.fileName ?? this.fileName,\n filesystem: patch.filesystem ?? this.filesystem,\n })\n }\n}\n\n/**\n * Command to read and render a markdown file.\n */\nfunction renderMarkdownCmd(\n fs: FileSystemAdapter,\n width: number,\n fileName: string,\n): Cmd<Msg> {\n return async () => {\n try {\n const content = await readFileContent(fs, fileName)\n const rendered = renderMarkdown(content, { width })\n return new RenderMarkdownMsg(rendered)\n } catch (error) {\n return new ErrorMsg(\n error instanceof Error ? error : new Error(String(error)),\n )\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,36 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suds-cli/markdown",
|
|
3
|
-
"version": "0.1.0-alpha.0",
|
|
4
3
|
"description": "Markdown viewer component for Suds terminal UIs",
|
|
5
|
-
"
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
4
|
+
"version": "0.1.0-alpha.1",
|
|
11
5
|
"dependencies": {
|
|
12
|
-
"chalk": "^5.4.1",
|
|
13
6
|
"marked": "^15.0.0",
|
|
14
7
|
"marked-terminal": "^7.3.0",
|
|
15
|
-
"@suds-cli/chapstick": "0.1.0-alpha.
|
|
16
|
-
"@suds-cli/filesystem": "0.0.0",
|
|
17
|
-
"@suds-cli/
|
|
18
|
-
"@suds-cli/
|
|
8
|
+
"@suds-cli/chapstick": "0.1.0-alpha.1",
|
|
9
|
+
"@suds-cli/filesystem": "0.1.0-alpha.0",
|
|
10
|
+
"@suds-cli/machine": "0.1.0-alpha.0",
|
|
11
|
+
"@suds-cli/tea": "0.1.0-alpha.0",
|
|
12
|
+
"@suds-cli/viewport": "0.1.0-alpha.1"
|
|
19
13
|
},
|
|
20
14
|
"devDependencies": {
|
|
21
15
|
"typescript": "5.8.2",
|
|
22
|
-
"vitest": "^4.0.
|
|
16
|
+
"vitest": "^4.0.16"
|
|
23
17
|
},
|
|
24
18
|
"engines": {
|
|
25
19
|
"node": ">=20.0.0"
|
|
26
20
|
},
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"require": {
|
|
28
|
+
"types": "./dist/index.d.cts",
|
|
29
|
+
"default": "./dist/index.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"main": "./dist/index.cjs",
|
|
38
|
+
"module": "./dist/index.js",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"types": "./dist/index.d.ts",
|
|
27
41
|
"scripts": {
|
|
28
|
-
"
|
|
29
|
-
"build": "pnpm run clean && tsc -p ./tsconfig.json",
|
|
30
|
-
"test": "vitest run",
|
|
31
|
-
"generate:api-report": "api-extractor run --local",
|
|
42
|
+
"build": "tsup",
|
|
32
43
|
"check:api-report": "pnpm run generate:api-report",
|
|
33
44
|
"check:eslint": "pnpm run lint",
|
|
34
|
-
"
|
|
45
|
+
"generate:api-report": "api-extractor run --local",
|
|
46
|
+
"lint": "eslint \"{src,test}/**/*.{ts,tsx}\"",
|
|
47
|
+
"test": "vitest run"
|
|
35
48
|
}
|
|
36
49
|
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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/messages.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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
|
package/dist/messages.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/messages.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
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
|
package/dist/messages.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/model.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
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
|
package/dist/model.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
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
|
package/dist/model.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
|
package/dist/renderer.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
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
|
package/dist/renderer.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/renderer.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
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
|
package/dist/renderer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|