@orkestrel/markdown 0.0.1 → 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.
@@ -1,4 +1,4 @@
1
- import type { BlockNode, InlineNode, ListNode, MarkdownDocument, TableNode } from './types.js';
1
+ import { BlockNode, InlineNode, ListNode, MarkdownDocument, TableNode } from './types.js';
2
2
  /**
3
3
  * Parses a run of markdown lines into a block AST, recursing into nested
4
4
  * blockquotes, list items, and depth-capped degrade paragraphs.
@@ -6,6 +6,11 @@ import type { BlockNode, InlineNode, ListNode, MarkdownDocument, TableNode } fro
6
6
  * @param lines - The markdown lines to parse.
7
7
  * @param depth - The current recursion depth (blockquotes/lists increment it).
8
8
  * @returns The parsed block nodes.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * parseBlocks(['# Hi'], 0) // [{ element: 'heading', level: 1, children: [...] }]
13
+ * ```
9
14
  */
10
15
  export declare function parseBlocks(lines: readonly string[], depth: number): readonly BlockNode[];
11
16
  /**
@@ -15,6 +20,11 @@ export declare function parseBlocks(lines: readonly string[], depth: number): re
15
20
  * @param lines - The markdown lines to scan.
16
21
  * @param start - The index of the header row.
17
22
  * @returns The parsed table node and the index of the first line after it.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * collectTable(['| a |', '| - |'], 0) // { node: { element: 'table', ... }, next: 2 }
27
+ * ```
18
28
  */
