dexin-content 0.1.0 → 0.1.2
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/collection.ts +2 -2
- package/core/frontmatter.ts +1 -1
- package/core/markdown.ts +28 -12
- package/package.json +2 -1
package/collection.ts
CHANGED
|
@@ -104,7 +104,7 @@ export function createMemorySource (files: Record<string, string>): SourceAdapte
|
|
|
104
104
|
list: async () => Object.keys(files).sort(),
|
|
105
105
|
read: async (rel) => {
|
|
106
106
|
if (!(rel in files)) throw new Error(`[MemorySource] Not found: ${rel}`)
|
|
107
|
-
return files[rel]
|
|
107
|
+
return files[rel]!
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -143,7 +143,7 @@ export async function discover (
|
|
|
143
143
|
const all = await source.list()
|
|
144
144
|
const files: ContentFile[] = []
|
|
145
145
|
for (const rel of all) {
|
|
146
|
-
const top = rel.split('/')[0]
|
|
146
|
+
const top = rel.split('/')[0]!
|
|
147
147
|
const col = byDir.get(top)
|
|
148
148
|
if (!col) {
|
|
149
149
|
throw new Error(
|
package/core/frontmatter.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function splitFrontmatter (source: string): SplitResult {
|
|
|
39
39
|
const lines = rest.split('\n')
|
|
40
40
|
let closeIdx = -1
|
|
41
41
|
for (let i = 0; i < lines.length; i++) {
|
|
42
|
-
if (lines[i].trimEnd() === '---') {
|
|
42
|
+
if ((lines[i] ?? '').trimEnd() === '---') {
|
|
43
43
|
closeIdx = i
|
|
44
44
|
break
|
|
45
45
|
}
|
package/core/markdown.ts
CHANGED
|
@@ -79,7 +79,7 @@ export function parseToDocAST (source: string, file: string): DocumentContent {
|
|
|
79
79
|
.use(remarkDirective)
|
|
80
80
|
.parse(source) as MdNode
|
|
81
81
|
|
|
82
|
-
const blocks = walkBlocks(mdast.children ?? [], file, 'root')
|
|
82
|
+
const blocks = walkBlocks(mdast.children ?? [], file, 'root', source)
|
|
83
83
|
return { version: 1, blocks }
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -89,20 +89,20 @@ export { parseToDocAST as parseDocument }
|
|
|
89
89
|
|
|
90
90
|
type BlockScope = 'root' | 'blockquote' | 'container'
|
|
91
91
|
|
|
92
|
-
function walkBlocks (nodes: MdNode[], file: string, scope: BlockScope): DocumentBlock[] {
|
|
92
|
+
function walkBlocks (nodes: MdNode[], file: string, scope: BlockScope, source: string): DocumentBlock[] {
|
|
93
93
|
const out: DocumentBlock[] = []
|
|
94
94
|
for (const n of nodes) {
|
|
95
95
|
switch (n.type) {
|
|
96
96
|
case 'heading': out.push(walkHeading(n, file)); break
|
|
97
|
-
case 'paragraph': out.push(walkParagraph(n, file)); break
|
|
98
|
-
case 'blockquote': out.push(walkBlockquote(n, file)); break
|
|
97
|
+
case 'paragraph': out.push(walkParagraph(n, file, source)); break
|
|
98
|
+
case 'blockquote': out.push(walkBlockquote(n, file, source)); break
|
|
99
99
|
case 'thematicBreak': out.push({ type: 'divider' }); break
|
|
100
100
|
case 'list': out.push(walkList(n, file)); break
|
|
101
101
|
case 'table': out.push(walkTable(n, file)); break
|
|
102
102
|
case 'image': out.push(walkImage(n)); break
|
|
103
103
|
case 'code': out.push(walkCode(n)); break
|
|
104
104
|
case NODE_FORMULA_BLOCK: out.push(walkFormula(n)); break
|
|
105
|
-
case 'containerDirective': out.push(walkContainerDirective(n, file)); break
|
|
105
|
+
case 'containerDirective': out.push(walkContainerDirective(n, file, source)); break
|
|
106
106
|
default: {
|
|
107
107
|
const err = new Error(
|
|
108
108
|
`[MDAST_UNSUPPORTED_NODE] Unsupported block node type '${n.type}' in ${file} (scope: ${scope}). ` +
|
|
@@ -145,8 +145,24 @@ function walkHeading (n: MdNode, file: string): HeadingBlock {
|
|
|
145
145
|
return h
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
function walkParagraph (n: MdNode, file: string):
|
|
149
|
-
|
|
148
|
+
function walkParagraph (n: MdNode, file: string, source: string): DocumentBlock {
|
|
149
|
+
// Block Math rescue (P-0 fix): remark-math 6.0.0 fails to recognize a
|
|
150
|
+
// single-line `$$...$$` (delimiter on the same line as the content) as a
|
|
151
|
+
// block-level math node, producing paragraph > inlineMath instead of a
|
|
152
|
+
// top-level `math` node. When a paragraph consists of exactly one inline
|
|
153
|
+
// math child whose original source delimiter is `$$` (verified via the
|
|
154
|
+
// node's position offset into `source`), promote it to
|
|
155
|
+
// FormulaBlock(display=true). A single `$` inline is never promoted.
|
|
156
|
+
const children = n.children ?? []
|
|
157
|
+
if (children.length === 1 && children[0]?.type === NODE_FORMULA_INLINE) {
|
|
158
|
+
const child = children[0]!
|
|
159
|
+
const pos = child.position as { start?: { offset?: number } } | undefined
|
|
160
|
+
const startOffset = pos?.start?.offset
|
|
161
|
+
if (startOffset !== undefined && source.slice(startOffset, startOffset + 2) === '$$') {
|
|
162
|
+
return { type: 'formula', latex: child.value ?? '', display: true }
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { type: 'paragraph', children: walkInlines(children, file) }
|
|
150
166
|
}
|
|
151
167
|
|
|
152
168
|
/**
|
|
@@ -155,8 +171,8 @@ function walkParagraph (n: MdNode, file: string): ParagraphBlock {
|
|
|
155
171
|
* ParagraphBlock with a literal newline rather than two paragraphs.
|
|
156
172
|
* Paragraphs separated by blank lines inside the quote remain separate.
|
|
157
173
|
*/
|
|
158
|
-
function walkBlockquote (n: MdNode, file: string): QuoteBlock {
|
|
159
|
-
const inner = walkBlocks(n.children ?? [], file, 'blockquote')
|
|
174
|
+
function walkBlockquote (n: MdNode, file: string, source: string): QuoteBlock {
|
|
175
|
+
const inner = walkBlocks(n.children ?? [], file, 'blockquote', source)
|
|
160
176
|
return { type: 'quote', children: inner }
|
|
161
177
|
}
|
|
162
178
|
|
|
@@ -192,7 +208,7 @@ function walkTable (n: MdNode, file: string): TableBlock {
|
|
|
192
208
|
const headers: TableCell[] = []
|
|
193
209
|
const rows: TableCell[][] = []
|
|
194
210
|
for (let i = 0; i < kids.length; i++) {
|
|
195
|
-
const row = kids[i]
|
|
211
|
+
const row = kids[i]!
|
|
196
212
|
const rowCells: TableCell[] = []
|
|
197
213
|
const cells = row.children ?? []
|
|
198
214
|
for (const cell of cells) rowCells.push(walkInlines(cell.children ?? [], file))
|
|
@@ -220,7 +236,7 @@ function walkFormula (n: MdNode): FormulaBlock {
|
|
|
220
236
|
* Interpretation of a container's name and semantics is deferred to the
|
|
221
237
|
* active domain parser; here the structure is preserved verbatim.
|
|
222
238
|
*/
|
|
223
|
-
function walkContainerDirective (n: MdNode, file: string): ContainerBlock {
|
|
239
|
+
function walkContainerDirective (n: MdNode, file: string, source: string): ContainerBlock {
|
|
224
240
|
const name = n.name ?? 'unknown'
|
|
225
241
|
const attrsIn = n.attributes ?? {}
|
|
226
242
|
const attrs: Record<string, string> = {}
|
|
@@ -228,7 +244,7 @@ function walkContainerDirective (n: MdNode, file: string): ContainerBlock {
|
|
|
228
244
|
const v = attrsIn[key]
|
|
229
245
|
attrs[key] = v == null ? '' : String(v)
|
|
230
246
|
}
|
|
231
|
-
const children = walkBlocks(n.children ?? [], file, 'container')
|
|
247
|
+
const children = walkBlocks(n.children ?? [], file, 'container', source)
|
|
232
248
|
return { type: 'container', name, attrs, children }
|
|
233
249
|
}
|
|
234
250
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dexin-content",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Structured content compilation & runtime layer — neutral Markdown → Content AST → PositiveArtifact + store/query/collection pipeline.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"./core/compiler": "./core/compiler.ts",
|
|
42
42
|
"./core/frontmatter": "./core/frontmatter.ts",
|
|
43
43
|
"./core/discovery": "./core/discovery.ts",
|
|
44
|
+
"./core/markdown": "./core/markdown.ts",
|
|
44
45
|
"./store": "./store.ts",
|
|
45
46
|
"./collection": "./collection.ts",
|
|
46
47
|
"./query": "./query.ts",
|