@pretextbook/remark-pretext 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.
- package/README.md +76 -76
- package/dist/index.cjs +6 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +796 -0
- package/dist/lib/context.d.ts +22 -0
- package/dist/lib/directive-factory.d.ts +24 -0
- package/dist/lib/directive-map.d.ts +64 -0
- package/dist/lib/directive-normalizer.d.ts +37 -0
- package/dist/lib/indentation-normalizer.d.ts +36 -0
- package/dist/lib/markdown-to-pretext.d.ts +19 -0
- package/dist/lib/math-parser.d.ts +31 -0
- package/dist/lib/mdast-to-ptxast.d.ts +13 -0
- package/dist/lib/remark-pretext.d.ts +11 -0
- package/index.cjs +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +54 -53
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BlockContent, DefinitionContent, PhrasingContent } from 'mdast';
|
|
2
|
+
export interface VisitContext {
|
|
3
|
+
/** Parent node, if any. */
|
|
4
|
+
parent?: BlockContent | DefinitionContent | PhrasingContent;
|
|
5
|
+
/** All ancestor nodes in traversal order. */
|
|
6
|
+
ancestors: (BlockContent | DefinitionContent | PhrasingContent)[];
|
|
7
|
+
/** Nesting depth. */
|
|
8
|
+
depth: number;
|
|
9
|
+
/** Accumulated error/warning messages. */
|
|
10
|
+
messages?: ConversionMessage[];
|
|
11
|
+
/** Raw source markdown (optional, used for delimiter detection). */
|
|
12
|
+
source?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ConversionMessage {
|
|
15
|
+
type: 'warning' | 'error';
|
|
16
|
+
reason: string;
|
|
17
|
+
category: string;
|
|
18
|
+
position?: {
|
|
19
|
+
line?: number;
|
|
20
|
+
column?: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BlockContent, DefinitionContent } from 'mdast';
|
|
2
|
+
import { ContainerDirective } from 'mdast-util-directive';
|
|
3
|
+
import { Element } from 'xast';
|
|
4
|
+
import { DirectiveSpec } from './directive-map.js';
|
|
5
|
+
import { VisitContext } from './context.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generic factory function: applies semantic rules from spec.
|
|
8
|
+
*
|
|
9
|
+
* Handles:
|
|
10
|
+
* - Statement wrapping for theorem-like elements
|
|
11
|
+
* - Task nesting with introduction wrapping (exercise/project/task)
|
|
12
|
+
* - Proof/solution sibling extraction
|
|
13
|
+
*
|
|
14
|
+
* @param spec Semantic specification for this directive type
|
|
15
|
+
* @param attrs HTML/XML attributes for the element
|
|
16
|
+
* @param titleEl Optional <title> element (extracted from first paragraph if present)
|
|
17
|
+
* @param children Body content of the directive
|
|
18
|
+
* @param ctx Visitor context
|
|
19
|
+
* @param convertBlock Callback to recursively convert block children
|
|
20
|
+
* @param convertDirective Callback to recursively convert nested directives
|
|
21
|
+
*
|
|
22
|
+
* @returns XAST element for this directive
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildDirectiveWithSpec(spec: DirectiveSpec, attrs: Record<string, string> | undefined, titleEl: Element | null, children: Array<BlockContent | DefinitionContent>, ctx: VisitContext, convertBlock: (child: BlockContent | DefinitionContent, ctx: VisitContext) => Element | null, convertDirective: (node: ContainerDirective, ctx: VisitContext) => Element | null): Element;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps directive names (from remark-directive's `:::name`) to their
|
|
3
|
+
* corresponding xast element names and semantic specifications.
|
|
4
|
+
*
|
|
5
|
+
* Architecture (Phase 2 refactor):
|
|
6
|
+
* - Separated semantic specs (requiresStatement) from routing logic
|
|
7
|
+
* - Factories apply spec-driven semantic rules uniformly
|
|
8
|
+
* - Adding new directives requires only configuration change, not new functions
|
|
9
|
+
*/
|
|
10
|
+
export type DirectiveCategory = 'theorem-like' | 'proof-like' | 'definition-like' | 'axiom-like' | 'remark-like' | 'example-like' | 'project-like' | 'exercise-like' | 'solution-like';
|
|
11
|
+
/**
|
|
12
|
+
* Semantic specification for how a directive type should be converted.
|
|
13
|
+
* This pattern mirrors unified-latex-to-pretext's factory specifications.
|
|
14
|
+
*/
|
|
15
|
+
export interface DirectiveSpec {
|
|
16
|
+
/** The PreTeXt XML element name (= xast `name` field). */
|
|
17
|
+
type: string;
|
|
18
|
+
/** Routing category for handler selection. */
|
|
19
|
+
category: DirectiveCategory;
|
|
20
|
+
/**
|
|
21
|
+
* If true, the directive's body content is wrapped in a <statement> element,
|
|
22
|
+
* and proof/solution siblings are extracted as siblings of the statement
|
|
23
|
+
* (not children of it). This matches PreTeXt semantics where theorems have:
|
|
24
|
+
* <theorem><title/><statement>...</statement><proof/></theorem>
|
|
25
|
+
*
|
|
26
|
+
* If false, content is added directly without statement wrapping.
|
|
27
|
+
*/
|
|
28
|
+
requiresStatement: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* If true, this directive can have nested task children.
|
|
31
|
+
* Content before the first task becomes an <introduction> wrapper.
|
|
32
|
+
* Example:
|
|
33
|
+
* <exercise><introduction>...</introduction><task>...</task><task>...</task></exercise>
|
|
34
|
+
*
|
|
35
|
+
* Only applies if nested tasks are actually present in the body.
|
|
36
|
+
* If no tasks are found, requiresStatement still applies.
|
|
37
|
+
*/
|
|
38
|
+
hasNestedTasks?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Backwards-compatible type for code that only needs type+category.
|
|
42
|
+
* @deprecated Use DirectiveSpec instead for new code.
|
|
43
|
+
*/
|
|
44
|
+
export interface DirectiveInfo {
|
|
45
|
+
type: string;
|
|
46
|
+
category: DirectiveCategory;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Semantic specification table: directive name → spec.
|
|
50
|
+
*
|
|
51
|
+
* Pattern mirrors unified-latex-to-pretext's environment specification approach:
|
|
52
|
+
* Declarative table + factory functions apply rules uniformly.
|
|
53
|
+
* To add a new directive: just add an entry here.
|
|
54
|
+
*/
|
|
55
|
+
export declare const DIRECTIVE_SPEC_TABLE: Readonly<Record<string, DirectiveSpec>>;
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated Use DIRECTIVE_SPEC_TABLE directly or via getDirectiveSpec().
|
|
58
|
+
* Kept for backwards compatibility. Returns spec as old DirectiveInfo type.
|
|
59
|
+
*/
|
|
60
|
+
export declare const DIRECTIVE_MAP: Readonly<Record<string, DirectiveInfo>>;
|
|
61
|
+
/** Get directive spec, or undefined if not found. */
|
|
62
|
+
export declare function getDirectiveSpec(name: string): DirectiveSpec | undefined;
|
|
63
|
+
/** Set of directive names that are proof/solution-like (used when separating statement siblings). */
|
|
64
|
+
export declare const PROOF_SOLUTION_NAMES: Set<string>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Directive Normalizer (Two-Pass Algorithm)
|
|
3
|
+
*
|
|
4
|
+
* Transforms user-friendly flexible colon syntax into standard remark-directive format.
|
|
5
|
+
*
|
|
6
|
+
* INPUT (flexible):
|
|
7
|
+
* :::exercise
|
|
8
|
+
* Intro
|
|
9
|
+
* :::task
|
|
10
|
+
* Content
|
|
11
|
+
* :::
|
|
12
|
+
* :::task
|
|
13
|
+
* More
|
|
14
|
+
* :::
|
|
15
|
+
* :::
|
|
16
|
+
*
|
|
17
|
+
* OUTPUT (normalized for remark-directive):
|
|
18
|
+
* ::::exercise
|
|
19
|
+
* Intro
|
|
20
|
+
* :::task
|
|
21
|
+
* Content
|
|
22
|
+
* :::
|
|
23
|
+
* :::task
|
|
24
|
+
* More
|
|
25
|
+
* :::
|
|
26
|
+
* ::::
|
|
27
|
+
*
|
|
28
|
+
* Algorithm (Two-Pass):
|
|
29
|
+
* - Pass 1: Parse markers, build nesting tree with parent references
|
|
30
|
+
* - Pass 2: Traverse tree bottom-up, compute final colon counts
|
|
31
|
+
* (each parent = max(children) + 1, ensuring proper nesting)
|
|
32
|
+
* - Pass 3: Re-emit with adjusted markers
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Main normalization function
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeDirectiveColons(markdown: string): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indentation-Based Directive Normalizer
|
|
3
|
+
*
|
|
4
|
+
* Transforms Python-like indentation-based directive syntax into colon syntax.
|
|
5
|
+
*
|
|
6
|
+
* INPUT (indentation-based):
|
|
7
|
+
* Theorem[Pythagorean]{#thm}:
|
|
8
|
+
* Statement text here.
|
|
9
|
+
*
|
|
10
|
+
* Proof:
|
|
11
|
+
* Proof content.
|
|
12
|
+
*
|
|
13
|
+
* Plain text (outdented).
|
|
14
|
+
*
|
|
15
|
+
* OUTPUT (colon-based):
|
|
16
|
+
* :::theorem[Pythagorean]{#thm}
|
|
17
|
+
* Statement text here.
|
|
18
|
+
*
|
|
19
|
+
* ::::proof
|
|
20
|
+
* Proof content.
|
|
21
|
+
* ::::
|
|
22
|
+
* :::
|
|
23
|
+
*
|
|
24
|
+
* Plain text (outdented).
|
|
25
|
+
*
|
|
26
|
+
* Algorithm:
|
|
27
|
+
* 1. Track fenced code blocks (``` and ~~~) and skip directive detection inside them
|
|
28
|
+
* 2. Parse each line to detect directive markers (Keyword[...]{...}:)
|
|
29
|
+
* 3. Track indentation stack: when indent increases, open a block; when decreases, close block(s)
|
|
30
|
+
* 4. Convert to colon syntax with proper nesting depth (validated against DIRECTIVE_SPEC_TABLE)
|
|
31
|
+
* 5. Preserve all non-directive content and indentation outside directives and code fences
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Normalize indentation-based syntax to colon-based syntax
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeIndentationDirectives(markdown: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a markdown string (with PreTeXt directive extensions) to a PreTeXt
|
|
3
|
+
* XML string.
|
|
4
|
+
*
|
|
5
|
+
* The output contains the converted XML fragment — the children of the root
|
|
6
|
+
* node serialized as a string — suitable for embedding in a PreTeXt document.
|
|
7
|
+
*
|
|
8
|
+
* @param markdown - The markdown source to convert.
|
|
9
|
+
* @returns A PreTeXt XML string.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { markdownToPretext } from '@pretextbook/remark-pretext';
|
|
14
|
+
*
|
|
15
|
+
* const xml = markdownToPretext('# Hello\n\nThis is a paragraph.');
|
|
16
|
+
* // → '<section>\n <title>Hello</title>\n <p>This is a paragraph.</p>\n</section>'
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function markdownToPretext(markdown: string): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Plugin } from 'unified';
|
|
2
|
+
import { Root, Text } from 'mdast';
|
|
3
|
+
export interface Math {
|
|
4
|
+
type: 'math';
|
|
5
|
+
value: string;
|
|
6
|
+
meta?: string;
|
|
7
|
+
}
|
|
8
|
+
declare module 'mdast' {
|
|
9
|
+
interface PhrasingContentMap {
|
|
10
|
+
math: Math;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export interface MathTokenizationResult {
|
|
14
|
+
markdown: string;
|
|
15
|
+
tokens: Map<string, Math>;
|
|
16
|
+
}
|
|
17
|
+
export declare function tokenizeMathInMarkdown(markdown: string): MathTokenizationResult;
|
|
18
|
+
/**
|
|
19
|
+
* Find math in a string and split into text and math nodes.
|
|
20
|
+
* Returns array of alternating Text and Math nodes.
|
|
21
|
+
*
|
|
22
|
+
* Order matters: we check longer/more specific delimiters first.
|
|
23
|
+
*/
|
|
24
|
+
export declare function splitTextWithMath(text: string): (Text | Math)[];
|
|
25
|
+
/**
|
|
26
|
+
* Remark plugin that detects and parses math delimiters in text nodes.
|
|
27
|
+
*/
|
|
28
|
+
export declare function applyMathDelimiters(tree: Root): void;
|
|
29
|
+
export declare function applyMathTokens(tree: Root, tokens: Map<string, Math>): void;
|
|
30
|
+
declare const remarkMath: Plugin<[], Root>;
|
|
31
|
+
export default remarkMath;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Root as MdastRoot } from 'mdast';
|
|
2
|
+
import { Root } from 'xast';
|
|
3
|
+
import { ConversionMessage } from './context.js';
|
|
4
|
+
/** Result type for conversion: tree + diagnostic messages. */
|
|
5
|
+
export interface ConversionResult {
|
|
6
|
+
tree: Root;
|
|
7
|
+
messages: ConversionMessage[];
|
|
8
|
+
}
|
|
9
|
+
/** Transform an mdast Root node into an xast Root node (backwards compatible). */
|
|
10
|
+
export declare function mdastToPtxast(tree: MdastRoot, source?: string): Root;
|
|
11
|
+
export { mdastToPtxast as mdastToXast };
|
|
12
|
+
/** Transform an mdast Root node, returning tree + diagnostic messages. */
|
|
13
|
+
export declare function mdastToPtxastWithDiagnostics(tree: MdastRoot, source?: string): ConversionResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Plugin } from 'unified';
|
|
2
|
+
import { Root as MdastRoot } from 'mdast';
|
|
3
|
+
import { Root } from 'xast';
|
|
4
|
+
/** Options for the remark-pretext plugin (currently none, reserved for future use). */
|
|
5
|
+
export interface RemarkPretextOptions {
|
|
6
|
+
}
|
|
7
|
+
declare const remarkPretext: Plugin<[RemarkPretextOptions?], MdastRoot, Root>;
|
|
8
|
+
export default remarkPretext;
|
|
9
|
+
export { mdastToPtxast } from './mdast-to-ptxast.js';
|
|
10
|
+
export { DIRECTIVE_MAP, PROOF_SOLUTION_NAMES } from './directive-map.js';
|
|
11
|
+
export type { DirectiveInfo, DirectiveCategory } from './directive-map.js';
|
package/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require('
|
|
1
|
+
module.exports = require('./dist/index.cjs');
|
package/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from "./dist/index.d.ts";
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '
|
|
1
|
+
export * from './dist/index.js';
|
package/package.json
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@pretextbook/remark-pretext",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "remark plugin to transform markdown-style PreTeXt directives into ptxast",
|
|
5
|
-
"author": "Oscar Levin",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
10
|
-
},
|
|
11
|
-
"bugs": {
|
|
12
|
-
"url": "https://github.com/
|
|
13
|
-
},
|
|
14
|
-
"homepage": "https://github.com/
|
|
15
|
-
"private": false,
|
|
16
|
-
"type": "module",
|
|
17
|
-
"main": "./index.cjs",
|
|
18
|
-
"module": "./index.js",
|
|
19
|
-
"types": "./index.d.ts",
|
|
20
|
-
"exports": {
|
|
21
|
-
".": {
|
|
22
|
-
"types": "./index.d.ts",
|
|
23
|
-
"import": "./index.js",
|
|
24
|
-
"require": "./index.cjs",
|
|
25
|
-
"default": "./index.js"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"sideEffects": false,
|
|
29
|
-
"files": [
|
|
30
|
-
"*.js",
|
|
31
|
-
"*.cjs",
|
|
32
|
-
"*.d.ts",
|
|
33
|
-
"*.d.cts",
|
|
34
|
-
"
|
|
35
|
-
"types"
|
|
36
|
-
],
|
|
37
|
-
"scripts": {
|
|
38
|
-
"build": "vite build",
|
|
39
|
-
"test": "vitest run"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@pretextbook/ptxast": "^0.0.
|
|
43
|
-
"@types/mdast": "^4.0.0",
|
|
44
|
-
"mdast-util-directive": "^3.0.0",
|
|
45
|
-
"remark-directive": "^4.0.0",
|
|
46
|
-
"remark-parse": "^11.0.0",
|
|
47
|
-
"unified": "^11.0.0",
|
|
48
|
-
"unist-util-visit": "^5.0.0"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@pretextbook/remark-pretext",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "remark plugin to transform markdown-style PreTeXt directives into ptxast",
|
|
5
|
+
"author": "Oscar Levin",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/PreTeXtBook/pretext-tools.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/PreTeXtBook/pretext-tools/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/PreTeXtBook/pretext-tools/packages/remark-pretext#readme",
|
|
15
|
+
"private": false,
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./index.cjs",
|
|
18
|
+
"module": "./index.js",
|
|
19
|
+
"types": "./index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./index.d.ts",
|
|
23
|
+
"import": "./index.js",
|
|
24
|
+
"require": "./index.cjs",
|
|
25
|
+
"default": "./index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"files": [
|
|
30
|
+
"*.js",
|
|
31
|
+
"*.cjs",
|
|
32
|
+
"*.d.ts",
|
|
33
|
+
"*.d.cts",
|
|
34
|
+
"dist",
|
|
35
|
+
"types"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "vite build",
|
|
39
|
+
"test": "vitest run"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@pretextbook/ptxast": "^0.0.3",
|
|
43
|
+
"@types/mdast": "^4.0.0",
|
|
44
|
+
"mdast-util-directive": "^3.0.0",
|
|
45
|
+
"remark-directive": "^4.0.0",
|
|
46
|
+
"remark-parse": "^11.0.0",
|
|
47
|
+
"unified": "^11.0.0",
|
|
48
|
+
"unist-util-visit": "^5.0.0",
|
|
49
|
+
"xast-util-to-xml": "^4.0.0"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
}
|
|
54
|
+
}
|