UNPKG

@stencil/react-output-target

Version:

React output target for @stencil/core components.

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