UNPKG

@stencil/react-output-target

Version:

React output target for @stencil/core components.

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