@limaformat/lima 0.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/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * LIMA Parser — LIMA Is Metadata Annotation
3
+ *
4
+ * Public entry point. The implementation is split per Appendix B's own
5
+ * layering:
6
+ * - `core.ts` — LIMA Core 1.0, reference-unaware by construction.
7
+ * - `references.ts` — the optional References 1.0 extension, layered on
8
+ * top of Core's internal annotated value tree.
9
+ * - `value.ts` — the shared Lima Value Model both build on.
10
+ *
11
+ * `parse` (the historical default export) resolves references — it is
12
+ * `parseReferences` under a name kept for backward compatibility.
13
+ */
14
+ export { parseCore } from './core.js';
15
+ export { parseReferences, parse } from './references.js';
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared, domain-agnostic parsing primitives: the parse context threaded
3
+ * through every module, Core §9's resource limits, and the length/duplicate
4
+ * checks built on them. Every other Core module (`scalars.ts`, `flow.ts`,
5
+ * `block.ts`, `core.ts`) sits above this one.
6
+ */
7
+ import { type LimaValue, SCALAR_LENGTH_LIMIT } from './value.js';
8
+ export { SCALAR_LENGTH_LIMIT };
9
+ /** Core §11.2: the minimal `onWarning` diagnostic shape — message and line only. */
10
+ export type Diagnostic = {
11
+ message: string;
12
+ line: number;
13
+ };
14
+ /**
15
+ * Threaded through the whole recursive descent instead of a bare `strict`
16
+ * boolean, so `onWarning` reaches every call site that can emit a warning
17
+ * (currently just duplicate-key detection) without growing every
18
+ * function's parameter list further as new warning types are added.
19
+ */
20
+ export type ParseContext = {
21
+ strict: boolean;
22
+ onWarning?: (diagnostic: Diagnostic) => void;
23
+ };
24
+ export declare const DOCUMENT_SIZE_LIMIT = 65536;
25
+ export declare const KEY_LENGTH_LIMIT = 128;
26
+ export declare const TOP_LEVEL_KEY_LIMIT = 128;
27
+ export declare const NESTING_DEPTH_LIMIT = 16;
28
+ export declare const byteLength: (s: string) => number;
29
+ export declare const checkStringLimit: (value: string, line: number) => void;
30
+ export declare const checkScalarLimit: (v: LimaValue, line: number) => void;
31
+ /**
32
+ * `line` is a thunk, not a plain number: computing a top-level key's line
33
+ * can trigger an O(document length) scan (see `keyLine` in core.ts) the very
34
+ * first time it's called, and this check runs for every key in the
35
+ * document. Evaluating it eagerly would pay that cost on every parse, even
36
+ * though the overwhelming majority of keys never violate the limit — the
37
+ * thunk defers it to the one branch that actually needs a line number.
38
+ */
39
+ export declare const checkKeyLength: (key: string, line: () => number) => void;
40
+ export declare const checkDuplicateKey: (exists: boolean, key: string, line: number, ctx: ParseContext) => void;
41
+ export declare const checkDuplicateKeyMap: (entries: Map<string, unknown>, key: string, line: number, ctx: ParseContext) => void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Shared, domain-agnostic parsing primitives: the parse context threaded
3
+ * through every module, Core §9's resource limits, and the length/duplicate
4
+ * checks built on them. Every other Core module (`scalars.ts`, `flow.ts`,
5
+ * `block.ts`, `core.ts`) sits above this one.
6
+ */
7
+ import { SCALAR_LENGTH_LIMIT, codepointLength } from './value.js';
8
+ import { LimaError } from './errors.js';
9
+ export { SCALAR_LENGTH_LIMIT };
10
+ // Core §9 resource limits. All are hard errors in both modes.
11
+ export const DOCUMENT_SIZE_LIMIT = 65536;
12
+ export const KEY_LENGTH_LIMIT = 128;
13
+ export const TOP_LEVEL_KEY_LIMIT = 128;
14
+ export const NESTING_DEPTH_LIMIT = 16;
15
+ const utf8Encoder = new TextEncoder();
16
+ export const byteLength = (s) => utf8Encoder.encode(s).length;
17
+ export const checkStringLimit = (value, line) => {
18
+ // UTF-16 code-unit length is always >= Unicode code-point length. Short
19
+ // values therefore cannot violate the limit and need no surrogate scan.
20
+ if (value.length > SCALAR_LENGTH_LIMIT && codepointLength(value) > SCALAR_LENGTH_LIMIT) {
21
+ throw new LimaError({
22
+ code: 'RESOURCE_LIMIT', line,
23
+ message: `LIMA: scalar exceeds maximum length of ${SCALAR_LENGTH_LIMIT} code points at line ${line}`,
24
+ });
25
+ }
26
+ };
27
+ export const checkScalarLimit = (v, line) => {
28
+ if (v.kind === 'string')
29
+ checkStringLimit(v.value, line);
30
+ };
31
+ /**
32
+ * `line` is a thunk, not a plain number: computing a top-level key's line
33
+ * can trigger an O(document length) scan (see `keyLine` in core.ts) the very
34
+ * first time it's called, and this check runs for every key in the
35
+ * document. Evaluating it eagerly would pay that cost on every parse, even
36
+ * though the overwhelming majority of keys never violate the limit — the
37
+ * thunk defers it to the one branch that actually needs a line number.
38
+ */
39
+ export const checkKeyLength = (key, line) => {
40
+ if (key.length > KEY_LENGTH_LIMIT && codepointLength(key) > KEY_LENGTH_LIMIT) {
41
+ const l = line();
42
+ throw new LimaError({
43
+ code: 'RESOURCE_LIMIT', line: l,
44
+ message: `LIMA: key "${key}" exceeds maximum length of ${KEY_LENGTH_LIMIT} code points at line ${l}`,
45
+ });
46
+ }
47
+ };
48
+ export const checkDuplicateKey = (exists, key, line, ctx) => {
49
+ if (!exists)
50
+ return;
51
+ const diagnostic = {
52
+ code: 'DUPLICATE_KEY', line, key,
53
+ message: `LIMA: duplicate key "${key}" at line ${line} — last value wins`,
54
+ };
55
+ if (ctx.strict)
56
+ throw new LimaError(diagnostic);
57
+ // Core §11.2: "Implementations MUST NOT emit warnings to any implicit
58
+ // output channel (e.g. console.warn)." Silently discarded when no
59
+ // onWarning callback is provided — never a fallback to console.warn.
60
+ // The public `Diagnostic` type is the spec-frozen {message, line} shape
61
+ // (§11.2); the object actually delivered is the richer `LimaDiagnostic`
62
+ // (a structural superset), letting an internal caller — such as the
63
+ // conformance runner, which imports these modules directly — read
64
+ // `.code` without parsing the message.
65
+ ctx.onWarning?.(diagnostic);
66
+ };
67
+ export const checkDuplicateKeyMap = (entries, key, line, ctx) => checkDuplicateKey(entries.has(key), key, line, ctx);
@@ -0,0 +1,36 @@
1
+ /**
2
+ * LIMA References 1.0 — layered strictly on top of `core.ts` (Appendix B:
3
+ * reference resolution is exclusively this extension's concern; Core never
4
+ * sees it). Reads the annotated `PositionedValue` tree Core produces and
5
+ * performs the two-phase resolution the spec describes (§4), keeping every
6
+ * intermediate result in the SAME annotated representation instead of a
7
+ * separate raw-value tree with a bolted-on marker for "inert":
8
+ *
9
+ * - A string's `quoted` flag (set once, by Core, from actual quote syntax)
10
+ * is the single source of truth for "never treat this as a reference
11
+ * site" — §2.3 (quoted tokens) and §3.8 (partial content) are the same
12
+ * rule applied to two different origins, so partial values are wrapped
13
+ * into this same representation with every string leaf pre-marked
14
+ * `quoted: true` before insertion (`partialToPositioned`), rather than
15
+ * needing a second, unrelated mechanism.
16
+ * - Every node keeps the source `line` it was parsed with, even after
17
+ * being deep-copied into a new position — diagnostics read it directly
18
+ * off the node instead of falling back to a coarser key-level lookup.
19
+ *
20
+ * There is no module-level mutable state: diagnostics are collected in a
21
+ * `ResolutionContext` created fresh per call and threaded explicitly.
22
+ */
23
+ import { type Diagnostic } from './core.js';
24
+ type Meta = Record<string, unknown>;
25
+ export type ReferencesOptions = {
26
+ /** Named values available via `(%key)` references. */
27
+ partials?: Meta;
28
+ strict?: boolean;
29
+ /** Core §11.2 (inherited): callback for non-strict warnings (e.g. duplicate keys). Discarded if omitted. */
30
+ onWarning?: (diagnostic: Diagnostic) => void;
31
+ };
32
+ export declare const parseReferences: <T extends Record<string, unknown> = Meta>(frontMatter: string, options?: ReferencesOptions) => T;
33
+ /** Backward-compatible primary entry point — References layered on Core. */
34
+ export declare const parse: typeof parseReferences;
35
+ export type ParseOptions = ReferencesOptions;
36
+ export {};