@nysds/codegen 0.0.0-stage → 1.20.1

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 (49) hide show
  1. package/README.md +95 -2
  2. package/cem-plugins/angular.mjs +551 -0
  3. package/cem-plugins/deps.mjs +154 -0
  4. package/cem-plugins/form-control.mjs +94 -0
  5. package/cem-plugins/index.mjs +12 -0
  6. package/cem-plugins/lib/core.d.mts +79 -0
  7. package/cem-plugins/lib/core.mjs +288 -0
  8. package/cem-plugins/react.mjs +143 -0
  9. package/cem-plugins/vue.mjs +228 -0
  10. package/dist/index.d.ts +17 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +14 -0
  13. package/dist/manifest/components.d.ts +6 -0
  14. package/dist/manifest/components.d.ts.map +1 -0
  15. package/dist/manifest/components.js +5 -0
  16. package/dist/manifest/filters.d.ts +6 -0
  17. package/dist/manifest/filters.d.ts.map +1 -0
  18. package/dist/manifest/filters.js +5 -0
  19. package/dist/manifest/form-control.d.ts +6 -0
  20. package/dist/manifest/form-control.d.ts.map +1 -0
  21. package/dist/manifest/form-control.js +5 -0
  22. package/dist/manifest/load.d.ts +11 -0
  23. package/dist/manifest/load.d.ts.map +1 -0
  24. package/dist/manifest/load.js +64 -0
  25. package/dist/manifest/naming.d.ts +7 -0
  26. package/dist/manifest/naming.d.ts.map +1 -0
  27. package/dist/manifest/naming.js +6 -0
  28. package/dist/manifest/packages.d.ts +6 -0
  29. package/dist/manifest/packages.d.ts.map +1 -0
  30. package/dist/manifest/packages.js +5 -0
  31. package/dist/manifest/types.d.ts +7 -0
  32. package/dist/manifest/types.d.ts.map +1 -0
  33. package/dist/manifest/types.js +1 -0
  34. package/dist/transform/index.d.ts +20 -0
  35. package/dist/transform/index.d.ts.map +1 -0
  36. package/dist/transform/index.js +11 -0
  37. package/dist/transform/parse.d.ts +19 -0
  38. package/dist/transform/parse.d.ts.map +1 -0
  39. package/dist/transform/parse.js +33 -0
  40. package/dist/transform/shared.d.ts +62 -0
  41. package/dist/transform/shared.d.ts.map +1 -0
  42. package/dist/transform/shared.js +96 -0
  43. package/dist/transform/to-angular.d.ts +7 -0
  44. package/dist/transform/to-angular.d.ts.map +1 -0
  45. package/dist/transform/to-angular.js +153 -0
  46. package/dist/transform/to-jsx.d.ts +7 -0
  47. package/dist/transform/to-jsx.d.ts.map +1 -0
  48. package/dist/transform/to-jsx.js +172 -0
  49. package/package.json +46 -4
