@jxsuite/parser 0.35.1 → 1.1.0
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 +107 -66
- package/dist/content-loader.js +285 -0
- package/dist/content.js +2 -2
- package/dist/markdown.js +19 -5
- package/dist/serialize.js +2 -2
- package/jx-extension.json +17 -0
- package/package.json +19 -16
- package/schemas/document.fragment.schema.json +27 -0
- package/schemas/project.fragment.schema.json +59 -0
- package/src/Content.class.json +117 -0
- package/src/ContentCollection.class.json +3 -3
- package/src/ContentEntry.class.json +1 -1
- package/src/Csv.class.json +1 -1
- package/src/content-loader.ts +499 -0
- package/src/content.ts +6 -4
- package/src/html-to-jx.ts +8 -117
- package/src/markdown.ts +7 -0
- package/src/md-html.ts +5 -42
- package/src/md.ts +28 -2
- package/src/serialize.ts +1 -1
- package/src/transpile.ts +2 -2
- package/src/types.ts +15 -18
package/src/md-html.ts
CHANGED
|
@@ -1,49 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Md-html —
|
|
2
|
+
* Md-html — compatibility shim.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Unlike `./md.ts` this module has no node-only imports, so it is safe for the studio
|
|
9
|
-
* bundle. It intentionally produces an HTML *string*, not Jx nodes — use
|
|
10
|
-
* `@jxsuite/parser/markdown` for markdown → Jx document transpilation.
|
|
4
|
+
* The browser-safe markdown → sanitized HTML pipeline moved to `@jxsuite/markup/md-html`;
|
|
5
|
+
* this module re-exports it so the parser's historical `@jxsuite/parser/md-html`
|
|
6
|
+
* entrypoint keeps working for downstream consumers.
|
|
11
7
|
*
|
|
12
8
|
* @module @jxsuite/parser/md-html
|
|
13
9
|
* @license MIT
|
|
14
10
|
*/
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
import rehypeStringify from "rehype-stringify";
|
|
18
|
-
import remarkGfm from "remark-gfm";
|
|
19
|
-
import remarkParse from "remark-parse";
|
|
20
|
-
import remarkRehype from "remark-rehype";
|
|
21
|
-
import { unified } from "unified";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Minimal structural surface of the unified processor used here — same rationale as
|
|
25
|
-
* `UnifiedProcessor` in ./types.ts (oxlint sees the ESM-only unified types as `any`), plus
|
|
26
|
-
* `processSync` which the shared type doesn't carry.
|
|
27
|
-
*/
|
|
28
|
-
interface MdHtmlProcessor {
|
|
29
|
-
use: (plugin: unknown, ...options: unknown[]) => MdHtmlProcessor;
|
|
30
|
-
processSync: (source: string) => { toString: () => string };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const processor = (unified as unknown as () => MdHtmlProcessor)()
|
|
34
|
-
.use(remarkParse)
|
|
35
|
-
.use(remarkGfm)
|
|
36
|
-
.use(remarkRehype)
|
|
37
|
-
.use(rehypeSanitize)
|
|
38
|
-
.use(rehypeStringify);
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Convert markdown source to a sanitized HTML string (GFM tables/strikethrough/task lists
|
|
42
|
-
* supported). Raw HTML in the source is dropped, not passed through.
|
|
43
|
-
*
|
|
44
|
-
* @param {string} markdown
|
|
45
|
-
* @returns {string}
|
|
46
|
-
*/
|
|
47
|
-
export function markdownToHtml(markdown: string): string {
|
|
48
|
-
return String(processor.processSync(markdown));
|
|
49
|
-
}
|
|
12
|
+
export { markdownToHtml } from "@jxsuite/markup/md-html";
|
package/src/md.ts
CHANGED
|
@@ -18,7 +18,7 @@ import remarkParseFrontmatter from "remark-parse-frontmatter";
|
|
|
18
18
|
import remarkGfm from "remark-gfm";
|
|
19
19
|
import remarkDirective from "remark-directive";
|
|
20
20
|
import { readFileSync } from "node:fs";
|
|
21
|
-
import { basename, extname, resolve as resolvePath } from "node:path";
|
|
21
|
+
import { basename, extname, relative, resolve as resolvePath } from "node:path";
|
|
22
22
|
import { globSync } from "glob";
|
|
23
23
|
import { mdastNodeToJx } from "./transpile.ts";
|
|
24
24
|
import type { MarkdownFileResult, MdastNode, TocEntry, UnifiedProcessor } from "./types.ts";
|
|
@@ -133,6 +133,30 @@ function extractExcerpt(tree: MdastNode) {
|
|
|
133
133
|
return mdastToString(firstParagraph);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Derive an entry slug from a file path. Without a source root (or for files directly at the root),
|
|
138
|
+
* the slug is the basename — the historical behavior every flat collection relies on. Files in
|
|
139
|
+
* subdirectories of the root get path-based slugs with POSIX separators and a trailing `/index`
|
|
140
|
+
* stripped, so `studio/canvas.md` and `studio/canvas/index.md` both yield `studio/canvas`.
|
|
141
|
+
*
|
|
142
|
+
* @param {string} filePath - Absolute path to the markdown file
|
|
143
|
+
* @param {string} [sourceRoot] - Resolved content-source root directory
|
|
144
|
+
* @returns {string} The entry slug
|
|
145
|
+
*/
|
|
146
|
+
function deriveSlug(filePath: string, sourceRoot?: string): string {
|
|
147
|
+
if (sourceRoot) {
|
|
148
|
+
const rel = relative(sourceRoot, filePath).split("\\").join("/");
|
|
149
|
+
if (rel && !rel.startsWith("..") && rel.includes("/")) {
|
|
150
|
+
let slug = rel.slice(0, rel.length - extname(rel).length);
|
|
151
|
+
if (slug.endsWith("/index")) {
|
|
152
|
+
slug = slug.slice(0, -"/index".length);
|
|
153
|
+
}
|
|
154
|
+
return slug;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return basename(filePath, extname(filePath));
|
|
158
|
+
}
|
|
159
|
+
|
|
136
160
|
/**
|
|
137
161
|
* Process a single markdown source string into a MarkdownFileResult.
|
|
138
162
|
*
|
|
@@ -143,6 +167,7 @@ function extractExcerpt(tree: MdastNode) {
|
|
|
143
167
|
* @param {object} config - Processing options
|
|
144
168
|
* @param {boolean} [config.directives] - Enable directive support
|
|
145
169
|
* @param {unknown} [config.directiveOptions] - Directive plugin options
|
|
170
|
+
* @param {string} [config.sourceRoot] - Content-source root; files below it get path-based slugs
|
|
146
171
|
* @returns {MarkdownFileResult}
|
|
147
172
|
*/
|
|
148
173
|
export function processMarkdown(
|
|
@@ -151,6 +176,7 @@ export function processMarkdown(
|
|
|
151
176
|
config: {
|
|
152
177
|
directives?: boolean;
|
|
153
178
|
directiveOptions?: unknown;
|
|
179
|
+
sourceRoot?: string;
|
|
154
180
|
} = {},
|
|
155
181
|
) {
|
|
156
182
|
let processor = (unified as unknown as () => UnifiedProcessor)()
|
|
@@ -173,7 +199,7 @@ export function processMarkdown(
|
|
|
173
199
|
const plainText = mdastToString(mdTree);
|
|
174
200
|
const toc = extractToc(tree);
|
|
175
201
|
const excerpt = extractExcerpt(tree);
|
|
176
|
-
const slug =
|
|
202
|
+
const slug = deriveSlug(filePath, config.sourceRoot);
|
|
177
203
|
|
|
178
204
|
const bodyNodes = tree.children!.filter(
|
|
179
205
|
(n: MdastNode) => n.type !== "yaml" && n.type !== "toml",
|
package/src/serialize.ts
CHANGED
|
@@ -24,7 +24,7 @@ import remarkStringify from "remark-stringify";
|
|
|
24
24
|
import remarkDirective from "remark-directive";
|
|
25
25
|
import remarkGfm from "remark-gfm";
|
|
26
26
|
import { stringify as stringifyYaml } from "yaml";
|
|
27
|
-
import { htmlToJx } from "
|
|
27
|
+
import { htmlToJx } from "@jxsuite/markup/html-to-jx";
|
|
28
28
|
import { expandDotPaths } from "./transpile.ts";
|
|
29
29
|
import type {
|
|
30
30
|
JsonValue,
|
package/src/transpile.ts
CHANGED
|
@@ -17,11 +17,11 @@ import remarkFrontmatter from "remark-frontmatter";
|
|
|
17
17
|
import remarkParseFrontmatter from "remark-parse-frontmatter";
|
|
18
18
|
import remarkGfm from "remark-gfm";
|
|
19
19
|
import remarkDirective from "remark-directive";
|
|
20
|
-
import { htmlToJx } from "
|
|
20
|
+
import { htmlToJx } from "@jxsuite/markup/html-to-jx";
|
|
21
21
|
import type { MdastNode, UnifiedProcessor } from "./types.ts";
|
|
22
22
|
import type { JsonValue, JxAttributeValue, JxDocument, JxElement } from "@jxsuite/schema/types";
|
|
23
23
|
|
|
24
|
-
export { htmlToJx } from "
|
|
24
|
+
export { htmlToJx } from "@jxsuite/markup/html-to-jx";
|
|
25
25
|
|
|
26
26
|
// ─── Dot-path expansion ─────────────────────────────────────────────────────
|
|
27
27
|
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type { JxElement } from "@jxsuite/schema/types";
|
|
1
|
+
import type { JxElement, TocEntry } from "@jxsuite/schema/types";
|
|
2
|
+
|
|
3
|
+
// The content wire types are core (extensions implement them, hosts thread them); re-exported here
|
|
4
|
+
// So parser-internal modules and downstream consumers keep their historical import path.
|
|
5
|
+
export type { ContentLoaderEntry, TocEntry } from "@jxsuite/schema/types";
|
|
2
6
|
|
|
3
7
|
export interface MarkdownFileResult {
|
|
4
8
|
slug: string;
|
|
@@ -12,25 +16,18 @@ export interface MarkdownFileResult {
|
|
|
12
16
|
[key: string]: unknown;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
export interface TocEntry {
|
|
16
|
-
depth: number;
|
|
17
|
-
text: string;
|
|
18
|
-
id: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
19
|
export type ContentEntry = MarkdownFileResult & Record<string, unknown>;
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
21
|
+
/**
|
|
22
|
+
* A content-type definition in the project.json `content` section — the parser extension owns this
|
|
23
|
+
* shape (its project fragment schema is the validation source of truth).
|
|
24
|
+
*/
|
|
25
|
+
export interface ContentTypeDef {
|
|
26
|
+
source?: string;
|
|
27
|
+
format?: string;
|
|
28
|
+
schema?: Record<string, unknown>;
|
|
29
|
+
$elements?: (string | { $ref: string })[];
|
|
30
|
+
[key: string]: unknown;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
export interface MdastNode {
|