@stencil/react-output-target
Version:
React output target for @stencil/core components.
392 lines (384 loc) • 13.1 kB
JavaScript
import D, { isAbsolute as Q, relative as X } from "node:path";
import { Project as x, VariableDeclarationKind as A } from "ts-morph";
const H = (t) => t.toLowerCase().split("-").map((n) => n.charAt(0).toUpperCase() + n.slice(1)).join(""), Z = (t) => t.replace(/-([_a-z])/g, (n, c) => c.toUpperCase()), ee = (t) => t.replace(/\/([a-z])/g, (n, c) => c.toUpperCase()), te = (t) => {
const n = ee(t);
return Z(`on-${n}`);
}, ne = (t) => t.replace(/\/\/.*$/gm, "").replace(/\n/g, " ").replace(/\s{2,}/g, " ").trim(), L = async ({
components: t,
project: n,
outDir: c,
filename: b = "components.ts",
componentSuffix: l = "",
serializeShadowRoot: g
}) => {
const $ = n || new x({ useInMemoryFileSystem: !0 }), T = `/* eslint-disable */
`, y = `/**
* This file was automatically generated by the Stencil React Output Target.
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
*/
`, v = D.join(c || "", b), p = $.createSourceFile(v, y + T, {
overwrite: !0
});
l && (p.addImportDeclaration({
moduleSpecifier: "@stencil/react-output-target/ssr",
namedImports: [{ name: "SerializeShadowRootOptions", isTypeOnly: !0 }]
}), p.addVariableStatement({
isExported: !0,
declarationKind: A.Const,
declarations: [
{
name: "serializeShadowRoot",
type: "SerializeShadowRootOptions",
initializer: g ? JSON.stringify(g) : '{ default: "declarative-shadow-dom" }'
}
]
}));
for (const f of t) {
const h = f.tagName, E = H(h), r = f.tagName;
p.addExportDeclaration({
moduleSpecifier: `./${r}${l}.js`,
namedExports: [E]
});
}
return p.organizeImports(), p.formatText(), await p.save(), p;
}, M = ({
components: t,
stencilPackageName: n,
customElementsDir: c,
componentsTypesDir: b,
hydrateModule: l,
clientModule: g,
serializeShadowRoot: $,
transformTag: T,
exportMaps: y,
typesFromComponentsFile: v
}) => {
const p = new x({ useInMemoryFileSystem: !0 }), f = y ? `${n}/components` : `${n}/${b}`, h = y || v ? f : n, E = `'use client';
`, r = `/**
* This file was automatically generated by the Stencil React Output Target.
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
*/
`, C = `/* eslint-disable */
`, i = l ? [
T ? `import { getTagTransformer } from './tag-transformer.js';
` : "",
"import { createComponent, type SerializeShadowRootOptions, type HydrateModule, type ReactWebComponent } from '@stencil/react-output-target/ssr';"
].filter(Boolean).join(`
`) : "import { createComponent } from '@stencil/react-output-target/runtime';", d = T ? `import { transformTag } from './tag-transformer.js';
` : "", e = p.createSourceFile(
"component.ts",
`${E}${r}${C}
import React from 'react';
${i}
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
${d}
import type { Components } from "${f}";
`
);
l && g && e.addImportDeclaration({
moduleSpecifier: g,
namespaceImport: "clientComponents"
}), l && e.addVariableStatement({
isExported: !0,
declarationKind: A.Const,
declarations: [
{
name: "serializeShadowRoot",
type: "SerializeShadowRootOptions",
initializer: $ ? JSON.stringify($) : '{ default: "declarative-shadow-dom" }'
}
]
});
for (const s of t) {
const m = s.tagName, u = H(m), S = `${u}Element`, I = `${u}CustomEvent`;
e.addImportDeclaration({
moduleSpecifier: y ? `${n}/${m}` : `${n}/${c}/${m}.js`,
namedImports: [
{
name: u,
alias: S
},
{
name: "defineCustomElement",
alias: `define${u}`
}
]
});
const F = (s.events || []).filter((o) => o.internal === !1), N = [], z = /* @__PURE__ */ new Set();
let q = !1;
for (const o of F) {
if (Object.keys(o.complexType.references).length > 0)
for (const R of Object.keys(o.complexType.references))
!(o.complexType.references[R].location === "global") && !z.has(R) && (z.add(R), e.addImportDeclaration({
moduleSpecifier: h,
namedImports: [
{
name: R,
isTypeOnly: !0
}
]
}));
q || (q = !0, e.addImportDeclaration({
moduleSpecifier: h,
namedImports: [
{
name: I,
isTypeOnly: !0
}
]
})), N.push({
originalName: o.name,
name: te(o.name),
type: `EventName<${I}<${ne(o.complexType.original)}>>`
});
}
const _ = `${u}Events`, V = s.properties.filter((o) => o.required && !o.internal).map((o) => `'${o.name}'`), O = V.length > 0 ? `, ${V.join(" | ")}` : "";
e.addTypeAlias({
isExported: !0,
name: _,
type: N.length > 0 ? `{ ${N.map((o) => `${o.name}: ${o.type}`).join(`,
`)} }` : "NonNullable<unknown>"
});
const Y = T ? `,
transformTag` : "", k = `/*@__PURE__*/ createComponent<${S}, ${_}, Components.${u}${O}>({
tagName: '${m}',
elementClass: ${S},
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
react: React,
events: {${N.map((o) => `${o.name}: '${o.originalName}'`).join(`,
`)}} as ${_},
defineCustomElement: define${u}${Y}
})`, B = T ? `,
getTagTransformer` : "", W = `/*@__PURE__*/ createComponent<${S}, ${_}, Components.${u}${O}>({
tagName: '${m}',
properties: {${s.properties.filter((o) => !!o.attribute).map((o) => `${o.name}: '${o.attribute}'`).join(`,
`)}},
hydrateModule: typeof window === 'undefined' ? (import('${l}') as Promise<HydrateModule>) : undefined,
clientModule: clientComponents.${u} as StencilReactComponent<${S}, ${_}, Components.${u}${O}>,
serializeShadowRoot${B}
})`;
e.addVariableStatement({
isExported: !0,
declarationKind: A.Const,
declarations: [
{
name: u,
type: `StencilReactComponent<${S}, ${_}, Components.${u}${O}>`,
initializer: l ? W : k
}
]
});
}
if (e.organizeImports(), l && g) {
const s = e.getImportDeclarations().find((m) => {
var u;
return ((u = m.getNamespaceImport()) == null ? void 0 : u.getText()) === "clientComponents";
});
s && e.insertText(
s.getStart(),
`// @ts-ignore - ignore potential type issues as the project is importing itself
`
);
}
return e.formatText(), e.getFullText();
}, oe = ({
stencilPackageName: t,
customElementsDir: n,
exportMaps: c
}) => `/* eslint-disable */
/* tslint:disable */
import { setTagTransformer as clientSetTagTransformer } from '${c ? `${t}/standalone` : `${t}/${n}/index.js`}';
let tagTransformer: ((tagName: string) => string) | undefined;
export const setTagTransformer = (transformer: (tagName: string) => string) => {
clientSetTagTransformer(transformer);
tagTransformer = transformer;
};
export const transformTag = (tag: string): string => {
return tagTransformer ? tagTransformer(tag) : tag;
};
export const getTagTransformer = () => tagTransformer;
`, re = async ({
stencilPackageName: t,
components: n,
outDir: c,
esModules: b,
customElementsDir: l,
componentsTypesDir: g,
excludeComponents: $,
project: T,
hydrateModule: y,
clientModule: v,
excludeServerSideRenderingFor: p,
serializeShadowRoot: f,
transformTag: h,
exportMaps: E,
typesFromComponentsFile: r
}) => {
const C = [], a = n.filter((e) => !(e.internal === !0 || $ != null && $.includes(e.tagName)));
if (a.length === 0)
return [];
const i = {};
function d(e, s = "components") {
const m = D.join(c, `${s}.ts`), u = M({
components: e,
stencilPackageName: t,
customElementsDir: l,
componentsTypesDir: g,
exportMaps: E,
typesFromComponentsFile: r,
transformTag: h
});
if (i[m] = u, h) {
const S = D.join(c, "tag-transformer.ts");
i[S] = oe({ stencilPackageName: t, customElementsDir: l, exportMaps: E });
}
if (y) {
const S = D.join(c, `${s}.server.ts`), I = M({
components: e.filter(
(F) => !p || !p.includes(F.tagName)
),
stencilPackageName: t,
customElementsDir: l,
componentsTypesDir: g,
exportMaps: E,
typesFromComponentsFile: r,
hydrateModule: y,
clientModule: v,
serializeShadowRoot: f,
transformTag: h
});
i[S] = I;
}
}
if (b) {
for (const s of a)
d([s], s.tagName);
const e = await L({ components: a, project: T, outDir: c });
if (C.push(e), y) {
const s = await L({
components: a.filter(
(m) => !p || !p.includes(m.tagName)
),
project: T,
outDir: c,
filename: "components.server.ts",
componentSuffix: ".server",
serializeShadowRoot: f
});
C.push(s);
}
} else
d(a);
return await Promise.all(
Object.entries(i).map(async ([e, s]) => {
const m = T.createSourceFile(e, s, { overwrite: !0 });
await m.save(), C.push(m);
})
), C;
}, w = "react-output-target", G = "dist/components", j = "dist-custom-elements", P = "standalone", J = "dist-hydrate-script", K = "ssr", ae = "types", se = "dist/types", U = (t, n) => (Q(n) ? X(t, n) : n).replace(/\\/g, "/"), me = ({
outDir: t,
esModules: n,
stencilPackageName: c,
excludeComponents: b,
customElementsDir: l,
hydrateModule: g,
clientModule: $,
excludeServerSideRenderingFor: T,
serializeShadowRoot: y,
transformTag: v
}) => {
let p = G, f = G, h = !1, E = !1;
return {
type: "custom",
name: w,
validate(r) {
const C = (r.outputTargets || []).some(
(a) => ["loader-bundle", "standalone", "ssr", "types"].includes(a.type)
);
if (h = C && r.generateExportMaps === !0, E = C, l)
p = l, f = l;
else {
const a = (r.outputTargets || []).find(
(i) => i.type === j || i.type === P
);
if (a == null) {
const d = (r.outputTargets || []).some(
(e) => ["loader-bundle", "standalone", "ssr", "types"].includes(e.type)
) ? P : j;
throw new Error(
`The '${w}' requires '${d}' output target. Add { type: '${d}' }, to the outputTargets config.`
);
}
if (a.type === P) {
const i = (r.outputTargets || []).find((s) => s.type === ae), d = (i == null ? void 0 : i.dir) ?? se;
if (f = `${U(r.rootDir, d)}/components`, a.dir !== void 0) {
const s = a.dir;
p = U(r.rootDir, s);
}
} else if (a.dir !== void 0) {
const i = a.dir;
p = U(r.rootDir, i), f = p;
}
if (a.type === j && a.externalRuntime !== !1)
throw new Error(
`The '${w}' requires the '${j}' output target to have 'externalRuntime: false' set in its configuration.`
);
}
if (g) {
if ((r.outputTargets || []).find(
(i) => i.type === J || i.type === K
) == null) {
const d = (r.outputTargets || []).some(
(e) => ["loader-bundle", "standalone", "ssr", "types"].includes(e.type)
) ? K : J;
throw new Error(
`The '${w}' requires '${d}' output target when the 'hydrateModule' option is set. Add { type: '${d}' }, to the outputTargets config.`
);
}
if ($ == null)
throw new Error(
`The '${w}' requires the 'clientModule' option when the 'hydrateModule' option is set. Please provide the clientModule manually to the ${w} output target.`
);
}
if (c === void 0) {
if (r.sys && r.packageJsonFilePath) {
const { name: a } = JSON.parse(r.sys.readFileSync(r.packageJsonFilePath, "utf8"));
c = a;
}
if (!c)
throw new Error(
`Unable to find the package name in the package.json file: ${r.packageJsonFilePath}. Please provide the stencilPackageName manually to the ${w} output target.`
);
}
},
async generator(r, C, a) {
const i = a.createTimeSpan(`generate ${w} started`, !0), d = a.components, e = new x(), s = await re({
outDir: t,
components: d,
stencilPackageName: c,
customElementsDir: p,
componentsTypesDir: f,
excludeComponents: b,
esModules: n === !0,
project: e,
hydrateModule: g,
clientModule: $,
excludeServerSideRenderingFor: T,
serializeShadowRoot: y,
transformTag: v,
exportMaps: h,
typesFromComponentsFile: E
});
await Promise.all(
s.map((m) => C.fs.writeFile(m.getFilePath(), m.getFullText()))
), i.finish(`generate ${w} finished`);
},
__internal_getCustomElementsDir() {
return p;
}
};
};
export {
me as reactOutputTarget
};
//# sourceMappingURL=index.js.map