@byteatatime/mdstream 0.0.2 → 0.0.3

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +47 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byteatatime/mdstream",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "module": "src/index.ts",
5
5
  "types": "src/index.ts",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -3,6 +3,28 @@ import remarkParse from "remark-parse";
3
3
  import type { Node, Root } from "mdast";
4
4
  import type { PluggableList } from "unified";
5
5
 
6
+ /**
7
+ * A function that fixes up incomplete markdown syntax so it renders correctly.
8
+ * Applied only to the pending (active) block — finalized blocks are never mended.
9
+ *
10
+ * The `remend` package is the recommended choice:
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import remend from "remend";
15
+ * const parser = createStreamingParser({ mend: remend });
16
+ * ```
17
+ *
18
+ * @example With options:
19
+ * ```ts
20
+ * import remend from "remend";
21
+ * const parser = createStreamingParser({
22
+ * mend: (source) => remend(source, { links: false }),
23
+ * });
24
+ * ```
25
+ */
26
+ type MendFunction = (source: string) => string;
27
+
6
28
  type Block = {
7
29
  readonly ast: Node;
8
30
  readonly start: number;
@@ -18,10 +40,21 @@ type ParserState = {
18
40
 
19
41
  type ParserOptions = {
20
42
  plugins?: PluggableList;
43
+ /**
44
+ * A mending function that fixes incomplete markdown syntax in the active block.
45
+ * Only applied to the pending block — finalized blocks are never touched.
46
+ *
47
+ * The `remend` package is the recommended mending function:
48
+ * ```ts
49
+ * import remend from "remend";
50
+ * const parser = createStreamingParser({ mend: remend });
51
+ * ```
52
+ */
53
+ mend?: MendFunction;
21
54
  };
22
55
 
23
56
  const createStreamingParser = (options: ParserOptions = {}) => {
24
- const { plugins = [] } = options;
57
+ const { plugins = [], mend } = options;
25
58
  const state: ParserState = {
26
59
  buffer: "",
27
60
  finalizedBlocks: [],
@@ -60,10 +93,12 @@ const createStreamingParser = (options: ParserOptions = {}) => {
60
93
  const secondToLastPosition = secondToLastNode?.position;
61
94
  const lastPosition = lastNode?.position;
62
95
 
63
- if (secondToLastNode?.type === "paragraph" &&
64
- secondToLastPosition &&
65
- lastPosition &&
66
- secondToLastPosition.end.offset === lastPosition.start.offset) {
96
+ if (
97
+ secondToLastNode?.type === "paragraph" &&
98
+ secondToLastPosition &&
99
+ lastPosition &&
100
+ secondToLastPosition.end.offset === lastPosition.start.offset
101
+ ) {
67
102
  finalizableNodes = finalizableNodes.slice(0, -1);
68
103
  }
69
104
  }
@@ -101,7 +136,9 @@ const createStreamingParser = (options: ParserOptions = {}) => {
101
136
  const getPendingBlock = (): Block | undefined => {
102
137
  if (!state.buffer) return undefined;
103
138
 
104
- const ast = processor.parse(state.buffer) as Root;
139
+ const mendedBuffer = mend ? mend(state.buffer) : state.buffer;
140
+
141
+ const ast = processor.parse(mendedBuffer) as Root;
105
142
  const tree = processor.runSync(ast) as Root;
106
143
  const children = tree.children;
107
144
 
@@ -113,13 +150,14 @@ const createStreamingParser = (options: ParserOptions = {}) => {
113
150
  if (!firstNode || !position) return undefined;
114
151
 
115
152
  const start = state.totalOffset + position.start.offset!;
116
- const end = state.totalOffset + position.end.offset!;
153
+ // end offset is relative to the original (unmended) buffer length
154
+ const end = state.totalOffset + state.buffer.length;
117
155
 
118
156
  return {
119
157
  ast: firstNode,
120
158
  start,
121
159
  end,
122
- source: state.buffer.slice(position.start.offset!, position.end.offset!),
160
+ source: mendedBuffer.slice(position.start.offset!, position.end.offset!),
123
161
  };
124
162
  };
125
163
 
@@ -135,4 +173,4 @@ const createStreamingParser = (options: ParserOptions = {}) => {
135
173
  };
136
174
 
137
175
  export { createStreamingParser };
138
- export type { Block, ParserOptions };
176
+ export type { Block, ParserOptions, MendFunction };