@minjun0219/mdwire 0.1.10 → 0.1.11
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 +20 -6
- package/bundler/mdwire.d.ts +42 -39
- package/bundler/mdwire_bg.js +51 -48
- package/bundler/mdwire_bg.wasm +0 -0
- package/js/events.d.ts +5 -5
- package/js/events.js +2 -2
- package/js/react.d.ts +10 -10
- package/js/react.js +15 -14
- package/node/mdwire.d.ts +42 -39
- package/node/mdwire.js +51 -48
- package/node/mdwire_bg.wasm +0 -0
- package/package.json +3 -3
package/js/react.d.ts
CHANGED
|
@@ -2,32 +2,32 @@ import type { ElementType, ReactElement, ReactNode } from "react";
|
|
|
2
2
|
import type { MdTag } from "./events.js";
|
|
3
3
|
import type { RenderOptions } from "@minjun0219/mdwire";
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/** Components that replace individual tags, e.g. `{ a: MyLink, code: CodeBlock }`. Each receives that tag's props. */
|
|
6
6
|
export type MdComponents = Partial<Record<MdTag, ElementType>>;
|
|
7
7
|
|
|
8
8
|
export interface MarkdownProps {
|
|
9
|
-
/**
|
|
9
|
+
/** Markdown written by the agent (complete text). For streaming, use `Streamer` + `toElements`; passing the accumulated output each time reconverts it from scratch. */
|
|
10
10
|
text: string;
|
|
11
11
|
components?: MdComponents;
|
|
12
|
-
/**
|
|
12
|
+
/** Options passed to the core. The `html` policy (line breaks, images, schemes) goes here. */
|
|
13
13
|
options?: RenderOptions;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
/**
|
|
16
|
+
/** Renders markdown as React elements. Does not use innerHTML. */
|
|
17
17
|
export function Markdown(props: MarkdownProps): ReactElement;
|
|
18
18
|
|
|
19
19
|
export interface MarkdownStreamOptions {
|
|
20
20
|
components?: MdComponents;
|
|
21
21
|
options?: RenderOptions;
|
|
22
|
-
/**
|
|
22
|
+
/** Also draw what is held back (open emphasis, table rows, code spans) ahead of time. Default `true`. With `false`, only final output is shown. */
|
|
23
23
|
eager?: boolean;
|
|
24
|
-
/**
|
|
24
|
+
/** Called when done. `revised` tells whether the final output differs from the last screen; if false, the hook does not redraw. */
|
|
25
25
|
onSettled?: (html: string, revised: boolean) => void;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
* `onSettled`
|
|
29
|
+
* Hook for streaming: call `push` for each token and `finish` at the end. By default it also draws what is held back (`eager`).
|
|
30
|
+
* Options other than `onSettled` are read only once, on first render.
|
|
31
31
|
*/
|
|
32
32
|
export function useMarkdownStream(opts?: MarkdownStreamOptions): {
|
|
33
33
|
elements: ReactElement;
|
|
@@ -35,6 +35,6 @@ export function useMarkdownStream(opts?: MarkdownStreamOptions): {
|
|
|
35
35
|
finish(): void;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
/** html
|
|
39
|
-
/** `schemes`
|
|
38
|
+
/** Converts html channel output (when streaming, the accumulated output + `preview()` or `closeOpen()`) into React nodes. */
|
|
39
|
+
/** Pass the same `schemes` you gave the core as `options.html.schemes`. Default `["http", "https", "mailto"]`. */
|
|
40
40
|
export function toElements(html: string, components?: MdComponents, schemes?: string[]): ReactNode[];
|
package/js/react.js
CHANGED
|
@@ -40,11 +40,11 @@ function propsOf(tag, attrs, key, schemes) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* html
|
|
44
|
-
* `toElements(acc + streamer.closeOpen())`.
|
|
43
|
+
* Converts html channel output into an array of React nodes. Use it when you handle the
|
|
44
|
+
* accumulated stream output yourself: `toElements(acc + streamer.closeOpen())`.
|
|
45
45
|
* @param {string} html
|
|
46
|
-
* @param {Partial<Record<string, import("react").ElementType>>} [components]
|
|
47
|
-
* @param {string[]} [schemes]
|
|
46
|
+
* @param {Partial<Record<string, import("react").ElementType>>} [components] Components that replace individual tags.
|
|
47
|
+
* @param {string[]} [schemes] Schemes allowed for links and images. Same as the `options.html.schemes` given to the core.
|
|
48
48
|
*/
|
|
49
49
|
export function toElements(html, components = {}, schemes = DEFAULT_SCHEMES) {
|
|
50
50
|
const root = { tag: null, children: [] };
|
|
@@ -84,9 +84,9 @@ export function toElements(html, components = {}, schemes = DEFAULT_SCHEMES) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* Renders agent markdown, for complete text. If you pass the accumulated stream on every token,
|
|
88
|
+
* it reconverts from scratch each time, so total cost grows quadratically, and half-written markers
|
|
89
|
+
* (`**bo`, an opening backtick, `##`) briefly show up as text and then vanish. For streaming, use [`useMarkdownStream`].
|
|
90
90
|
* @param {import("./react.d.ts").MarkdownProps} props
|
|
91
91
|
*/
|
|
92
92
|
export function Markdown({ text, components, options }) {
|
|
@@ -95,15 +95,16 @@ export function Markdown({ text, components, options }) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Hook for streaming. Call `push(chunk)` as tokens arrive and `finish()` at the end.
|
|
99
99
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
100
|
+
* By default (`eager: true`) it **also draws what is held back**: open emphasis closed, tables with
|
|
101
|
+
* the rows received so far, code spans closed (`Streamer.preview()`). This is a guess, so later tokens
|
|
102
|
+
* may change the shape, but the final output matches a one-shot conversion. With `eager: false`, only
|
|
103
|
+
* final output is shown (append-only, SPEC 8.2): unmatched emphasis and prefixes not yet decided
|
|
104
|
+
* appear once they become final.
|
|
104
105
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
106
|
+
* At the end it calls `onSettled(html, revised)`. `revised` tells whether the final output differs
|
|
107
|
+
* from what was last **drawn on screen**. If they match, the hook does not redraw.
|
|
107
108
|
* @param {import("./react.d.ts").MarkdownStreamOptions} [opts]
|
|
108
109
|
*/
|
|
109
110
|
export function useMarkdownStream({ components, options, eager = true, onSettled } = {}) {
|
package/node/mdwire.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/** Conversion options. Anything omitted uses the channel's default. */
|
|
5
5
|
export interface RenderOptions {
|
|
6
|
-
/**
|
|
6
|
+
/** Part size limit (in characters). Defaults to the channel's limit; for example, 4096 when sending plain to Telegram. Streaming does not split. */
|
|
7
7
|
limit?: number;
|
|
8
|
-
/**
|
|
8
|
+
/** Policy for the browser channel ("html"). The defaults are the most conservative. */
|
|
9
9
|
html?: {
|
|
10
|
-
/**
|
|
10
|
+
/** Line breaks inside a block. "br" (default) emits `<br>`; "space" lets the browser collapse them into spaces. */
|
|
11
11
|
lineBreaks?: "br" | "space";
|
|
12
|
-
/**
|
|
12
|
+
/** Images. "link" (default) loads nothing until clicked; "load" emits `<img>`. */
|
|
13
13
|
images?: "link" | "load";
|
|
14
|
-
/**
|
|
14
|
+
/** Schemes allowed in link and image URLs (without the colon). If given, only these are allowed. Default ["http","https","mailto"]. */
|
|
15
15
|
schemes?: string[];
|
|
16
16
|
};
|
|
17
17
|
}
|
|
@@ -19,133 +19,136 @@ export interface RenderOptions {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* `renderWithReport
|
|
22
|
+
* The result of `renderWithReport`.
|
|
23
23
|
*/
|
|
24
24
|
export class Rendered {
|
|
25
25
|
private constructor();
|
|
26
26
|
free(): void;
|
|
27
27
|
[Symbol.dispose](): void;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* The parts. Just one if the text fit within the limit.
|
|
30
30
|
*/
|
|
31
31
|
readonly parts: string[];
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* What normalization repaired.
|
|
34
34
|
*/
|
|
35
35
|
readonly repairs: Repairs;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Counts of what normalization repaired and what was changed to fit the channel.
|
|
40
40
|
*/
|
|
41
41
|
export class Repairs {
|
|
42
42
|
private constructor();
|
|
43
43
|
free(): void;
|
|
44
44
|
[Symbol.dispose](): void;
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* Emphasis left open at the end of a block, closed for you.
|
|
47
47
|
*/
|
|
48
48
|
closedEmphasis: number;
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* Code fences left open at the end of the document, closed for you.
|
|
51
51
|
*/
|
|
52
52
|
closedFence: number;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Emphasis markers and `<url|text>` links rewritten in a different notation.
|
|
55
55
|
*/
|
|
56
56
|
convertedMarker: number;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* Unmatched `**` markers that were dropped.
|
|
59
59
|
*/
|
|
60
60
|
droppedMarker: number;
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Characters escaped because the channel would read them as syntax (GitHub's `\~`, `\<`, `\*`).
|
|
63
63
|
*/
|
|
64
64
|
escapedChar: number;
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* Unmatched backtick runs, turned back into literal text.
|
|
67
67
|
*/
|
|
68
68
|
revertedCodeSpan: number;
|
|
69
69
|
/**
|
|
70
|
-
*
|
|
70
|
+
* List bullets rewritten with a different symbol.
|
|
71
71
|
*/
|
|
72
72
|
rewrittenBullet: number;
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
74
|
+
* Tables rewritten in a different shape from the source.
|
|
75
75
|
*/
|
|
76
76
|
rewrittenTable: number;
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Raw HTML stripped from the source (tags, comments, and `<br>` turned into line breaks).
|
|
79
79
|
*/
|
|
80
80
|
strippedHtml: number;
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
82
|
+
* Emphasis emitted differently because the channel would not read the marker in that position (GitHub's `<strong>`, Slack's U+2060).
|
|
83
83
|
*/
|
|
84
84
|
tagEmphasis: number;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
88
|
+
* Streaming converter.
|
|
89
89
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
90
|
+
* Push a chunk and it returns only what is safe to emit now. Markup cut off at the
|
|
91
|
+
* chunk boundary stays inside. This is what you want when appending tokens to the
|
|
92
|
+
* screen as they arrive.
|
|
92
93
|
*/
|
|
93
94
|
export class Streamer {
|
|
94
95
|
free(): void;
|
|
95
96
|
[Symbol.dispose](): void;
|
|
96
97
|
/**
|
|
97
|
-
*
|
|
98
|
+
* **To send what you have received so far as is, append this after it.**
|
|
98
99
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
100
|
+
* It does not touch the state, so streaming continues afterwards. Do not add it
|
|
101
|
+
* to the accumulated output itself; append it only right before sending. Use it
|
|
102
|
+
* when editing a message as tokens arrive.
|
|
101
103
|
*
|
|
102
104
|
* ```js
|
|
103
105
|
* acc += s.push(chunk);
|
|
104
|
-
* await edit(acc + s.closeOpen()); //
|
|
106
|
+
* await edit(acc + s.closeOpen()); // leave acc unchanged
|
|
105
107
|
* ```
|
|
106
108
|
*/
|
|
107
109
|
closeOpen(): string;
|
|
108
110
|
/**
|
|
109
|
-
*
|
|
111
|
+
* Input has ended. Emits what is left and closes open markup.
|
|
110
112
|
*/
|
|
111
113
|
finish(): string;
|
|
112
114
|
constructor(channel: string, options?: RenderOptions | null);
|
|
113
115
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
116
|
+
* **The tail that would follow the final output if input ended now.** It goes in the
|
|
117
|
+
* same place as `closeOpen`, but also draws what is being held back (open emphasis,
|
|
118
|
+
* table rows, code spans). This is the default when you redraw the whole message.
|
|
119
|
+
* It is a guess, so later chunks may change the shape. Check `revised()` after the end.
|
|
117
120
|
*
|
|
118
121
|
* ```js
|
|
119
122
|
* acc += s.push(chunk);
|
|
120
|
-
* await edit(acc + s.preview()); //
|
|
123
|
+
* await edit(acc + s.preview()); // call only when drawing (costs as much as the open block)
|
|
121
124
|
* acc += s.finish();
|
|
122
|
-
* if (s.revised()) await edit(acc); //
|
|
125
|
+
* if (s.revised()) await edit(acc); // skip if the last screen already is the final output
|
|
123
126
|
* ```
|
|
124
127
|
*/
|
|
125
128
|
preview(): string;
|
|
126
129
|
push(chunk: string): string;
|
|
127
130
|
/**
|
|
128
|
-
*
|
|
131
|
+
* What normalization has repaired so far. After `finish`, this covers the whole document.
|
|
129
132
|
*/
|
|
130
133
|
repairs(): Repairs;
|
|
131
134
|
/**
|
|
132
|
-
*
|
|
135
|
+
* Whether the final output differs from the last `preview()`. Check it after `finish`.
|
|
133
136
|
*/
|
|
134
137
|
revised(): boolean;
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
/**
|
|
138
|
-
*
|
|
141
|
+
* The channel's length limit (in characters). Exposed for callers that handle parts themselves.
|
|
139
142
|
*/
|
|
140
143
|
export function limit(channel: string): number;
|
|
141
144
|
|
|
142
145
|
/**
|
|
143
|
-
*
|
|
146
|
+
* Converts a complete document. Returns an array of parts; it has more than one when the text exceeds the limit.
|
|
144
147
|
*/
|
|
145
148
|
export function render(input: string, channel: string, options?: RenderOptions | null): string[];
|
|
146
149
|
|
|
147
150
|
/**
|
|
148
|
-
* [`render`]
|
|
149
|
-
*
|
|
151
|
+
* Like [`render`], but also returns **what normalization repaired**. Use it to log
|
|
152
|
+
* how often the model breaks formatting.
|
|
150
153
|
*/
|
|
151
154
|
export function renderWithReport(input: string, channel: string, options?: RenderOptions | null): Rendered;
|