@@ -0,0 +1,143 @@
1
+ /**
2
+ * CEM plugin: generates the `@lit/react` wrapper for every NYSDS component
3
+ * into `packages/react/src/generated/` (decision R1).
4
+ *
5
+ * The output directory is cleared and recreated on every run, so removed
6
+ * components leave no orphans. A hand-written file at
7
+ * `src/overrides/<ClassName>.ts` replaces the generated one: the component
8
+ * is skipped and the barrel re-exports the override.
9
+ */
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { listComponents } from "./lib/core.mjs";
13
+
14
+ /** Event interface names the platform provides; never imported. */
15
+ const GLOBAL_EVENT_TYPES = new Set([
16
+ "Event",
17
+ "CustomEvent",
18
+ "UIEvent",
19
+ "FocusEvent",
20
+ "InputEvent",
21
+ "KeyboardEvent",
22
+ "MouseEvent",
23
+ "PointerEvent",
24
+ "TouchEvent",
25
+ "WheelEvent",
26
+ "AnimationEvent",
27
+ "TransitionEvent",
28
+ "ClipboardEvent",
29
+ "DragEvent",
30
+ "SubmitEvent",
31
+ ]);
32
+
33
+ const IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
34
+
35
+ /**
36
+ * Splits event types into locally usable text and package type imports.
37
+ * Bare identifiers that are not platform globals are assumed to be typed
38
+ * aliases exported by the component package (section 4.3 of the plan).
39
+ * Anything else — including today's bare `CustomEvent` — is used verbatim.
40
+ */
41
+ export function resolveEventType(typeText) {
42
+ if (IDENTIFIER_RE.test(typeText) && !GLOBAL_EVENT_TYPES.has(typeText)) {
43
+ return { text: typeText, importName: typeText };
44
+ }
45
+ return { text: typeText, importName: undefined };
46
+ }
47
+
48
+ function renderReactWrapper(component) {
49
+ const { tag, className, packageName, events } = component;
50
+ const elementAlias = `${className}Element`;
51
+
52
+ const typeImports = new Set();
53
+ const eventLines = [];
54
+ const seenProps = new Set();
55
+ for (const event of events) {
56
+ // Two event names can map to one React prop (a deprecated camelCase
57
+ // alias like `nys-fileRemove` next to `nys-file-remove`). Keep the
58
+ // first, which is the canonical name in manifest order.
59
+ if (seenProps.has(event.reactProp)) continue;
60
+ seenProps.add(event.reactProp);
61
+ const { text, importName } = resolveEventType(event.typeText);
62
+ if (importName) typeImports.add(importName);
63
+ eventLines.push(` ${event.reactProp}: "${event.name}" as EventName<${text}>,`);
64
+ }
65
+
66
+ const lines = [];
67
+ lines.push(`"use client";`);
68
+ lines.push(
69
+ `// GENERATED by @nysds/codegen — do not edit. Override: src/overrides/${className}.ts`
70
+ );
71
+ lines.push(`import * as React from "react";`);
72
+ lines.push(
73
+ events.length > 0
74
+ ? `import { createComponent, type EventName } from "@lit/react";`
75
+ : `import { createComponent } from "@lit/react";`
76
+ );
77
+ lines.push(
78
+ `import { ${className} as ${elementAlias} } from "${packageName}";`
79
+ );
80
+ if (typeImports.size > 0) {
81
+ lines.push(
82
+ `import type { ${[...typeImports].sort().join(", ")} } from "${packageName}";`
83
+ );
84
+ }
85
+ lines.push(``);
86
+ lines.push(`export const ${className} = createComponent({`);
87
+ lines.push(` react: React,`);
88
+ lines.push(` tagName: "${tag}",`);
89
+ lines.push(` elementClass: ${elementAlias},`);
90
+ lines.push(` displayName: "${className}",`);
91
+ if (eventLines.length > 0) {
92
+ lines.push(` events: {`);
93
+ lines.push(...eventLines);
94
+ lines.push(` },`);
95
+ }
96
+ lines.push(`});`);
97
+ lines.push(``);
98
+ lines.push(
99
+ `export type ${className}Props = React.ComponentProps<typeof ${className}>;`
100
+ );
101
+ lines.push(`export type { ${elementAlias} };`);
102
+ lines.push(``);
103
+ return lines.join("\n");
104
+ }
105
+
106
+ export function reactPlugin(options = {}) {
107
+ const {
108
+ outDir = "packages/react/src/generated",
109
+ overridesDir = "packages/react/src/overrides",
110
+ } = options;
111
+
112
+ return {
113
+ name: "nysds-react-wrappers",
114
+
115
+ packageLinkPhase({ customElementsManifest }) {
116
+ const components = listComponents(customElementsManifest);
117
+ if (components.length === 0) return;
118
+
119
+ fs.rmSync(outDir, { recursive: true, force: true });
120
+ fs.mkdirSync(outDir, { recursive: true });
121
+
122
+ const barrel = [
123
+ `// GENERATED by @nysds/codegen — do not edit.`,
124
+ ];
125
+ for (const component of components) {
126
+ const overridePath = path.join(
127
+ overridesDir,
128
+ `${component.className}.ts`
129
+ );
130
+ if (fs.existsSync(overridePath)) {
131
+ barrel.push(`export * from "../overrides/${component.className}.js";`);
132
+ continue;
133
+ }
134
+ fs.writeFileSync(
135
+ path.join(outDir, `${component.className}.ts`),
136
+ renderReactWrapper(component)
137
+ );
138
+ barrel.push(`export * from "./${component.className}.js";`);
139
+ }
140
+ fs.writeFileSync(path.join(outDir, "index.ts"), barrel.join("\n") + "\n");
141
+ },
142
+ };
143
+ }
@@ -0,0 +1,228 @@
1
+ /**
2
+ * CEM plugin: generates the Vue typings for every NYSDS component into
3
+ * `packages/vue/src/generated/`.
4
+ *
5
+ * Per component, `<ClassName>.ts` exports:
6
+ * - `<ClassName>Props`, `<ClassName>Events`: the attributes, properties and
7
+ * `on<Event>` handlers a raw `<nys-*>` tag accepts.
8
+ * - `<ClassName>Slots`: the slot names from the manifest, typed for
9
+ * `<template #name>` on the wrapper.
10
+ * - `<ClassName>Model` (form controls only): `modelValue` and
11
+ * `onUpdate:modelValue`, derived from the `@formControl` tag.
12
+ * - `<ClassName>`: a Vue component (built by `createNysComponent` in
13
+ * `src/runtime.ts`) that renders the element, maps slots to light-DOM
14
+ * children, and supports `v-model` on form controls.
15
+ *
16
+ * Plus:
17
+ * - `index.ts` is the barrel.
18
+ * - `global.ts` augments `vue`'s `GlobalComponents` (typed `<nys-*>` in
19
+ * templates via Volar / vue-tsc) and the global `JSX.IntrinsicElements`
20
+ * (typed `<nys-*>` in TSX/JSX).
21
+ *
22
+ * Prop types are picked from the element class, so they stay exact even where
23
+ * the manifest carries only a loose type string. The output directory is
24
+ * cleared on every run, so removed components leave no orphans.
25
+ */
26
+ import fs from "node:fs";
27
+ import path from "node:path";
28
+ import { listComponents } from "./lib/core.mjs";
29
+ import { resolveEventType } from "./react.mjs";
30
+
31
+ function renderVueProps(component) {
32
+ const { className, packageName, props, events, slots, formControl } =
33
+ component;
34
+ const elementAlias = `${className}Element`;
35
+ const propsName = `${className}Props`;
36
+
37
+ const typeImports = new Set();
38
+ const eventLines = [];
39
+ const seenProps = new Set();
40
+ for (const event of events) {
41
+ // Vue camelizes `@nys-change` to `onNysChange`, the same shape React
42
+ // uses, so two event names can collide here too. Keep the first.
43
+ if (seenProps.has(event.reactProp)) continue;
44
+ seenProps.add(event.reactProp);
45
+ const { text, importName } = resolveEventType(event.typeText);
46
+ if (importName) typeImports.add(importName);
47
+ if (event.description) {
48
+ eventLines.push(
49
+ ` /** ${event.description.replace(/\s*\n\s*/g, " ").replace(/\*\//g, "*\\/")} */`
50
+ );
51
+ }
52
+ eventLines.push(` ${event.reactProp}?: (event: ${text}) => void;`);
53
+ }
54
+
55
+ const propNames = [...new Set(props.map((prop) => prop.name))].sort();
56
+ const propsType =
57
+ propNames.length > 0
58
+ ? `Partial<Pick<${elementAlias}, ${propNames.map((n) => JSON.stringify(n)).join(" | ")}>>`
59
+ : `{}`;
60
+
61
+ const lines = [];
62
+ lines.push(
63
+ `// GENERATED by @nysds/codegen — do not edit. Regenerate with \`npm run cem\`.`
64
+ );
65
+ lines.push(
66
+ `import type { ${className} as ${elementAlias}${[...typeImports].sort().map((n) => `, ${n}`).join("")} } from "${packageName}";`
67
+ );
68
+ lines.push(`import "${packageName}";`);
69
+ lines.push(`import type { HTMLAttributes, ReservedProps } from "vue";`);
70
+ lines.push(
71
+ `import { createNysComponent, type NysComponent, type NysSlots } from "../runtime.js";`
72
+ );
73
+ lines.push(``);
74
+ lines.push(`/** Handlers for the events \`<${component.tag}>\` dispatches. */`);
75
+ lines.push(`export interface ${className}Events {`);
76
+ lines.push(...eventLines);
77
+ lines.push(`}`);
78
+ lines.push(``);
79
+ lines.push(`type ${className}Members = ${propsType};`);
80
+ lines.push(``);
81
+ lines.push(
82
+ `/** Everything \`<${component.tag}>\` accepts in a Vue template or TSX file. */`
83
+ );
84
+ lines.push(`export type ${propsName} = Omit<`);
85
+ lines.push(` HTMLAttributes,`);
86
+ lines.push(` keyof ${className}Members | keyof ${className}Events`);
87
+ lines.push(`> &`);
88
+ lines.push(` ReservedProps &`);
89
+ lines.push(` ${className}Members &`);
90
+ lines.push(` ${className}Events;`);
91
+ lines.push(``);
92
+ lines.push(`export type { ${elementAlias} };`);
93
+ lines.push(``);
94
+
95
+ // Slots: "" is the default slot. The default slot is always allowed: some
96
+ // elements take children without documenting one in the manifest.
97
+ const slotKeys = [
98
+ ...new Set(["default", ...slots.map((slot) => slot.name || "default")]),
99
+ ].sort();
100
+ lines.push(
101
+ `/** Slots of \`<${component.tag}>\`, fillable with \`<template #name>\` on the wrapper. */`
102
+ );
103
+ lines.push(
104
+ `export type ${className}SlotName = ${slotKeys.map((n) => JSON.stringify(n)).join(" | ")};`
105
+ );
106
+ lines.push(
107
+ `export type ${className}Slots = NysSlots<${className}SlotName>;`
108
+ );
109
+ lines.push(``);
110
+
111
+ // v-model: only where the manifest declares a form contract.
112
+ let modelType = "";
113
+ if (formControl) {
114
+ const modelValueType = `${elementAlias}[${JSON.stringify(formControl.kind)}]`;
115
+ lines.push(
116
+ `/** \`v-model\` binds \`${formControl.kind}\`; add \`.lazy\` to update on \`${formControl.changeEvent}\`. */`
117
+ );
118
+ lines.push(`export interface ${className}Model {`);
119
+ lines.push(` modelValue?: ${modelValueType};`);
120
+ lines.push(
121
+ ` "onUpdate:modelValue"?: (value: ${modelValueType}) => void;`
122
+ );
123
+ lines.push(`}`);
124
+ lines.push(``);
125
+ modelType = ` & ${className}Model`;
126
+ }
127
+
128
+ // Runtime wrapper.
129
+ const booleanProps = [
130
+ ...new Set(props.filter((prop) => prop.isBoolean).map((prop) => prop.name)),
131
+ ].sort();
132
+ lines.push(`export const ${className} = createNysComponent<`);
133
+ lines.push(
134
+ ` NysComponent<${propsName}${modelType}, ${className}Slots, ${elementAlias}>`
135
+ );
136
+ lines.push(`>({`);
137
+ lines.push(` tag: "${component.tag}",`);
138
+ lines.push(` name: "${className}",`);
139
+ lines.push(` props: ${JSON.stringify(propNames)},`);
140
+ lines.push(` booleanProps: ${JSON.stringify(booleanProps)},`);
141
+ if (formControl) {
142
+ const listener = (name) =>
143
+ events.find((event) => event.name === name)?.reactProp;
144
+ const changeListener = listener(formControl.changeEvent);
145
+ const inputListener = formControl.inputEvent
146
+ ? listener(formControl.inputEvent)
147
+ : undefined;
148
+ lines.push(` model: {`);
149
+ lines.push(` kind: "${formControl.kind}",`);
150
+ lines.push(` changeListener: "${changeListener}",`);
151
+ if (inputListener) lines.push(` inputListener: "${inputListener}",`);
152
+ lines.push(` },`);
153
+ }
154
+ lines.push(`});`);
155
+ lines.push(``);
156
+ return lines.join("\n");
157
+ }
158
+
159
+ function renderGlobal(components) {
160
+ const lines = [];
161
+ lines.push(`// GENERATED by @nysds/codegen — do not edit.`);
162
+ lines.push(`import type { DefineComponent } from "vue";`);
163
+ // A module augmentation only resolves if the program already loads the
164
+ // module; this import guarantees it does.
165
+ lines.push(`import type {} from "vue/jsx-runtime";`);
166
+ for (const c of components) {
167
+ lines.push(`import type { ${c.className}Props } from "./${c.className}.js";`);
168
+ }
169
+ lines.push(``);
170
+ lines.push(`declare module "vue" {`);
171
+ lines.push(` /** Typed \`<nys-*>\` tags in Vue templates (Volar / vue-tsc). */`);
172
+ lines.push(` interface GlobalComponents {`);
173
+ for (const c of components) {
174
+ lines.push(` "${c.tag}": DefineComponent<${c.className}Props>;`);
175
+ }
176
+ lines.push(` }`);
177
+ lines.push(`}`);
178
+ lines.push(``);
179
+ // Vue exposes JSX two ways: the global namespace (`vue/jsx`) and the
180
+ // `vue/jsx-runtime` module (`jsxImportSource: "vue"`). Augment both.
181
+ for (const [open, close, indent] of [
182
+ ["declare module \"vue/jsx-runtime\" {", "}", " "],
183
+ ["declare global {", "}", " "],
184
+ ]) {
185
+ lines.push(open);
186
+ lines.push(`${indent}namespace JSX {`);
187
+ lines.push(`${indent} /** Typed \`<nys-*>\` tags in TSX / JSX. */`);
188
+ lines.push(`${indent} interface IntrinsicElements {`);
189
+ for (const c of components) {
190
+ lines.push(`${indent} "${c.tag}": ${c.className}Props;`);
191
+ }
192
+ lines.push(`${indent} }`);
193
+ lines.push(`${indent}}`);
194
+ lines.push(close);
195
+ lines.push(``);
196
+ }
197
+ lines.push(`export {};`);
198
+ lines.push(``);
199
+ return lines.join("\n");
200
+ }
201
+
202
+ export function vuePlugin(options = {}) {
203
+ const { outDir = "packages/vue/src/generated" } = options;
204
+
205
+ return {
206
+ name: "nysds-vue-types",
207
+
208
+ packageLinkPhase({ customElementsManifest }) {
209
+ const components = listComponents(customElementsManifest);
210
+ if (components.length === 0) return;
211
+
212
+ fs.rmSync(outDir, { recursive: true, force: true });
213
+ fs.mkdirSync(outDir, { recursive: true });
214
+
215
+ const barrel = [`// GENERATED by @nysds/codegen — do not edit.`];
216
+ for (const component of components) {
217
+ fs.writeFileSync(
218
+ path.join(outDir, `${component.className}.ts`),
219
+ renderVueProps(component)
220
+ );
221
+ barrel.push(`export * from "./${component.className}.js";`);
222
+ }
223
+ barrel.push(`import "./global.js";`);
224
+ fs.writeFileSync(path.join(outDir, "global.ts"), renderGlobal(components));
225
+ fs.writeFileSync(path.join(outDir, "index.ts"), barrel.join("\n") + "\n");
226
+ },
227
+ };
228
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @nysds/codegen public API.
3
+ *
4
+ * One package that reads the custom elements manifest and derives every
5
+ * framework artifact: metadata for generators, naming rules, and the HTML
6
+ * to JSX / Angular snippet transformer. The CEM plugins ship separately as
7
+ * `@nysds/codegen/cem-plugins`.
8
+ */
9
+ export { loadManifest } from "./manifest/load.js";
10
+ export { listComponents, normalizeTypeText } from "./manifest/components.js";
11
+ export { parseFormControlTag } from "./manifest/form-control.js";
12
+ export { isPublicMember, isPublicProp, isExposedEvent, } from "./manifest/filters.js";
13
+ export { NYS_PREFIX, NYS_BLUR_EVENT, pascalize, tagToClass, classToAngularClass, eventToReactProp, eventToAngularOutput, tagToSubpath, tagToPackage, } from "./manifest/naming.js";
14
+ export type { Manifest, ManifestModule, ComponentMeta, PropMeta, EventMeta, SlotMeta, FormControlMeta, } from "./manifest/types.js";
15
+ export { transformExample, toJsx, toAngular } from "./transform/index.js";
16
+ export type { TransformExampleInput, TransformResult, FormsMode, } from "./transform/index.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EACL,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,cAAc,EACd,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,SAAS,GACV,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @nysds/codegen public API.
3
+ *
4
+ * One package that reads the custom elements manifest and derives every
5
+ * framework artifact: metadata for generators, naming rules, and the HTML
6
+ * to JSX / Angular snippet transformer. The CEM plugins ship separately as
7
+ * `@nysds/codegen/cem-plugins`.
8
+ */
9
+ export { loadManifest } from "./manifest/load.js";
10
+ export { listComponents, normalizeTypeText } from "./manifest/components.js";
11
+ export { parseFormControlTag } from "./manifest/form-control.js";
12
+ export { isPublicMember, isPublicProp, isExposedEvent, } from "./manifest/filters.js";
13
+ export { NYS_PREFIX, NYS_BLUR_EVENT, pascalize, tagToClass, classToAngularClass, eventToReactProp, eventToAngularOutput, tagToSubpath, tagToPackage, } from "./manifest/naming.js";
14
+ export { transformExample, toJsx, toAngular } from "./transform/index.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Component metadata reader. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { listComponents, normalizeTypeText, } from "../../cem-plugins/lib/core.mjs";
6
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/manifest/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,iBAAiB,GAClB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Component metadata reader. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { listComponents, normalizeTypeText, } from "../../cem-plugins/lib/core.mjs";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Member and event filters. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { isPublicMember, isPublicProp, isExposedEvent, } from "../../cem-plugins/lib/core.mjs";
6
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/manifest/filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Member and event filters. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { isPublicMember, isPublicProp, isExposedEvent, } from "../../cem-plugins/lib/core.mjs";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `@formControl` tag parsing. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { parseFormControlTag } from "../../cem-plugins/lib/core.mjs";
6
+ //# sourceMappingURL=form-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-control.d.ts","sourceRoot":"","sources":["../../src/manifest/form-control.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * `@formControl` tag parsing. Logic lives in `cem-plugins/lib/core.mjs`;
3
+ * this module re-exports it with types.
4
+ */
5
+ export { parseFormControlTag } from "../../cem-plugins/lib/core.mjs";
@@ -0,0 +1,11 @@
1
+ import type { Manifest } from "./types.js";
2
+ /**
3
+ * Loads and validates a custom elements manifest.
4
+ *
5
+ * Without an argument, resolves the manifest that ships with
6
+ * `@nysds/components`. The root package's `exports` map doesn't expose
7
+ * `./custom-elements.json` as a subpath, so resolution goes through the
8
+ * package entry point and walks up to the package root.
9
+ */
10
+ export declare function loadManifest(manifestPath?: string): Manifest;
11
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/manifest/load.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,YAAY,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAW5D"}
@@ -0,0 +1,64 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createRequire } from "node:module";
4
+ /**
5
+ * Loads and validates a custom elements manifest.
6
+ *
7
+ * Without an argument, resolves the manifest that ships with
8
+ * `@nysds/components`. The root package's `exports` map doesn't expose
9
+ * `./custom-elements.json` as a subpath, so resolution goes through the
10
+ * package entry point and walks up to the package root.
11
+ */
12
+ export function loadManifest(manifestPath) {
13
+ const resolved = manifestPath ?? defaultManifestPath();
14
+ let raw;
15
+ try {
16
+ raw = JSON.parse(fs.readFileSync(resolved, "utf8"));
17
+ }
18
+ catch (error) {
19
+ throw new Error(`Cannot read manifest at ${resolved}: ${error.message}`);
20
+ }
21
+ return validateManifest(raw, resolved);
22
+ }
23
+ function defaultManifestPath() {
24
+ const require = createRequire(import.meta.url);
25
+ let entry;
26
+ try {
27
+ entry = require.resolve("@nysds/components");
28
+ }
29
+ catch {
30
+ throw new Error("Cannot resolve @nysds/components. Install it, or pass an explicit manifest path to loadManifest().");
31
+ }
32
+ let dir = path.dirname(entry);
33
+ for (let depth = 0; depth < 4; depth += 1) {
34
+ const candidate = path.join(dir, "custom-elements.json");
35
+ if (fs.existsSync(candidate))
36
+ return candidate;
37
+ const parent = path.dirname(dir);
38
+ if (parent === dir)
39
+ break;
40
+ dir = parent;
41
+ }
42
+ throw new Error(`Found @nysds/components at ${entry} but no custom-elements.json near it. Pass an explicit manifest path to loadManifest().`);
43
+ }
44
+ /** Light structural validation: enough to fail fast on the wrong file. */
45
+ function validateManifest(raw, source) {
46
+ if (typeof raw !== "object" || raw === null) {
47
+ throw new Error(`${source} is not a custom elements manifest: not an object.`);
48
+ }
49
+ const manifest = raw;
50
+ if (!Array.isArray(manifest.modules)) {
51
+ throw new Error(`${source} is not a custom elements manifest: missing "modules" array.`);
52
+ }
53
+ for (const mod of manifest.modules) {
54
+ const candidate = mod;
55
+ if (typeof candidate?.path !== "string") {
56
+ throw new Error(`${source} is not a custom elements manifest: a module has no "path".`);
57
+ }
58
+ if (candidate.declarations !== undefined &&
59
+ !Array.isArray(candidate.declarations)) {
60
+ throw new Error(`${source} is not a custom elements manifest: "declarations" of ${candidate.path} is not an array.`);
61
+ }
62
+ }
63
+ return raw;
64
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Naming rules (README section 4.1 of the framework-support plan is
3
+ * normative). Logic lives in `cem-plugins/lib/core.mjs`; this module
4
+ * re-exports it with types.
5
+ */
6
+ export { NYS_PREFIX, NYS_BLUR_EVENT, pascalize, tagToClass, classToAngularClass, eventToReactProp, eventToAngularOutput, tagToSubpath, tagToPackage, } from "../../cem-plugins/lib/core.mjs";
7
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/manifest/naming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,UAAU,EACV,cAAc,EACd,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,YAAY,GACb,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Naming rules (README section 4.1 of the framework-support plan is
3
+ * normative). Logic lives in `cem-plugins/lib/core.mjs`; this module
4
+ * re-exports it with types.
5
+ */
6
+ export { NYS_PREFIX, NYS_BLUR_EVENT, pascalize, tagToClass, classToAngularClass, eventToReactProp, eventToAngularOutput, tagToSubpath, tagToPackage, } from "../../cem-plugins/lib/core.mjs";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Package derivation from manifest module paths. Logic lives in
3
+ * `cem-plugins/lib/core.mjs`; this module re-exports it with types.
4
+ */
5
+ export { tagToPackage } from "../../cem-plugins/lib/core.mjs";
6
+ //# sourceMappingURL=packages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.d.ts","sourceRoot":"","sources":["../../src/manifest/packages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Package derivation from manifest module paths. Logic lives in
3
+ * `cem-plugins/lib/core.mjs`; this module re-exports it with types.
4
+ */
5
+ export { tagToPackage } from "../../cem-plugins/lib/core.mjs";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Metadata types. Declared once in `cem-plugins/lib/core.d.mts` (next to the
3
+ * runtime rules) and re-exported here so the TypeScript API and the plugins
4
+ * can never disagree.
5
+ */
6
+ export type { Manifest, ManifestModule, ComponentMeta, PropMeta, EventMeta, SlotMeta, FormControlMeta, } from "../../cem-plugins/lib/core.mjs";
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/manifest/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,GAChB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { Manifest } from "../manifest/types.js";
2
+ import type { FormsMode, TransformResult } from "./shared.js";
3
+ export type { FormsMode, TransformResult } from "./shared.js";
4
+ export { toJsx } from "./to-jsx.js";
5
+ export { toAngular } from "./to-angular.js";
6
+ export interface TransformExampleInput {
7
+ /** The canonical HTML example. */
8
+ html: string;
9
+ framework: "react" | "angular";
10
+ manifest: Manifest;
11
+ /**
12
+ * How form components render. `"none"` (default) keeps snippets static;
13
+ * `"template"` emits `[(ngModel)]` (Angular) or the controlled pattern
14
+ * (React); `"reactive"` emits `formControlName` (Angular).
15
+ */
16
+ formsMode?: FormsMode;
17
+ }
18
+ /** Transforms one HTML example into a framework snippet. */
19
+ export declare function transformExample(input: TransformExampleInput): TransformResult;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transform/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI9D,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,qBAAqB;IACpC,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,qBAAqB,GAC3B,eAAe,CAKjB"}
@@ -0,0 +1,11 @@
1
+ import { toJsx } from "./to-jsx.js";
2
+ import { toAngular } from "./to-angular.js";
3
+ export { toJsx } from "./to-jsx.js";
4
+ export { toAngular } from "./to-angular.js";
5
+ /** Transforms one HTML example into a framework snippet. */
6
+ export function transformExample(input) {
7
+ const formsMode = input.formsMode ?? "none";
8
+ return input.framework === "react"
9
+ ? toJsx(input.html, input.manifest, formsMode)
10
+ : toAngular(input.html, input.manifest, formsMode);
11
+ }
@@ -0,0 +1,19 @@
1
+ import type { DefaultTreeAdapterMap } from "parse5";
2
+ export type P5Node = DefaultTreeAdapterMap["childNode"];
3
+ export type P5Element = DefaultTreeAdapterMap["element"];
4
+ export type P5Text = DefaultTreeAdapterMap["textNode"];
5
+ export type P5Comment = DefaultTreeAdapterMap["commentNode"];
6
+ /**
7
+ * Parses an HTML fragment (a docs `preview` block or an `@example` block)
8
+ * into parse5 nodes. parse5 lowercases element and attribute names, matching
9
+ * what a browser does to the same markup.
10
+ */
11
+ export declare function parseHtmlFragment(html: string): P5Node[];
12
+ export declare function isElement(node: P5Node): node is P5Element;
13
+ export declare function isText(node: P5Node): node is P5Text;
14
+ export declare function isComment(node: P5Node): node is P5Comment;
15
+ /** Child nodes, reading through `<template>` content. */
16
+ export declare function childNodesOf(element: P5Element): P5Node[];
17
+ /** Concatenated text content of an element's direct text children. */
18
+ export declare function textContent(element: P5Element): string;
19
+ //# sourceMappingURL=parse.d.ts.map