@frontlit/text-editor 0.1.0-alpha.1 → 0.1.0-alpha.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 CHANGED
@@ -58,3 +58,48 @@ import "@frontlit/text-editor/styles.css";
58
58
  ## License
59
59
 
60
60
  MIT
61
+ # Documentation content profile
62
+
63
+ `@frontlit/text-editor/docs` is a server-safe entry for documentation validation,
64
+ CommonMark/GFM conversion, bounded YAML frontmatter, source-path mapping, and
65
+ versioned content hashes (DM-VALIDATE, DM-CONVERT, DM-SOURCE, DM-ROUTE). It does
66
+ not load React or instantiate an editor, node view, or upload control. Import
67
+ `@frontlit/text-editor/headings` for the lightweight heading policy alone.
68
+
69
+ ```ts
70
+ import { parseDocsMarkdown, serializeDocsMarkdown, validateDocsContent } from "@frontlit/text-editor/docs";
71
+
72
+ const { content, frontmatter } = parseDocsMarkdown(markdown, { file: "manual/setup.md" });
73
+ const report = validateDocsContent(content);
74
+ const exported = serializeDocsMarkdown(content, frontmatter);
75
+ ```
76
+
77
+ Parsing requires frontmatter with a title by default. Use `{ frontmatter: false }`
78
+ for editor Markdown bodies with metadata supplied separately. Unsupported content
79
+ throws `DocsContentError` with structured diagnostics; validation returns a report
80
+ without replacing invalid input with an empty document. A serialization failure
81
+ must prevent a draft write.
82
+
83
+ The profile supports paragraphs, headings 1–6, bold/italic/strike/inline-code/link
84
+ marks, nested lists, blockquotes, fenced code, horizontal rules, block images,
85
+ and rectangular tables with one header row and one paragraph per cell. It rejects
86
+ raw HTML/MDX, task lists, footnotes, inline images, merged/multiblock/aligned tables,
87
+ resize attributes, and unsupported marks. Images require stable HTTPS URLs.
88
+ URL syntax checks do not establish asset ownership or prove third-party privacy;
89
+ the API must verify managed-media provenance separately (DM-MEDIA).
90
+
91
+ Normalizations apply schema defaults, retain an omitted root array as `[]`, and
92
+ represent absent image alt descriptions as `""`. Markdown semantic comparisons
93
+ ignore empty top-level paragraphs used for spacing; canonical JSON retains them.
94
+ Unknown frontmatter stays bounded plain data. YAML aliases, custom tags, duplicate
95
+ keys, and prototype-sensitive metadata keys are rejected. Module safety ceilings
96
+ are 1 MiB of Markdown/text, 20,000 nodes, depth 64, and 32 KiB of metadata; request
97
+ transport limits can be smaller. Production admission limits remain a separate
98
+ operator configuration concern.
99
+
100
+ Use `<Editor profile="documentation" />` and
101
+ `<TextRenderer profile="documentation" />` for docs. The editor omits unsupported
102
+ controls and requires a media picker for uploads. Heading IDs use Unicode text,
103
+ remove punctuation, and assign unique suffixes in document order. Docs navigation,
104
+ validation helpers, rendering, and retrieval use the same policy; the default
105
+ editor/renderer profile preserves general-purpose behavior.
package/dist/docs.d.ts ADDED
@@ -0,0 +1,90 @@
1
+ import { Extensions, JSONContent } from '@tiptap/core';
2
+ import { Schema } from '@tiptap/pm/model';
3
+ export { DOCS_HEADING_POLICY_VERSION, HeadingNode, createHeadingIdGenerator, docsNodeText, extractDocsHeadings } from './headings.js';
4
+
5
+ /** DM-VALIDATE: shared, deterministic reports for authoring and import. */
6
+ interface DocsDiagnostic {
7
+ code: string;
8
+ severity: "error" | "warning";
9
+ blocksSave: boolean;
10
+ blocksPublish: boolean;
11
+ message: string;
12
+ fieldPath?: string;
13
+ file?: string;
14
+ line?: number;
15
+ column?: number;
16
+ route?: string;
17
+ documentId?: string;
18
+ relatedFiles?: string[];
19
+ }
20
+ declare function diagnostic(code: string, message: string, location?: Partial<DocsDiagnostic>): DocsDiagnostic;
21
+ declare function sortDiagnostics(items: DocsDiagnostic[]): DocsDiagnostic[];
22
+ declare class DocsContentError extends Error {
23
+ readonly diagnostics: DocsDiagnostic[];
24
+ constructor(diagnostics: DocsDiagnostic[]);
25
+ }
26
+
27
+ /** DM-VALIDATE: schema-only extensions; no React, upload controls, or node views. */
28
+ declare function createDocsExtensions(): Extensions;
29
+ declare const docsSchema: Schema;
30
+ declare const DOCS_SCHEMA_VERSION = 1;
31
+
32
+ /** DM-VALIDATE/DM-MEDIA: syntax safety; ownership/provider checks belong to the API. */
33
+ declare function isSafeDocsUrl(value: unknown, image?: boolean): value is string;
34
+
35
+ declare const DOCS_LIMITS: {
36
+ readonly bytes: number;
37
+ readonly nodes: 20000;
38
+ readonly depth: 64;
39
+ readonly metadataBytes: 32768;
40
+ };
41
+ /** Checks before ProseMirror can discard unknown keys. Never repairs supplied invalid trees. */
42
+ declare function validateDocsContent(input: unknown): {
43
+ content?: JSONContent;
44
+ diagnostics: DocsDiagnostic[];
45
+ };
46
+ declare function requireDocsContent(input: unknown): JSONContent;
47
+
48
+ type PlainData = null | string | number | boolean | PlainData[] | {
49
+ [key: string]: PlainData;
50
+ };
51
+ type DocsFrontmatter = Record<string, PlainData>;
52
+ /** DM-SOURCE: unknown metadata is retained as bounded, inert plain data. */
53
+ declare function requireDocsFrontmatter(value: unknown, file?: string): DocsFrontmatter;
54
+ declare function splitDocsFrontmatter(source: string, file?: string): {
55
+ frontmatter: DocsFrontmatter;
56
+ body: string;
57
+ lineOffset: number;
58
+ };
59
+ declare function serializeDocsFrontmatter(meta: DocsFrontmatter): string;
60
+
61
+ declare const DOCS_PARSER_VERSION = 1;
62
+ /** DM-CONVERT: CommonMark/GFM is parsed as data. Unsupported constructs fail closed. */
63
+ declare function parseDocsMarkdown(markdown: string, options?: {
64
+ file?: string;
65
+ frontmatter?: boolean;
66
+ }): {
67
+ content: JSONContent;
68
+ frontmatter: DocsFrontmatter;
69
+ };
70
+ declare function serializeDocsMarkdown(input: unknown, frontmatter?: DocsFrontmatter): string;
71
+
72
+ /** DM-CONVERT: include conversion and retrieval versions in immutable content identities. */
73
+ declare function hashDocsContent(input: {
74
+ content: unknown;
75
+ metadata: DocsFrontmatter;
76
+ embeddingConfigurationVersion: string;
77
+ }): Promise<string>;
78
+
79
+ /** DM-ROUTE: fixed /docs prefix, Latin segments, case-folded collision identity. */
80
+ declare function normalizeDocsSlug(value: unknown): string;
81
+ declare function normalizeDocsSourceDirectory(value: string): string;
82
+ /** Input path is repository-relative; callers must also reject symlink entries in Git trees. */
83
+ declare function resolveDocsSourcePath(path: string, directory: string, explicitSlug?: string): {
84
+ relativePath: string;
85
+ slug: string;
86
+ route: string;
87
+ sectionSlug: string;
88
+ };
89
+
90
+ export { DOCS_LIMITS, DOCS_PARSER_VERSION, DOCS_SCHEMA_VERSION, DocsContentError, type DocsDiagnostic, type DocsFrontmatter, type PlainData, createDocsExtensions, diagnostic, docsSchema, hashDocsContent, isSafeDocsUrl, normalizeDocsSlug, normalizeDocsSourceDirectory, parseDocsMarkdown, requireDocsContent, requireDocsFrontmatter, resolveDocsSourcePath, serializeDocsFrontmatter, serializeDocsMarkdown, sortDiagnostics, splitDocsFrontmatter, validateDocsContent };