UNPKG

@stencil/react-output-target

Version:

React output target for @stencil/core components.

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