dexin-content 0.1.1 → 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.
Files changed (2) hide show
  1. package/core/markdown.ts +27 -11
  2. package/package.json +2 -1
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): ParagraphBlock {
149
- return { type: 'paragraph', children: walkInlines(n.children ?? [], file) }
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
 
@@ -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.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",