19
29
  export declare function collectTable(lines: readonly string[], start: number): {
20
30
  readonly node: TableNode;
@@ -28,6 +38,11 @@ export declare function collectTable(lines: readonly string[], start: number): {
28
38
  * @param start - The index of the first list item.
29
39
  * @param depth - The current recursion depth (each item recurses at `depth + 1`).
30
40
  * @returns The parsed list node and the index of the first line after it.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * collectList(['- item'], 0, 0) // { node: { element: 'list', ... }, next: 1 }
45
+ * ```
31
46
  */
32
47
  export declare function collectList(lines: readonly string[], start: number, depth: number): {
33
48
  readonly node: ListNode;
@@ -1,3 +1,4 @@
1
+ import { ObjectShape, LiteralShape, StringShape, OptionalShape, BooleanShape, NumberShape } from '@orkestrel/contract';
1
2
  /**
2
3
  * The shape of a {@link TextNode} - a plain-text leaf inline run.
3
4
  *
@@ -10,10 +11,10 @@
10
11
  * text.is({ element: 'text', value: 'hi' }) // true
11
12
  * ```
12
13
  */
13
- export declare const textShape: import("@orkestrel/contract").ObjectShape<{
14
- element: import("@orkestrel/contract").LiteralShape<readonly ["text"]>;
15
- value: import("@orkestrel/contract").StringShape;
16
- }>;
14
+ export declare const textShape: ObjectShape<{
15
+ element: LiteralShape<readonly ["text"]>;
16
+ value: StringShape;
17
+ }, false>;
17
18
  /**
18
19
  * The shape of a {@link CodeSpanNode} - an inline code span (`` `code` ``).
19
20
  *
@@ -26,10 +27,10 @@ export declare const textShape: import("@orkestrel/contract").ObjectShape<{
26
27
  * codeSpan.is({ element: 'codeSpan', value: 'const x = 1' }) // true
27
28
  * ```
28
29
  */
29
- export declare const codeSpanShape: import("@orkestrel/contract").ObjectShape<{
30
- element: import("@orkestrel/contract").LiteralShape<readonly ["codeSpan"]>;
31
- value: import("@orkestrel/contract").StringShape;
32
- }>;
30
+ export declare const codeSpanShape: ObjectShape<{
31
+ element: LiteralShape<readonly ["codeSpan"]>;
32
+ value: StringShape;
33
+ }, false>;
33
34
  /**
34
35
  * The shape of a {@link CodeBlockNode} - a fenced code block. `lang` is
35
36
  * optional (absent when the opening fence carries no info-string).
@@ -44,11 +45,11 @@ export declare const codeSpanShape: import("@orkestrel/contract").ObjectShape<{
44
45
  * codeBlock.is({ element: 'codeBlock', code: 'x', lang: 'ts' }) // true
45
46
  * ```
46
47
  */
47
- export declare const codeBlockShape: import("@orkestrel/contract").ObjectShape<{
48
- element: import("@orkestrel/contract").LiteralShape<readonly ["codeBlock"]>;
49
- lang: import("@orkestrel/contract").OptionalShape<import("@orkestrel/contract").StringShape>;
50
- code: import("@orkestrel/contract").StringShape;
51
- }>;
48
+ export declare const codeBlockShape: ObjectShape<{
49
+ element: LiteralShape<readonly ["codeBlock"]>;
50
+ lang: OptionalShape<StringShape>;
51
+ code: StringShape;
52
+ }, false>;
52
53
  /**
53
54
  * The shape of a {@link ThematicBreakNode} - a horizontal rule. Carries no
54
55
  * fields beyond its `element` discriminant.
@@ -62,9 +63,9 @@ export declare const codeBlockShape: import("@orkestrel/contract").ObjectShape<{
62
63
  * thematicBreak.is({ element: 'thematicBreak' }) // true
63
64
  * ```
64
65
  */
65
- export declare const thematicBreakShape: import("@orkestrel/contract").ObjectShape<{
66
- element: import("@orkestrel/contract").LiteralShape<readonly ["thematicBreak"]>;
67
- }>;
66
+ export declare const thematicBreakShape: ObjectShape<{
67
+ element: LiteralShape<readonly ["thematicBreak"]>;
68
+ }, false>;
68
69
  /**
69
70
  * The shape of a {@link TableAlign} - the per-column GFM table alignment
70
71
  * literal.
@@ -80,7 +81,7 @@ export declare const thematicBreakShape: import("@orkestrel/contract").ObjectSha
80
81
  * tableAlign.is('top') // false
81
82
  * ```
82
83
  */
83
- export declare const tableAlignShape: import("@orkestrel/contract").LiteralShape<readonly ["none", "left", "right", "center"]>;
84
+ export declare const tableAlignShape: LiteralShape<readonly ["none", "left", "right", "center"]>;
84
85
  /**
85
86
  * The shape of {@link ListItemParts} - the parsed parts of a single list-item
86
87
  * line the block phase's list detector returns. Fully non-recursive (no
@@ -95,10 +96,10 @@ export declare const tableAlignShape: import("@orkestrel/contract").LiteralShape
95
96
  * listItemParts.is({ ordered: false, start: 1, content: 'hi', indent: 0, marker: 2 }) // true
96
97
  * ```
97
98
  */
98
- export declare const listItemPartsShape: import("@orkestrel/contract").ObjectShape<{
99
- ordered: import("@orkestrel/contract").BooleanShape;
100
- start: import("@orkestrel/contract").NumberShape;
101
- content: import("@orkestrel/contract").StringShape;
102
- indent: import("@orkestrel/contract").NumberShape;
103
- marker: import("@orkestrel/contract").NumberShape;
104
- }>;
99
+ export declare const listItemPartsShape: ObjectShape<{
100
+ ordered: BooleanShape;
101
+ start: NumberShape;
102
+ content: StringShape;
103
+ indent: NumberShape;
104
+ marker: NumberShape;
105
+ }, false>;
@@ -1,11 +1,17 @@
1
- import type { Guard } from '@orkestrel/contract';
2
- import type { BlockNode, BlockquoteNode, CodeBlockNode, CodeSpanNode, EmphasisNode, HeadingNode, InlineNode, LinkNode, ListNode, MarkdownDocument, MarkdownNode, ParagraphNode, TableNode, TextNode, ThematicBreakNode } from './types.js';
1
+ import { Guard } from '@orkestrel/contract';
2
+ import { BlockNode, BlockquoteNode, CodeBlockNode, CodeSpanNode, EmphasisNode, HeadingNode, InlineNode, LinkNode, ListNode, MarkdownDocument, MarkdownNode, ParagraphNode, TableNode, TextNode, ThematicBreakNode } from './types.js';
3
3
  /**
4
4
  * Whether `character` is an inline whitespace character (space / tab / newline) - the
5
5
  * emphasis flanking rule's space test.
6
6
  *
7
7
  * @param character - The character to test
8
8
  * @returns `true` when it is inline whitespace
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * isWhitespace(' ') // true
13
+ * isWhitespace('a') // false
14
+ * ```
9
15
  */
10
16
  export declare function isWhitespace(character: string): boolean;
11
17
  /**
@@ -14,6 +20,12 @@ export declare function isWhitespace(character: string): boolean;
14
20
  *
15
21
  * @param character - The single character after a backslash
16
22
  * @returns `true` when a backslash before it is an escape
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * isEscapable('*') // true
27
+ * isEscapable('a') // false
28
+ * ```
17
29
  */
18
30
  export declare function isEscapable(character: string): boolean;
19
31
  /**
@@ -23,6 +35,11 @@ export declare function isEscapable(character: string): boolean;
23
35
  *
24
36
  * @param line - The candidate line
25
37
  * @returns `true` when the line is blank
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * isBlankLine(' ') // true
42
+ * ```
26
43
  */
27
44
  export declare function isBlankLine(line: string): boolean;
28
45
  /**
@@ -31,6 +48,11 @@ export declare function isBlankLine(line: string): boolean;
31
48
  *
32
49
  * @param line - The candidate line
33
50
  * @returns `true` when the line begins a blockquote
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * isQuote('> quoted') // true
55
+ * ```
34
56
  */
35
57
  export declare function isQuote(line: string): boolean;
36
58
  /**
@@ -40,6 +62,11 @@ export declare function isQuote(line: string): boolean;
40
62
  * @param line - The candidate closing line
41
63
  * @param marker - The opening fence's marker run (from {@link extractFence})
42
64
  * @returns `true` when `line` closes the fence
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * isFenceClose('```', '```') // true
69
+ * ```
43
70
  */
44
71
  export declare function isFenceClose(line: string, marker: string): boolean;
45
72
  /**
@@ -48,6 +75,12 @@ export declare function isFenceClose(line: string, marker: string): boolean;
48
75
  *
49
76
  * @param character - The single character to test, or `undefined` past the end of a line
50
77
  * @returns `true` when it is whitespace
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * isFenceWhitespace(' ') // true
82
+ * isFenceWhitespace(undefined) // false
83
+ * ```
51
84
  */
52
85
  export declare function isFenceWhitespace(character: string | undefined): boolean;
53
86
  /**
@@ -57,6 +90,11 @@ export declare function isFenceWhitespace(character: string | undefined): boolea
57
90
  *
58
91
  * @param line - The candidate line
59
92
  * @returns `true` when the line is a thematic break
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * isThematicBreak('---') // true
97
+ * ```
60
98
  */
61
99
  export declare function isThematicBreak(line: string): boolean;
62
100
  /**
@@ -67,25 +105,79 @@ export declare function isThematicBreak(line: string): boolean;
67
105
  * @param header - The candidate header line
68
106
  * @param delimiter - The line after it (the candidate delimiter)
69
107
  * @returns `true` when the two lines open a table
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * isTableStart('| a |', '| - |') // true
112
+ * ```
70
113
  */
71
114
  export declare function isTableStart(header: string, delimiter: string | undefined): boolean;
72
115
  /** Determine whether a node is a heading block. */
73
116
  export declare function isHeadingNode(node: MarkdownNode): node is HeadingNode;
74
- /** Determine whether a node is a paragraph block. */
117
+ /**
118
+ * Determine whether a node is a paragraph block.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * isParagraphNode({ element: 'paragraph', children: [] }) // true
123
+ * ```
124
+ */
75
125
  export declare function isParagraphNode(node: MarkdownNode): node is ParagraphNode;
76
- /** Determine whether a node is a list block. */
126
+ /**
127
+ * Determine whether a node is a list block.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * isListNode({ element: 'list', ordered: false, start: 1, items: [] }) // true
132
+ * ```
133
+ */
77
134
  export declare function isListNode(node: MarkdownNode): node is ListNode;
78
135
  /** Determine whether a node is a GFM table block. */
79
136
  export declare function isTableNode(node: MarkdownNode): node is TableNode;
80
- /** Determine whether a node is a fenced code block. */
137
+ /**
138
+ * Determine whether a node is a fenced code block.
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * isCodeBlockNode({ element: 'codeBlock', code: 'x' }) // true
143
+ * ```
144
+ */
81
145
  export declare function isCodeBlockNode(node: MarkdownNode): node is CodeBlockNode;
82
- /** Determine whether a node is a blockquote block. */
146
+ /**
147
+ * Determine whether a node is a blockquote block.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * isBlockquoteNode({ element: 'blockquote', children: [] }) // true
152
+ * ```
153
+ */
83
154
  export declare function isBlockquoteNode(node: MarkdownNode): node is BlockquoteNode;
84
- /** Determine whether a node is a thematic break (horizontal rule) block. */
155
+ /**
156
+ * Determine whether a node is a thematic break (horizontal rule) block.
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * isThematicBreakNode({ element: 'thematicBreak' }) // true
161
+ * ```
162
+ */
85
163
  export declare function isThematicBreakNode(node: MarkdownNode): node is ThematicBreakNode;
86
- /** Determine whether a node is a plain text run. */
164
+ /**
165
+ * Determine whether a node is a plain text run.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * isTextNode({ element: 'text', value: 'hi' }) // true
170
+ * ```
171
+ */
87
172
  export declare function isTextNode(node: MarkdownNode): node is TextNode;
88
- /** Determine whether a node is an emphasis run (`*em*` / `**strong**`). */
173
+ /**
174
+ * Determine whether a node is an emphasis run (`*em*` / `**strong**`).
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * isEmphasisNode({ element: 'emphasis', strong: false, children: [] }) // true
179
+ * ```
180
+ */
89
181
  export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode;
90
182
  /**
91
183
  * Determine whether a node is an inline code span.
@@ -93,6 +185,11 @@ export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode
93
185
  * @remarks
94
186
  * Narrows to {@link CodeSpanNode} - the node whose `element` discriminant is
95
187
  * `'codeSpan'`.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * isCodeSpanNode({ element: 'codeSpan', value: 'x' }) // true
192
+ * ```
96
193
  */
97
194
  export declare function isCodeSpanNode(node: MarkdownNode): node is CodeSpanNode;
98
195
  /** Determine whether a node is a link. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orkestrel/markdown",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Markdown parser toolkit — a fast, zero-surprise CommonMark-style parser with GFM tables, a typed AST, contract-backed node guards, and safe HTML rendering. Part of the @orkestrel line.",
5
5
  "keywords": [
6
6
  "ast",
@@ -25,13 +25,19 @@
25
25
  ],
26
26
  "type": "module",
27
27
  "sideEffects": false,
28
- "main": "./dist/src/core/index.js",
28
+ "main": "./dist/src/core/index.cjs",
29
+ "module": "./dist/src/core/index.js",
29
30
  "types": "./dist/src/core/index.d.ts",
30
31
  "exports": {
31
32
  ".": {
32
- "types": "./dist/src/core/index.d.ts",
33
- "import": "./dist/src/core/index.js",
34
- "default": "./dist/src/core/index.js"
33
+ "import": {
34
+ "types": "./dist/src/core/index.d.ts",
35
+ "default": "./dist/src/core/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/src/core/index.d.cts",
39
+ "default": "./dist/src/core/index.cjs"
40
+ }
35
41
  },
36
42
  "./package.json": "./package.json"
37
43
  },
@@ -43,31 +49,35 @@
43
49
  "copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
44
50
  "tmp:txt": "node -e \"const fs=require('node:fs'),p=require('node:path');function walk(d){for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=p.join(d,e.name);if(e.isDirectory()){walk(f)}else if(!e.name.endsWith('.md')&&!e.name.endsWith('.txt')){const t=f+'.txt';if(!fs.existsSync(t)){fs.renameSync(f,t)}else{console.warn('Skipping '+f+' — target exists: '+t)}}}}try{walk('tmp')}catch(e){if(e.code!=='ENOENT')throw e}\"",
45
51
  "lint": "oxlint --config .oxlintrc.json --fix .",
46
- "check": "tsc --noEmit --project tsconfig.json",
52
+ "check": "tsc --noEmit --project tsconfig.json && npm run check:src",
47
53
  "check:src": "npm run check:src:core",
48
54
  "check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
49
55
  "format": "oxfmt --config .oxfmtrc.json --write .",
50
56
  "format:check": "oxfmt --config .oxfmtrc.json --check .",
51
57
  "lint:check": "oxlint --config .oxlintrc.json .",
52
- "test": "npm run test:src",
53
- "test:src": "vitest run --config vite.config.ts --reporter=dot --project src:core",
58
+ "test": "npm run test:src && npm run test:guides",
59
+ "test:src": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
60
+ "test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
61
+ "test:guides": "vitest run --config vite.config.ts --reporter=dot --project guides",
54
62
  "build": "npm run clean && npm run build:src",
55
63
  "build:src": "npm run build:src:core",
56
- "build:src:core": "vite build --config configs/src/vite.core.config.ts && tsc -p configs/src/tsconfig.core.json",
57
- "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run check:src && npm run build && npm test"
64
+ "build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
65
+ "prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test"
58
66
  },
59
67
  "dependencies": {
60
- "@orkestrel/contract": "^0.0.1"
68
+ "@orkestrel/contract": "^0.0.3"
61
69
  },
62
70
  "devDependencies": {
71
+ "@orkestrel/guide": "^0.0.2",
63
72
  "@types/node": "^26.1.1",
64
- "oxfmt": "^0.58.0",
65
- "oxlint": "^1.73.0",
73
+ "oxfmt": "^0.59.0",
74
+ "oxlint": "^1.74.0",
66
75
  "typescript": "^6.0.3",
67
- "vite": "^8.1.4",
76
+ "vite": "^8.1.5",
77
+ "vite-plugin-dts": "^5.0.3",
68
78
  "vitest": "^4.1.10"
69
79
  },
70
80
  "engines": {
71
- "node": ">=24"
81
+ "node": ">=22"
72
82
  }
73
83
  }