@knapsack/renderer-react 4.70.0--canary.3797.b249674.0 → 4.70.0--canary.4821.56b0218.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -1,53 +1,1294 @@
1
- 'use strict';
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2
29
 
3
- var Ie = require('sleep-promise');
4
- var rendererWebpackBase = require('@knapsack/renderer-webpack-base');
5
- var utils = require('@knapsack/utils');
6
- var app = require('@knapsack/app');
7
- var renderers = require('@knapsack/app/renderers');
8
- var types = require('@knapsack/types');
9
- var fileUtils = require('@knapsack/file-utils');
10
- var h = require('path');
11
- var creatorUtils = require('@knapsack/creator-utils');
12
- var ksFileUtils = require('@knapsack/ks-file-utils');
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ KnapsackReactRenderer: () => KnapsackReactRenderer
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
13
36
 
14
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
37
+ // src/renderer-react.ts
38
+ var import_sleep_promise = __toESM(require("sleep-promise"));
39
+ var import_renderer_webpack_base = require("@knapsack/renderer-webpack-base");
40
+ var import_utils3 = require("@knapsack/utils");
41
+ var import_app2 = require("@knapsack/app");
42
+ var import_renderers = require("@knapsack/app/renderers");
43
+ var import_types2 = require("@knapsack/types");
44
+ var import_file_utils3 = require("@knapsack/file-utils");
45
+ var import_path2 = require("path");
15
46
 
16
- var Ie__default = /*#__PURE__*/_interopDefault(Ie);
17
- var h__default = /*#__PURE__*/_interopDefault(h);
18
-
19
- var N=Object.defineProperty;var c=(r,e)=>N(r,"name",{value:e,configurable:!0}),K=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});function ee({templateName:r,attributes:e,children:t}){return `
20
- <${r}
21
- ${e}
22
- ${t?`>
23
- ${t}
24
- </${r}>`:"/>"}
25
- `}c(ee,"renderUsageTemplate");var O="DemoApp";function te({imports:r="",children:e}){return `${r}
47
+ // src/utils.ts
48
+ var import_app = require("@knapsack/app");
49
+ var import_file_utils = require("@knapsack/file-utils");
50
+ var import_utils = require("@knapsack/utils");
51
+ var import_path = __toESM(require("path"));
52
+ var import_types = require("@knapsack/types");
53
+ function renderUsageTemplate({
54
+ templateName,
55
+ attributes,
56
+ children
57
+ }) {
58
+ return `
59
+ <${templateName}
60
+ ${attributes}
61
+ ${children ? `>
62
+ ${children}
63
+ </${templateName}>` : "/>"}
64
+ `;
65
+ }
66
+ __name(renderUsageTemplate, "renderUsageTemplate");
67
+ var demoAppName = "DemoApp";
68
+ function renderDemoAppTemplate({
69
+ imports = "",
70
+ children
71
+ }) {
72
+ return `${imports}
26
73
 
27
- function ${O}() {
74
+ function ${demoAppName}() {
28
75
  return (
29
- ${e}
76
+ ${children}
30
77
  )
31
78
  }
32
- `}c(te,"renderDemoAppTemplate");async function M(r){let e=Object.keys(r.props||{}).map(n=>{let p=r.props[n];return {key:n,value:p}}),{templateName:t,children:s,extraProps:a=[]}=r;if(!t)throw new Error('Cannot getUsage of a React Component when no "templateName" is provided.');let o=e.map(({key:n,value:p})=>{switch(typeof p){case"string":return p.startsWith("(")&&p.includes("=>")?`${n}={${p}}`:`${n}="${p}"`;case"boolean":return p?`${n}`:`${n}={${p}}`;default:return `${n}={${JSON.stringify(p)}}`}}),i=[],l={};a.forEach(({key:n,value:p})=>{l[n]=l[n]??[],l[n].push(p);}),Object.entries(l).forEach(([n,p])=>{let u=p.length===1?p[0]:`<>${p.join(`
33
- `)}</>`;i.push(`${n}={${u}}`);});let m=ee({templateName:t,attributes:[...o,...i].join(" "),children:s});return r.format?fileUtils.formatCode({contents:m,path:"x.tsx"}).then(n=>n.trim()).catch(()=>m.trim()):m.trim()}c(M,"getUsage");async function v({children:r,imports:e,format:t}){let s=te({children:r,imports:e});return t?fileUtils.formatCode({contents:s,path:"x.tsx"}):s}c(v,"getDemoAppUsage");async function J({src:r}){let e=await fileUtils.findUp("tsconfig.json",{cwd:h__default.default.dirname(r)}),t=await import('react-docgen-typescript'),s={shouldExtractLiteralValuesFromEnum:!0,savePropValueAsString:!0,skipChildrenPropWithoutDoc:!1,customComponentTypes:["VoidFunctionComponent","VFC"]};return {info:(e?t.withCustomConfig(e,s).parse:t.withDefaultConfig(s).parse)(r)}}c(J,"getTypeScriptInfoFromFile");function re({info:r,exportName:e}){try{if(!r)return !1;let t={props:{$schema:"http://json-schema.org/draft-07/schema",type:"object",required:[],properties:{}},slots:{}},a=!e||e==="default"?r.pop():r.find(i=>i.displayName===e);if(!a)return !1;return Object.entries(a?.props||{}).forEach(([i,l])=>{let{name:m,description:n,defaultValue:p,required:u,type:f,parent:y}=l;switch(f?.name?.replace("| undefined","").replace(/<.*/g,"").trim()){case"string":t.props.properties[i]={type:"string"};break;case"number":t.props.properties[i]={type:"number"};break;case"boolean":case"bool":p&&"value"in p&&(p.value=p.value==="true"),t.props.properties[i]={type:"boolean"};break;case"enum":t.props.properties[i]={type:"string",enum:[...new Set(f.value.map(({value:d})=>utils.removeWrappingDoubleQuotes(d?.trim())).filter(Boolean))]};break;case"ReactNode":case"React.ReactNode":case"React.ReactElement":case"ReactElement":t.slots[i]={title:i},n&&(t.slots[i]={...t.slots[i],description:n});break;case"VFC":case"FC":t.slots[i]={title:i,description:n||"A reference to a component",isTemplateReference:!0,allowOnlyOne:!0,disallowText:!0};break;default:if(f?.name?.startsWith("("))t.props.properties[i]={typeof:"function",tsType:l?.type?.name};else if(f?.name?.includes("|")){let d=f.name.split("|").map(P=>utils.removeWrappingDoubleQuotes(P.trim())).filter(Boolean);d?.length&&(t.props.properties[i]={type:"string",enum:[...new Set(d)]});}else t.props.properties[i]={tsType:l?.type?.name};}t.props.properties[i]&&(u&&t.props.required.push(i),n&&!t.props.properties[i].description&&(t.props.properties[i].description=n),p&&"value"in p&&(types.isNumberProp(t.props.properties[i])?t.props.properties[i].default=parseFloat(p.value):t.props.properties[i].default=utils.removeWrappingDoubleQuotes(p.value)));}),t}catch(t){return app.log.verbose("Could not infer spec from React TypeScript file",{exportName:e,error:t},"react renderer"),!1}}c(re,"extractSpecFromTypeScriptInfo");async function se({src:r}){let e=await import('react-docgen'),{builtinResolvers:t}=e,s=await fileUtils.readFile(r),{FindExportedDefinitionsResolver:a}=t;return {info:e.parse(s,{resolver:new a,handlers:null,filename:r})}}c(se,"getPropTypesInfoFromFile");function ae({info:r,exportName:e}){try{let s=!e||e==="default"?r.pop():r.find(o=>o.displayName===e),a={isInferred:!0,props:{$schema:"http://json-schema.org/draft-07/schema",type:"object",required:[],properties:{}},slots:{}};return Object.entries(s?.props||{}).forEach(([o,i])=>{let{required:l,description:m,defaultValue:n}=i;switch(i?.type?.name){case"string":a.props.properties[o]={type:"string"};break;case"func":a.props.properties[o]={type:"string"};break;case"bool":a.props.properties[o]={type:"boolean"};break;case"node":a.slots[o]={title:o,description:m};}a.props.properties[o]&&(l&&a.props.required.push(o),m&&!a.props.properties[o].description&&(a.props.properties[o].description=m),n&&"value"in n&&(a.props.properties[o].default=typeof n.value=="string"?utils.removeWrappingDoubleQuotes(n.value):n.value));}),a}catch(t){return app.log.verbose("Could not infer spec from React PropTypes",{exportName:e,error:t},"react renderer"),!1}}c(ae,"extractSpecFromPropTypesInfo");function ne({spec:r}){return r===!1||Object.entries(r?.props?.properties||{}).forEach(([e,t])=>{types.isOptionsProp(t)&&(t.enum.includes(t.default)||(t.default=void 0));}),r}c(ne,"cleanUpSpec");async function oe({src:r,resolveFromDir:e}){let t=await fileUtils.resolvePath({path:r,resolveFromDir:e,resolveType:"types"});if(t.exists){let o=await J({src:t.absolutePath});if(o)return {type:"typescript",info:o.info}}let s=await fileUtils.resolvePath({path:r,resolveFromDir:e});if(!s.exists)return {type:"unknown"};let{ext:a}=h__default.default.parse(s.absolutePath);switch(a){case".jsx":return {type:"propTypes",info:(await se({src:s.absolutePath})).info};case".ts":case".tsx":return {type:"typescript",info:(await J({src:s.absolutePath})).info};default:return {type:"unknown"}}}c(oe,"getReactModuleInfoUncached");var $=new Map,V=c(()=>{app.log.info("Clearing React TypeScript inferSpec cache..."),$.clear();},"clearInferSpecCache");async function ie(r){let e=JSON.stringify(r);return $.has(e)||$.set(e,oe(r)),$.get(e)}c(ie,"getReactModuleInfo");async function pe({src:r,exportName:e,resolveFromDir:t}){let s=await ie({src:r,resolveFromDir:t});switch(s.type){case"typescript":return re({info:s.info,exportName:e});case"propTypes":return ae({info:s.info,exportName:e});case"unknown":default:return !1}}c(pe,"getReactSpec");async function B(r){return ne({spec:await pe(r)})}c(B,"getReactDocs");async function L(r,e){try{let{version:t}=fileUtils.getModulePkgJson("react"),{version:s}=fileUtils.getModulePkgJson("react-dom"),a=h__default.default.dirname(K.resolve("react",{paths:[process.cwd()]})),o=h__default.default.dirname(K.resolve("react-dom",{paths:[process.cwd()]}));await Promise.all([fileUtils.copy(h__default.default.join(a,"umd/react.development.js"),h__default.default.join(r,`react.development.${t}.js`)),fileUtils.copy(h__default.default.join(a,"umd/react.production.min.js"),h__default.default.join(r,`react.production.min.${t}.js`)),fileUtils.copy(h__default.default.join(o,"umd/react-dom.production.min.js"),h__default.default.join(r,`react-dom.production.min.${s}.js`)),fileUtils.copy(h__default.default.join(o,"umd/react-dom.development.js"),h__default.default.join(r,`react-dom.development.${s}.js`))]);let i=process.env.NODE_ENV==="production"?"production.min":"development";return [h__default.default.join(e,`react.${i}.${t}.js`),h__default.default.join(e,`react-dom.${i}.${s}.js`)]}catch(t){app.log.warn('Error trying to copy "react" and "react-dom" JS files, are they installed? We want to use your exact versions.',t,"templateRenderer:react"),process.exit(1);}}c(L,"copyReactAssets");function ye(r){return r.toUpperCase()===r}c(ye,"isCapitalLetter");function we(r){return ye(r[0])}c(we,"startsWithCapitalLetter");function Pe({importName:r,id:e,title:t=r,pkgPath:s,initialDemoId:a}){return {id:e,title:t,description:"",statuses:{main:"ready"},templates:[{id:"react",title:"react",path:s,alias:r,templateLanguageId:"react",spec:{isInferred:!0},demoIds:[a],blockIds:[]}],tabs:[{type:"template",id:"react"}],subPages:[]}}c(Pe,"createPatternData");var G=creatorUtils.createCreator({id:"react-patterns",title:"React Ks Patterns",description:"Adds React templates as Knapsack Patterns",getQuestions:c(async()=>({pkgPath:{type:"text",title:"Package path"},importPrefix:{type:"text",title:"Import Prefix to Remove"}}),"getQuestions"),getTasks:c(async({answers:{pkgPath:r,importPrefix:e=""},config:t})=>{let s=t.dest,o=(await ksFileUtils.readKsPatternConfigs({dataDir:s})).reduce((l,m)=>{let n=m.templates?.filter(p=>p.templateLanguageId==="react")??[];return l.push(...n.map(p=>p.alias)),l},[]),{exports:i}=await fileUtils.getJsExportNames({path:r});return [{title:"Pick Imports to add",task:c((l,m)=>creatorUtils.tasks.runSubCreator({task:m,config:t,creator:creatorUtils.createCreator({id:"react-pattern-import-names",getQuestions:c(async()=>({importNames:{type:"choices",choices:i.filter(n=>we(n)&&!o.includes(n)).map(n=>({value:n}))}}),"getQuestions"),getTasks:c(async({answers:{importNames:n}})=>{let p=n.map(u=>({importName:u,patternId:u.startsWith(e)?u.slice(e.length).toLowerCase():u.toLowerCase()}));return [...p.map(({importName:u,patternId:f})=>({title:`Add ${u} React Template`,task:c(async(y,R)=>{let d={type:"data",id:utils.makeShortId(),title:"Main",patternId:f,templateId:"react",data:{props:{},slots:{}}},P=Pe({id:f,importName:u,pkgPath:r,initialDemoId:d.id});await Promise.all([ksFileUtils.writeDemo({dataDir:s,demo:d}),ksFileUtils.writeKsPatternConfig({dataDir:s,patternId:f,data:P})]);},"task")})),{title:"Updating Nav",task:c(async(u,f)=>{let{byId:y}=await ksFileUtils.readKsNavConfig({dataDir:s}),R=Object.values(y).find(({path:d,name:P,id:w})=>d?!1:P.toLowerCase()==="patterns"||P.toLowerCase()==="components");await ksFileUtils.addKsNavItems({dataDir:s,navItems:p.map(({patternId:d})=>({navId:d,navPath:`/pattern/${d}`,navParent:R?.id||"root"}))});},"task")}]},"getTasks")})}),"task")}]},"getTasks")});var H="ks-react-meta";var{pkg:j}=fileUtils.findUpPkgJson(__dirname);app.log.setupUpdateNotifier({...j,name:j.name,version:j.version});var Q=class r extends rendererWebpackBase.RendererWebpackBase{static{c(this,"KnapsackReactRenderer");}assets;babelConfig;demoWrapperPath;disableReactStrictMode;constructor({webpackConfig:e,demoWrapperPath:t=h.join(__dirname,"./demo-wrapper.mjs"),id:s=types.rendererIds.react,disableReactStrictMode:a}={}){super({id:s,extension:".jsx",language:"jsx",webpackConfig:e,extraScripts:["@knapsack/renderer-react/client"]}),this.language="jsx",this.assets=[],this.demoWrapperPath=t,this.disableReactStrictMode=a,this.creators=[G];}init=c(async e=>{if(await super.init(e),this.assets=await L(this.outputDir,this.publicPath),!await fileUtils.exists(this.demoWrapperPath))throw new Error(`Could not find demo wrapper at: "${this.demoWrapperPath}"`)},"init");getMeta=c(()=>({id:this.id,title:"React",aliasUse:"optional",aliasTitle:"Named Export",aliasIsJsNamedExport:!0,aliasDescription:"If `export X` was used instead of `export default`, then provide X.",enableDataDemos:!0,enableTemplateDemos:!0,hasSlotsSupport:!0,hasSlotOptionsSupport:!0,version:j.version,hasInferSpecSupport:!0,syntaxHighlightingLanguage:"jsx",hasTemplateSuggestionsSupport:!0,prototypingTemplate:{path:"@knapsack/renderer-react/prototype-template",spec:{isInferred:!1,props:{type:"object",properties:{}},slots:{children:{title:"Children"}}}}}),"getMeta");changeCase=c(e=>utils.pascalCase(e),"changeCase");createWebpackConfig=c(()=>{let e=super.createWebpackConfig();return e.externals={react:"React","react-dom":"ReactDOM"},e},"createWebpackConfig");getJsImports=c(()=>{let e=super.getJsImports();return e.push({type:"extra",importInfo:{type:"default",path:this.demoWrapperPath,name:"DemoWrapper"}},{type:"extra",importInfo:{type:"default",path:h.join(__dirname,"./error-catcher.mjs"),name:"ErrorCatcher"}}),e},"getJsImports");async prepClientRenderResults({usage:e,demoApp:t,imports:s,renderOptions:{pattern:a,template:o,demo:i}}){let l=this.getJsImports().filter(d=>d.type==="extra"),{imports:m,isDeclaredVarsUnique:n,nameCollisions:p}=this.makeKsJsImportsUnique({imports:[...s,...l]});n||app.log.error(`${p.join(", ")} are declared multiple times`,{imports:m});let u={demo:i,disableReactStrictMode:this.disableReactStrictMode,neededImports:m,demoWrapperProps:{pattern:a,template:o,demo:i,patternsUsed:m.flatMap(d=>d.type==="pattern-template"?[{patternId:d.patternId,templateId:d.templateId}]:d.type==="pattern-template-demo"?[{patternId:d.patternId,templateId:d.templateId,demoId:d.demoId}]:[])}},f=`
79
+ `;
80
+ }
81
+ __name(renderDemoAppTemplate, "renderDemoAppTemplate");
82
+ async function getUsage(data) {
83
+ const props = Object.keys(data.props || {}).map((key) => {
84
+ const value = data.props[key];
85
+ return {
86
+ key,
87
+ value
88
+ };
89
+ });
90
+ const { templateName, children, extraProps = [] } = data;
91
+ if (!templateName) {
92
+ throw new Error(
93
+ `Cannot getUsage of a React Component when no "templateName" is provided.`
94
+ );
95
+ }
96
+ const attributes = props.map(({ key, value }) => {
97
+ switch (typeof value) {
98
+ case "string":
99
+ if (value.startsWith("(") && value.includes("=>")) {
100
+ return `${key}={${value}}`;
101
+ }
102
+ return `${key}="${value}"`;
103
+ case "boolean":
104
+ return value ? `${key}` : `${key}={${value}}`;
105
+ default:
106
+ return `${key}={${JSON.stringify(value)}}`;
107
+ }
108
+ });
109
+ const extraAttributes = [];
110
+ const slotProps = {};
111
+ extraProps.forEach(({ key, value }) => {
112
+ slotProps[key] = slotProps[key] ?? [];
113
+ slotProps[key].push(value);
114
+ });
115
+ Object.entries(slotProps).forEach(([key, values]) => {
116
+ const value = values.length === 1 ? values[0] : `<>${values.join("\n")}</>`;
117
+ extraAttributes.push(`${key}={${value}}`);
118
+ });
119
+ const result = renderUsageTemplate({
120
+ templateName,
121
+ attributes: [...attributes, ...extraAttributes].join(" "),
122
+ children
123
+ });
124
+ return data.format ? (0, import_file_utils.formatCode)({
125
+ contents: result,
126
+ path: "x.tsx"
127
+ // doing this to set format language
128
+ }).then((code) => code.trim()).catch(() => result.trim()) : result.trim();
129
+ }
130
+ __name(getUsage, "getUsage");
131
+ async function getDemoAppUsage({
132
+ children,
133
+ imports,
134
+ format
135
+ }) {
136
+ const code = renderDemoAppTemplate({
137
+ children,
138
+ imports
139
+ });
140
+ if (!format) return code;
141
+ return (0, import_file_utils.formatCode)({
142
+ contents: code,
143
+ path: "x.tsx"
144
+ // doing this to set format language
145
+ });
146
+ }
147
+ __name(getDemoAppUsage, "getDemoAppUsage");
148
+ async function getTypeScriptInfoFromFile({ src }) {
149
+ const tsConfigPath = await (0, import_file_utils.findUp)("tsconfig.json", {
150
+ cwd: import_path.default.dirname(src)
151
+ });
152
+ const rdTs = await import("react-docgen-typescript");
153
+ const config = {
154
+ shouldExtractLiteralValuesFromEnum: true,
155
+ savePropValueAsString: true,
156
+ skipChildrenPropWithoutDoc: false,
157
+ // In addition to the ones listed here, which had not strangely included these below ~ https://github.com/styleguidist/react-docgen-typescript/blob/287e7012843cb26fed8f4bd8ee24e462c25a1414/src/parser.ts#L308
158
+ customComponentTypes: ["VoidFunctionComponent", "VFC"]
159
+ };
160
+ const parse2 = tsConfigPath ? rdTs.withCustomConfig(tsConfigPath, config).parse : rdTs.withDefaultConfig(config).parse;
161
+ return {
162
+ info: parse2(src)
163
+ };
164
+ }
165
+ __name(getTypeScriptInfoFromFile, "getTypeScriptInfoFromFile");
166
+ function extractSpecFromTypeScriptInfo({
167
+ info: results,
168
+ exportName
169
+ }) {
170
+ try {
171
+ if (!results) return false;
172
+ const spec = {
173
+ props: {
174
+ $schema: "http://json-schema.org/draft-07/schema",
175
+ type: "object",
176
+ required: [],
177
+ properties: {}
178
+ },
179
+ slots: {
180
+ // children: {
181
+ // title: 'children',
182
+ // },
183
+ }
184
+ };
185
+ const isDefaultExport = !exportName || exportName === "default";
186
+ const result = isDefaultExport ? results.pop() : results.find((r) => r.displayName === exportName);
187
+ if (!result) return false;
188
+ const { displayName } = result;
189
+ Object.entries(result?.props || {}).forEach(([propName, propDef]) => {
190
+ const { name, description, defaultValue, required, type, parent } = propDef;
191
+ const propType = type?.name?.replace("| undefined", "").replace(/<.*/g, "").trim();
192
+ switch (propType) {
193
+ case "string":
194
+ spec.props.properties[propName] = {
195
+ type: "string"
196
+ };
197
+ break;
198
+ case "number":
199
+ spec.props.properties[propName] = {
200
+ type: "number"
201
+ };
202
+ break;
203
+ case "boolean":
204
+ case "bool":
205
+ if (defaultValue && "value" in defaultValue) {
206
+ defaultValue.value = defaultValue.value === "true";
207
+ }
208
+ spec.props.properties[propName] = {
209
+ type: "boolean"
210
+ };
211
+ break;
212
+ case "enum":
213
+ spec.props.properties[propName] = {
214
+ type: "string",
215
+ // yes there is a double "value" & yes it is confusing
216
+ enum: [
217
+ // ensure list is unique
218
+ ...new Set(
219
+ type.value.map(({ value }) => (0, import_utils.removeWrappingDoubleQuotes)(value?.trim())).filter(Boolean)
220
+ )
221
+ ]
222
+ };
223
+ break;
224
+ case "ReactNode":
225
+ case "React.ReactNode":
226
+ case "React.ReactElement":
227
+ case "ReactElement":
228
+ spec.slots[propName] = {
229
+ title: propName
230
+ };
231
+ if (description) {
232
+ spec.slots[propName] = {
233
+ ...spec.slots[propName],
234
+ description
235
+ };
236
+ }
237
+ break;
238
+ case "VFC":
239
+ case "FC":
240
+ spec.slots[propName] = {
241
+ title: propName,
242
+ description: description || "A reference to a component",
243
+ isTemplateReference: true,
244
+ allowOnlyOne: true,
245
+ disallowText: true
246
+ };
247
+ break;
248
+ default: {
249
+ if (type?.name?.startsWith("(")) {
250
+ spec.props.properties[propName] = {
251
+ // description: `\`${type.name}\` ${description}`,
252
+ typeof: "function",
253
+ tsType: propDef?.type?.name
254
+ };
255
+ } else if (type?.name?.includes("|")) {
256
+ const options = type.name.split("|").map((enumItem) => (0, import_utils.removeWrappingDoubleQuotes)(enumItem.trim())).filter(Boolean);
257
+ if (options?.length) {
258
+ spec.props.properties[propName] = {
259
+ type: "string",
260
+ // ensuring list is unique
261
+ enum: [...new Set(options)]
262
+ };
263
+ }
264
+ } else {
265
+ spec.props.properties[propName] = {
266
+ tsType: propDef?.type?.name
267
+ };
268
+ }
269
+ }
270
+ }
271
+ if (spec.props.properties[propName]) {
272
+ if (required) spec.props.required.push(propName);
273
+ if (description && !spec.props.properties[propName].description) {
274
+ spec.props.properties[propName].description = description;
275
+ }
276
+ if (defaultValue && "value" in defaultValue) {
277
+ if ((0, import_types.isNumberProp)(spec.props.properties[propName])) {
278
+ spec.props.properties[propName].default = parseFloat(
279
+ defaultValue.value
280
+ );
281
+ } else {
282
+ spec.props.properties[propName].default = (0, import_utils.removeWrappingDoubleQuotes)(defaultValue.value);
283
+ }
284
+ }
285
+ }
286
+ });
287
+ return spec;
288
+ } catch (error) {
289
+ import_app.log.verbose(
290
+ "Could not infer spec from React TypeScript file",
291
+ {
292
+ exportName,
293
+ error
294
+ },
295
+ "react renderer"
296
+ );
297
+ return false;
298
+ }
299
+ }
300
+ __name(extractSpecFromTypeScriptInfo, "extractSpecFromTypeScriptInfo");
301
+ async function getPropTypesInfoFromFile({ src }) {
302
+ const reactDocs = await import("react-docgen");
303
+ const { builtinResolvers } = reactDocs;
304
+ const fileSrc = await (0, import_file_utils.readFile)(src);
305
+ const { FindExportedDefinitionsResolver } = builtinResolvers;
306
+ const results = reactDocs.parse(fileSrc, {
307
+ resolver: new FindExportedDefinitionsResolver(),
308
+ handlers: null,
309
+ filename: src
310
+ // babelrc: false,
311
+ });
312
+ return {
313
+ info: results
314
+ };
315
+ }
316
+ __name(getPropTypesInfoFromFile, "getPropTypesInfoFromFile");
317
+ function extractSpecFromPropTypesInfo({
318
+ info: results,
319
+ exportName
320
+ }) {
321
+ try {
322
+ const isDefaultExport = !exportName || exportName === "default";
323
+ const result = isDefaultExport ? results.pop() : results.find((r) => r.displayName === exportName);
324
+ const spec = {
325
+ isInferred: true,
326
+ props: {
327
+ $schema: "http://json-schema.org/draft-07/schema",
328
+ type: "object",
329
+ required: [],
330
+ properties: {}
331
+ },
332
+ slots: {}
333
+ };
334
+ Object.entries(result?.props || {}).forEach(([propName, propDef]) => {
335
+ const { required, description, defaultValue } = propDef;
336
+ switch (propDef?.type?.name) {
337
+ case "string":
338
+ spec.props.properties[propName] = {
339
+ type: "string"
340
+ };
341
+ break;
342
+ case "func":
343
+ spec.props.properties[propName] = {
344
+ type: "string"
345
+ };
346
+ break;
347
+ case "bool":
348
+ spec.props.properties[propName] = {
349
+ type: "boolean"
350
+ };
351
+ break;
352
+ case "node":
353
+ spec.slots[propName] = {
354
+ title: propName,
355
+ description
356
+ };
357
+ }
358
+ if (spec.props.properties[propName]) {
359
+ if (required) spec.props.required.push(propName);
360
+ if (description && !spec.props.properties[propName].description) {
361
+ spec.props.properties[propName].description = description;
362
+ }
363
+ if (defaultValue && "value" in defaultValue) {
364
+ spec.props.properties[propName].default = typeof defaultValue.value === "string" ? (0, import_utils.removeWrappingDoubleQuotes)(defaultValue.value) : defaultValue.value;
365
+ }
366
+ }
367
+ });
368
+ return spec;
369
+ } catch (error) {
370
+ import_app.log.verbose(
371
+ "Could not infer spec from React PropTypes",
372
+ {
373
+ exportName,
374
+ error
375
+ },
376
+ "react renderer"
377
+ );
378
+ return false;
379
+ }
380
+ }
381
+ __name(extractSpecFromPropTypesInfo, "extractSpecFromPropTypesInfo");
382
+ function cleanUpSpec({
383
+ spec
384
+ }) {
385
+ if (spec === false) return spec;
386
+ Object.entries(spec?.props?.properties || {}).forEach(([propName, prop]) => {
387
+ if ((0, import_types.isOptionsProp)(prop)) {
388
+ if (!prop.enum.includes(prop.default)) {
389
+ prop.default = void 0;
390
+ }
391
+ }
392
+ });
393
+ return spec;
394
+ }
395
+ __name(cleanUpSpec, "cleanUpSpec");
396
+ async function getReactModuleInfoUncached({
397
+ src: unknownSrc,
398
+ resolveFromDir
399
+ }) {
400
+ const typesInfo = await (0, import_file_utils.resolvePath)({
401
+ path: unknownSrc,
402
+ resolveFromDir,
403
+ resolveType: "types"
404
+ });
405
+ if (typesInfo.exists) {
406
+ const typeScriptInfo = await getTypeScriptInfoFromFile({
407
+ src: typesInfo.absolutePath
408
+ });
409
+ if (typeScriptInfo) {
410
+ return {
411
+ type: "typescript",
412
+ info: typeScriptInfo.info
413
+ };
414
+ }
415
+ }
416
+ const jsInfo = await (0, import_file_utils.resolvePath)({
417
+ path: unknownSrc,
418
+ resolveFromDir
419
+ });
420
+ if (!jsInfo.exists) return { type: "unknown" };
421
+ const { ext } = import_path.default.parse(jsInfo.absolutePath);
422
+ switch (ext) {
423
+ case ".jsx": {
424
+ const propTypesInfo = await getPropTypesInfoFromFile({
425
+ src: jsInfo.absolutePath
426
+ });
427
+ return {
428
+ type: "propTypes",
429
+ info: propTypesInfo.info
430
+ };
431
+ }
432
+ case ".ts":
433
+ case ".tsx": {
434
+ const typeScriptInfo = await getTypeScriptInfoFromFile({
435
+ src: jsInfo.absolutePath
436
+ });
437
+ return {
438
+ type: "typescript",
439
+ info: typeScriptInfo.info
440
+ };
441
+ }
442
+ default:
443
+ return {
444
+ type: "unknown"
445
+ };
446
+ }
447
+ }
448
+ __name(getReactModuleInfoUncached, "getReactModuleInfoUncached");
449
+ var getReactModuleInfoCache = /* @__PURE__ */ new Map();
450
+ var clearInferSpecCache = /* @__PURE__ */ __name(() => {
451
+ import_app.log.info(`Clearing React TypeScript inferSpec cache...`);
452
+ getReactModuleInfoCache.clear();
453
+ }, "clearInferSpecCache");
454
+ async function getReactModuleInfo(args) {
455
+ const cacheKey = JSON.stringify(args);
456
+ if (!getReactModuleInfoCache.has(cacheKey)) {
457
+ getReactModuleInfoCache.set(cacheKey, getReactModuleInfoUncached(args));
458
+ }
459
+ return getReactModuleInfoCache.get(cacheKey);
460
+ }
461
+ __name(getReactModuleInfo, "getReactModuleInfo");
462
+ async function getReactSpec({
463
+ src,
464
+ exportName,
465
+ resolveFromDir
466
+ }) {
467
+ const reactModuleInfo = await getReactModuleInfo({
468
+ src,
469
+ resolveFromDir
470
+ });
471
+ switch (reactModuleInfo.type) {
472
+ case "typescript":
473
+ return extractSpecFromTypeScriptInfo({
474
+ info: reactModuleInfo.info,
475
+ exportName
476
+ });
477
+ case "propTypes":
478
+ return extractSpecFromPropTypesInfo({
479
+ info: reactModuleInfo.info,
480
+ exportName
481
+ });
482
+ case "unknown":
483
+ default:
484
+ return false;
485
+ }
486
+ }
487
+ __name(getReactSpec, "getReactSpec");
488
+ async function getReactDocs(opt) {
489
+ return cleanUpSpec({
490
+ spec: await getReactSpec(opt)
491
+ });
492
+ }
493
+ __name(getReactDocs, "getReactDocs");
494
+ async function copyReactAssets(distDirAbsolute, publicPath) {
495
+ try {
496
+ const { version: reactVersion } = (0, import_file_utils.getModulePkgJson)("react");
497
+ const { version: reactDomVersion } = (0, import_file_utils.getModulePkgJson)("react-dom");
498
+ const reactRoot = import_path.default.dirname(
499
+ require.resolve("react", {
500
+ paths: [process.cwd()]
501
+ })
502
+ );
503
+ const reactDomRoot = import_path.default.dirname(
504
+ require.resolve("react-dom", {
505
+ paths: [process.cwd()]
506
+ })
507
+ );
508
+ await Promise.all([
509
+ (0, import_file_utils.copy)(
510
+ import_path.default.join(reactRoot, "umd/react.development.js"),
511
+ import_path.default.join(distDirAbsolute, `react.development.${reactVersion}.js`)
512
+ ),
513
+ (0, import_file_utils.copy)(
514
+ import_path.default.join(reactRoot, "umd/react.production.min.js"),
515
+ import_path.default.join(distDirAbsolute, `react.production.min.${reactVersion}.js`)
516
+ ),
517
+ (0, import_file_utils.copy)(
518
+ import_path.default.join(reactDomRoot, "umd/react-dom.production.min.js"),
519
+ import_path.default.join(
520
+ distDirAbsolute,
521
+ `react-dom.production.min.${reactDomVersion}.js`
522
+ )
523
+ ),
524
+ (0, import_file_utils.copy)(
525
+ import_path.default.join(reactDomRoot, "umd/react-dom.development.js"),
526
+ import_path.default.join(
527
+ distDirAbsolute,
528
+ `react-dom.development.${reactDomVersion}.js`
529
+ )
530
+ )
531
+ ]);
532
+ const reactFileSuffix = process.env.NODE_ENV === "production" ? "production.min" : "development";
533
+ return [
534
+ import_path.default.join(publicPath, `react.${reactFileSuffix}.${reactVersion}.js`),
535
+ import_path.default.join(
536
+ publicPath,
537
+ `react-dom.${reactFileSuffix}.${reactDomVersion}.js`
538
+ )
539
+ ];
540
+ } catch (error) {
541
+ import_app.log.warn(
542
+ 'Error trying to copy "react" and "react-dom" JS files, are they installed? We want to use your exact versions.',
543
+ error,
544
+ "templateRenderer:react"
545
+ );
546
+ process.exit(1);
547
+ }
548
+ }
549
+ __name(copyReactAssets, "copyReactAssets");
550
+
551
+ // src/react-creators.ts
552
+ var import_file_utils2 = require("@knapsack/file-utils");
553
+ var import_creator_utils = require("@knapsack/creator-utils");
554
+ var import_ks_file_utils = require("@knapsack/ks-file-utils");
555
+ var import_utils2 = require("@knapsack/utils");
556
+ function isCapitalLetter(char) {
557
+ return char.toUpperCase() === char;
558
+ }
559
+ __name(isCapitalLetter, "isCapitalLetter");
560
+ function startsWithCapitalLetter(str) {
561
+ return isCapitalLetter(str[0]);
562
+ }
563
+ __name(startsWithCapitalLetter, "startsWithCapitalLetter");
564
+ function createPatternData({
565
+ importName,
566
+ id,
567
+ title = importName,
568
+ pkgPath,
569
+ initialDemoId
570
+ }) {
571
+ return {
572
+ id,
573
+ title,
574
+ description: "",
575
+ statuses: {
576
+ main: "ready"
577
+ },
578
+ templates: [
579
+ {
580
+ id: "react",
581
+ title: "react",
582
+ path: pkgPath,
583
+ alias: importName,
584
+ templateLanguageId: "react",
585
+ spec: {
586
+ isInferred: true
587
+ },
588
+ demoIds: [initialDemoId],
589
+ blockIds: []
590
+ }
591
+ ],
592
+ tabs: [
593
+ {
594
+ type: "template",
595
+ id: "react"
596
+ }
597
+ ],
598
+ subPages: []
599
+ };
600
+ }
601
+ __name(createPatternData, "createPatternData");
602
+ var createReactPattern = (0, import_creator_utils.createCreator)({
603
+ id: "react-patterns",
604
+ title: "React Ks Patterns",
605
+ description: "Adds React templates as Knapsack Patterns",
606
+ getQuestions: /* @__PURE__ */ __name(async () => ({
607
+ pkgPath: {
608
+ type: "text",
609
+ title: "Package path"
610
+ },
611
+ importPrefix: {
612
+ type: "text",
613
+ title: "Import Prefix to Remove"
614
+ }
615
+ }), "getQuestions"),
616
+ getTasks: /* @__PURE__ */ __name(async ({ answers: { pkgPath, importPrefix = "" }, config }) => {
617
+ const dataDir = config.dest;
618
+ const currentPatterns = await (0, import_ks_file_utils.readKsPatternConfigs)({
619
+ dataDir
620
+ });
621
+ const currentReactPatternsImportNames = currentPatterns.reduce(
622
+ (cur, pattern) => {
623
+ const reactTemplates = pattern.templates?.filter((t) => t.templateLanguageId === "react") ?? [];
624
+ cur.push(...reactTemplates.map((t) => t.alias));
625
+ return cur;
626
+ },
627
+ []
628
+ );
629
+ const { exports: allImports } = await (0, import_file_utils2.getJsExportNames)({
630
+ path: pkgPath
631
+ });
632
+ return [
633
+ {
634
+ title: "Pick Imports to add",
635
+ task: /* @__PURE__ */ __name((_, task) => import_creator_utils.tasks.runSubCreator({
636
+ task,
637
+ config,
638
+ creator: (0, import_creator_utils.createCreator)({
639
+ id: "react-pattern-import-names",
640
+ getQuestions: /* @__PURE__ */ __name(async () => ({
641
+ importNames: {
642
+ type: "choices",
643
+ choices: allImports.filter(
644
+ (importName) => startsWithCapitalLetter(importName) && !currentReactPatternsImportNames.includes(importName)
645
+ ).map((importName) => ({
646
+ value: importName
647
+ }))
648
+ }
649
+ }), "getQuestions"),
650
+ getTasks: /* @__PURE__ */ __name(async ({ answers: { importNames } }) => {
651
+ const patterns = importNames.map((importName) => ({
652
+ importName,
653
+ patternId: importName.startsWith(importPrefix) ? importName.slice(importPrefix.length).toLowerCase() : importName.toLowerCase()
654
+ }));
655
+ return [
656
+ ...patterns.map(
657
+ ({ importName, patternId }) => ({
658
+ title: `Add ${importName} React Template`,
659
+ task: /* @__PURE__ */ __name(async (__, subTask) => {
660
+ const initialDemo = {
661
+ type: "data",
662
+ id: (0, import_utils2.makeShortId)(),
663
+ title: "Main",
664
+ patternId,
665
+ templateId: "react",
666
+ data: {
667
+ props: {},
668
+ slots: {}
669
+ }
670
+ };
671
+ const pattern = createPatternData({
672
+ id: patternId,
673
+ importName,
674
+ pkgPath,
675
+ initialDemoId: initialDemo.id
676
+ });
677
+ await Promise.all([
678
+ (0, import_ks_file_utils.writeDemo)({
679
+ dataDir,
680
+ demo: initialDemo
681
+ }),
682
+ (0, import_ks_file_utils.writeKsPatternConfig)({
683
+ dataDir,
684
+ patternId,
685
+ data: pattern
686
+ })
687
+ ]);
688
+ }, "task")
689
+ })
690
+ ),
691
+ {
692
+ title: `Updating Nav`,
693
+ task: /* @__PURE__ */ __name(async (__, subTask) => {
694
+ const { byId } = await (0, import_ks_file_utils.readKsNavConfig)({
695
+ dataDir
696
+ });
697
+ const componentsGroup = Object.values(byId).find(
698
+ ({ path: path2, name, id }) => {
699
+ if (path2) return false;
700
+ if (name.toLowerCase() === "patterns") return true;
701
+ if (name.toLowerCase() === "components") return true;
702
+ return false;
703
+ }
704
+ );
705
+ await (0, import_ks_file_utils.addKsNavItems)({
706
+ dataDir,
707
+ navItems: patterns.map(({ patternId }) => ({
708
+ navId: patternId,
709
+ navPath: `/pattern/${patternId}`,
710
+ navParent: componentsGroup?.id || "root"
711
+ }))
712
+ });
713
+ }, "task")
714
+ }
715
+ ];
716
+ }, "getTasks")
717
+ })
718
+ }), "task")
719
+ }
720
+ ];
721
+ }, "getTasks")
722
+ });
723
+
724
+ // src/types.ts
725
+ var rendererMetaScriptTagId = "ks-react-meta";
726
+
727
+ // src/renderer-react.ts
728
+ var { pkg } = (0, import_file_utils3.findUpPkgJson)(__dirname);
729
+ import_app2.log.setupUpdateNotifier({ ...pkg, name: pkg.name, version: pkg.version });
730
+ var errorCatcherPath = (0, import_path2.join)(__dirname, "./error-catcher.mjs");
731
+ var KnapsackReactRenderer = class _KnapsackReactRenderer extends import_renderer_webpack_base.RendererWebpackBase {
732
+ static {
733
+ __name(this, "KnapsackReactRenderer");
734
+ }
735
+ /**
736
+ * `react.js` & `react-dom.js` root relative paths
737
+ */
738
+ assets;
739
+ babelConfig;
740
+ demoWrapperPath;
741
+ disableReactStrictMode;
742
+ constructor({
743
+ webpackConfig,
744
+ demoWrapperPath = (0, import_path2.join)(__dirname, "./demo-wrapper.mjs"),
745
+ id = import_types2.rendererIds.react,
746
+ disableReactStrictMode
747
+ } = {}) {
748
+ super({
749
+ id,
750
+ language: "jsx",
751
+ webpackConfig,
752
+ extraScripts: [
753
+ // this is the code in `./client/init.mts`
754
+ "@knapsack/renderer-react/client"
755
+ ],
756
+ codeSrcs: [demoWrapperPath, errorCatcherPath]
757
+ });
758
+ this.language = "jsx";
759
+ this.assets = [];
760
+ this.demoWrapperPath = (0, import_path2.isAbsolute)(demoWrapperPath) ? demoWrapperPath : this.resolvePathSync({
761
+ path: demoWrapperPath,
762
+ resolveFromDir: this.userConfigDir
763
+ }).absolutePath;
764
+ (0, import_file_utils3.assertFileExists)(
765
+ this.demoWrapperPath,
766
+ `Could not find demo wrapper at: "${this.demoWrapperPath}"
767
+ Please adjust setting in "knapsack.config.js" or pass a different path when creating the React Renderer.`
768
+ );
769
+ this.disableReactStrictMode = disableReactStrictMode;
770
+ this.creators = [createReactPattern];
771
+ }
772
+ init = /* @__PURE__ */ __name(async () => {
773
+ this.assets = await copyReactAssets(this.outputDir, this.publicPath);
774
+ if (!await (0, import_file_utils3.exists)(this.demoWrapperPath)) {
775
+ throw new Error(
776
+ `Could not find demo wrapper at: "${this.demoWrapperPath}"`
777
+ );
778
+ }
779
+ }, "init");
780
+ getMeta = /* @__PURE__ */ __name(() => ({
781
+ id: this.id,
782
+ title: "React",
783
+ aliasUse: "optional",
784
+ aliasTitle: "Named Export",
785
+ aliasIsJsNamedExport: true,
786
+ aliasDescription: "If `export X` was used instead of `export default`, then provide X.",
787
+ enableDataDemos: true,
788
+ enableTemplateDemos: true,
789
+ hasSlotsSupport: true,
790
+ hasSlotOptionsSupport: true,
791
+ version: pkg.version,
792
+ hasInferSpecSupport: true,
793
+ syntaxHighlightingLanguage: "jsx",
794
+ hasTemplateSuggestionsSupport: true,
795
+ prototypingTemplate: {
796
+ path: "@knapsack/renderer-react/prototype-template",
797
+ spec: {
798
+ isInferred: false,
799
+ props: {
800
+ type: "object",
801
+ properties: {}
802
+ },
803
+ slots: {
804
+ children: { title: "Children" }
805
+ }
806
+ }
807
+ }
808
+ }), "getMeta");
809
+ changeCase = /* @__PURE__ */ __name((str) => (0, import_utils3.pascalCase)(str), "changeCase");
810
+ createWebpackConfig = /* @__PURE__ */ __name(() => {
811
+ const config = super.createWebpackConfig();
812
+ config.externals = {
813
+ react: "React",
814
+ "react-dom": "ReactDOM"
815
+ };
816
+ return config;
817
+ }, "createWebpackConfig");
818
+ async prepClientRenderResults({
819
+ usage,
820
+ demoApp,
821
+ importMap,
822
+ renderOptions: { demo, state, patternId, templateId }
823
+ }) {
824
+ const meta = {
825
+ demo,
826
+ disableReactStrictMode: this.disableReactStrictMode,
827
+ neededImportsByPath: (0, import_renderer_webpack_base.convertImportMapToNeededImportsByPath)(importMap),
828
+ extraImports: {
829
+ DemoWrapper: {
830
+ type: "default",
831
+ path: this.demoWrapperPath,
832
+ name: "DemoWrapper"
833
+ },
834
+ ErrorCatcher: {
835
+ type: "default",
836
+ path: errorCatcherPath,
837
+ name: "ErrorCatcher"
838
+ }
839
+ },
840
+ demoWrapperProps: {
841
+ patternId,
842
+ templateId,
843
+ demo
844
+ }
845
+ };
846
+ let code = `
34
847
  window.knapsack = window.knapsack || {};
35
- window.knapsack.getDemoApp = ({ ${m.map(d=>d.importInfo.name).join(", ")} }) => {
36
- ${t}
37
- return ${O}
848
+ window.knapsack.getDemoApp = ({ ${[...importMap.keys()].join(", ")} }) => {
849
+ ${demoApp}
850
+ return ${demoAppName}
851
+ }
852
+ `;
853
+ let errorHtmlMsg = "";
854
+ try {
855
+ code = await (0, import_renderers.babelCodeForBrowser)({ code });
856
+ } catch (e) {
857
+ console.log(code);
858
+ console.log("---original code before babel error ^---");
859
+ console.trace(e.message);
860
+ code = `console.error(${JSON.stringify(e.message)});`;
861
+ errorHtmlMsg = `<pre><code>${e.message}</code></pre>`;
38
862
  }
39
- `,y="";try{f=await renderers.babelCodeForBrowser({code:f});}catch(d){console.log(f),console.log("---original code before babel error ^---"),console.trace(d.message),f=`console.error(${JSON.stringify(d.message)});`,y=`<pre><code>${d.message}</code></pre>`;}let R=`
40
- <script type="application/json" id="${H}">${JSON.stringify(u)}</script>
41
- <script type="application/javascript">${f}</script>
863
+ const html = `
864
+ <script type="application/json" id="${rendererMetaScriptTagId}">${JSON.stringify(
865
+ meta
866
+ )}</script>
867
+ <script type="application/javascript">${code}</script>
42
868
  <div id="render-root" class="knapsack-pattern-direct-parent" data-dev-note="Knapsack React Template Wrapper"></div>
43
- ${this.assets.map(d=>`<script src="${d}"></script>`).join(`
44
- `)}
45
- ${this.createHtmlTagsForAssetPaths({assets:this.getWebpackAssetPaths(),scriptTagsAreAsync:!1})}
46
- ${y}
47
- `;return {ok:!y,html:await fileUtils.formatCode({contents:R,path:"x.html"}),usage:e,templateLanguage:this.language}}render=c(async e=>{if(e.demo?.type==="template"){let t=[5,10,20,50,100,1e3,1e3],s,a=0;for(;;)try{let{absolutePath:p,exists:u}=await this.resolvePath(e.demo.templateInfo.path);if(!u)throw new Error(`Template demo file does not exist: ${p}`);s=p;break}catch(p){let u=t[a];if(!u)throw new Error(p);a+=1,await Ie__default.default(u);}let[o,{usage:i,imports:l}]=await Promise.all([fileUtils.readFile(s),this.getUsageAndImports(e)]),m=await v({children:i});return await this.prepClientRenderResults({usage:o,demoApp:m,imports:l,renderOptions:e})}if(e.demo?.type==="data"){let{usage:t,imports:s}=await this.getUsageAndImports(e),{code:a}=this.createJsImportCodeBlock({imports:s}),[o,i]=await Promise.all([v({children:t,imports:a,format:!0}),v({children:t})]);return this.prepClientRenderResults({demoApp:i,usage:o,imports:s,renderOptions:e})}},"render");getUsageAndImports=c(async({pattern:e,template:t,patternManifest:s,demo:a})=>{if(a?.type&&a.type==="data"){let{data:{props:o,slots:i,slotsOptionsComputed:l}}=a,m=this.getJsImport({patternId:e.id,templateId:t.id});if(!m)throw new Error(`Could not find import for pattern-template: ${e.id}-${t.id}`);let{type:n,name:p}=m.importInfo,u=[m],f=[],y=[];if(i){let d=Object.keys(i);(await Promise.all(d.map(async w=>{let T=i[w],D=await Promise.all(T.filter(g=>!(g.type!=="text"&&(!g.patternId||!g.templateId||g.type==="template-demo"&&!g.demoId))).map(async g=>{if(g.type==="text")return T.length===1&&w!=="children"?`\`${g.text}\``:g.text;let I=s.getPattern(g.patternId),b=I.templates.find(k=>k.id===g.templateId);if(g.type==="template-reference"){let{usage:k,imports:E}=await this.getUsageAndImports({pattern:I,template:b,patternManifest:s});return u.push(...E),k}if(g.type==="template-demo"){let{usage:k,imports:E}=await this.getUsageAndImports({pattern:I,template:b,demo:g.demo||this.patterns.demosById[g.demoId],patternManifest:s});return u.push(...E),k}throw new Error(`Unknown slot item: ${JSON.stringify(g)}`)}));return {slotName:w,slotItemsUsages:D}}))).forEach(({slotName:w,slotItemsUsages:T})=>{let D=l?.[w],{openTag:g,closeTag:I}=renderers.createSlotOptionsHtmlTags({slotOptionsComputed:D,classAttributeName:"className",stylesValueType:"object"});g&&(w==="children"?f.push(g):y.push({key:w,value:g})),T.forEach(b=>{w==="children"?f.push(b):y.push({key:w,value:b});}),I&&(w==="children"?f.push(I):y.push({key:w,value:I}));});}return {usage:await M({templateName:p,props:o,children:f.join(`
48
- `),extraProps:y}),imports:u}}if(a?.type&&a.type==="template"){let o=this.getJsImport({patternId:e.id,templateId:t.id,demoId:a.id});if(!o)throw new Error(`Could not find import for pattern-template-demo: ${e.id}-${t.id}-${a.id}`);let{type:i,name:l}=o.importInfo;return {usage:await M({templateName:l}),imports:[o]}}if(!a){let o=this.getJsImport({patternId:e.id,templateId:t.id});if(!o)throw new Error(`Could not find import for pattern-template: ${e.id}-${t.id}`);let{type:i,name:l}=o.importInfo;return {usage:l,imports:[o]}}throw new Error(`Unhandled demo type for ${e.id}-${t.id}: ${JSON.stringify(a)}`)},"getUsageAndImports");inferSpec=c(async({template:e,templatePath:t})=>{let s=await B({src:e.path,exportName:e.alias||"default",resolveFromDir:this.config.data});if(s!==!1){let a=Object.keys(s?.props?.properties||{}).length,o=Object.keys(s?.slots||{}).length;if(a===0&&o===0)return !1}return s},"inferSpec");watch=c(async e=>{super.watch(e),app.knapsackEvents.onPatternTemplateChanged(()=>{V();});},"watch");getTemplateMeta=c(async({pattern:e,template:t})=>{let s=[];if(t?.spec?.props){let a=JSON.parse(JSON.stringify(t.spec.props));t?.spec?.slots&&Object.entries(t.spec.slots).forEach(([i,l])=>{a.properties[i]={typeof:"function",tsType:"React.ReactNode",description:l.allowedPatternIds?`${l.description}. Only use: ${l.allowedPatternIds.join(", ")}`:l.description},a.required=a.required??[],l.isRequired&&a.required.push(i);});let o=await r.convertSchemaToTypeScriptDefs({schema:a,title:`${this.changeCase(e.id)}Props`,description:`[Knapsack Docs](http://localhost:3999/pattern/${e.id}/${t.id})`,patternId:e.id,templateId:t.id,postBanner:"import * as React from 'react';"});s.push({contents:o,encoding:"utf8",path:`${e.id}.${t.id}.spec.d.ts`}),s.push({contents:JSON.stringify(a,null," "),encoding:"utf8",path:`${e.id}.${t.id}.spec.json`});}return s},"getTemplateMeta");alterTemplateMetaFiles=c(async({files:e,metaDir:t})=>{let s=[],a=".spec.d.ts";return e.forEach(o=>{if(o.path.endsWith(a)){let{base:i}=h.parse(o.path),[l,m]=i.split("."),n=m===this.id,p=this.changeCase(`${l}Props`),u=this.changeCase(`${l}-${m}Props`);s.push(`export { ${n?p:`${p} as ${u}`} } from './${h.relative(t,o.path).replace(".d.ts","")}';`);}}),s.push(""),[...e,{contents:s.join(`
49
- `),encoding:"utf8",path:h.join(t,"react.d.ts")}]},"alterTemplateMetaFiles");getTemplateSuggestions=c(async({newPath:e})=>{let{data:t}=this.patterns.userConfig,{allTemplateDemos:s,allTemplates:a}=this.getMyTemplates(),o=[...s,...a].map(({path:n,alias:p})=>({path:n,alias:p||"default"})),i=[...new Set([e,...o.map(({path:n})=>n)])];return {suggestions:(await Promise.all(i.map(async n=>{if(!n)return [];try{let{exports:p,errorMsg:u}=await fileUtils.getJsExportNames({path:n,resolveFromDir:t,pkgPathAliases:this.pkgPathAliases});if(u)throw new Error(u);return p.filter(f=>f==="default"||utils.isFirstLetterCapital(f)).map(f=>({alias:f,path:n}))}catch(p){return app.log.verbose(`Error getting import names for ${n}: ${p.message}`,null,this.logPrefix),[]}})).then(n=>n.flat())).filter(n=>!o.find(p=>p.alias===n.alias&&p.path===n.path))}},"getTemplateSuggestions")};
50
-
51
- exports.KnapsackReactRenderer = Q;
52
- //# sourceMappingURL=index.js.map
869
+ ${this.assets.map((asset) => `<script src="${asset}"></script>`).join("\n")}
870
+ ${import_renderer_webpack_base.RendererWebpackBase.createHtmlTagsForAssetPaths({
871
+ assets: this.getWebpackAssetPaths(),
872
+ // we need the scripts to finish adding methods to the global knapsack object synchronously before the client-side code runs that is in the <script> tag below
873
+ scriptTagsAreAsync: false
874
+ })}
875
+ ${errorHtmlMsg}
876
+ `;
877
+ return {
878
+ ok: !errorHtmlMsg,
879
+ html: await (0, import_file_utils3.formatCode)({
880
+ contents: html,
881
+ path: "x.html"
882
+ // doing this to set format language
883
+ }),
884
+ usage,
885
+ templateLanguage: this.language
886
+ };
887
+ }
888
+ render = /* @__PURE__ */ __name(async (opt) => {
889
+ if (opt.demo?.type === "template") {
890
+ const waits = [5, 10, 20, 50, 100, 1e3, 1e3];
891
+ let templateDemoPath;
892
+ let attempt = 0;
893
+ while (true) {
894
+ try {
895
+ const { absolutePath, exists } = await this.resolvePath(
896
+ opt.demo.templateInfo.path
897
+ );
898
+ if (!exists) {
899
+ throw new Error(
900
+ `Template demo file does not exist: ${absolutePath}`
901
+ );
902
+ }
903
+ templateDemoPath = absolutePath;
904
+ break;
905
+ } catch (e) {
906
+ const waitTime = waits[attempt];
907
+ if (!waitTime) {
908
+ throw new Error(e);
909
+ }
910
+ attempt += 1;
911
+ await (0, import_sleep_promise.default)(waitTime);
912
+ }
913
+ }
914
+ const [templateFileContents, { usage, importMap }] = await Promise.all([
915
+ (0, import_file_utils3.readFile)(templateDemoPath),
916
+ this.getUsageAndImports({
917
+ ...opt,
918
+ importMap: /* @__PURE__ */ new Map()
919
+ })
920
+ ]);
921
+ const demoApp = await getDemoAppUsage({
922
+ children: usage
923
+ });
924
+ const results = await this.prepClientRenderResults({
925
+ usage: templateFileContents,
926
+ demoApp,
927
+ renderOptions: opt,
928
+ importMap
929
+ });
930
+ return results;
931
+ }
932
+ if (opt.demo?.type === "data") {
933
+ const { usage, importMap } = await this.getUsageAndImports({
934
+ ...opt,
935
+ importMap: /* @__PURE__ */ new Map()
936
+ });
937
+ const importCode = import_renderer_webpack_base.RendererWebpackBase.createJsImportCodeBlock({
938
+ importMap
939
+ });
940
+ const [demoAppUsage, demoApp] = await Promise.all([
941
+ getDemoAppUsage({
942
+ children: usage,
943
+ imports: importCode,
944
+ format: true
945
+ }),
946
+ getDemoAppUsage({
947
+ children: usage
948
+ })
949
+ ]);
950
+ return this.prepClientRenderResults({
951
+ demoApp,
952
+ usage: demoAppUsage,
953
+ renderOptions: opt,
954
+ importMap
955
+ });
956
+ }
957
+ }, "render");
958
+ getUsageAndImports = /* @__PURE__ */ __name(async ({
959
+ patternId,
960
+ templateId,
961
+ demo,
962
+ state,
963
+ importMap
964
+ }) => {
965
+ if (!demo) {
966
+ throw new Error(
967
+ `No demo provided while rendering ${patternId} ${templateId}`
968
+ );
969
+ }
970
+ const pattern = state.patterns[patternId];
971
+ if (!pattern) {
972
+ throw new Error(`Could not find pattern: ${patternId}`);
973
+ }
974
+ if (demo.type === "data") {
975
+ const template = pattern.templates.find((t) => t.id === templateId);
976
+ if (!template) {
977
+ throw new Error(`Could not find template: ${templateId}`);
978
+ }
979
+ const {
980
+ data: { props, slots, slotsOptionsComputed }
981
+ } = demo;
982
+ const { name: templateName } = await this.addUniqueValueToImportMap({
983
+ importMap,
984
+ path: template.path,
985
+ alias: template.alias || "default"
986
+ });
987
+ const children = [];
988
+ const extraProps = [];
989
+ if (slots) {
990
+ const slotNames = Object.keys(slots);
991
+ const slotUsages = await Promise.all(
992
+ slotNames.map(async (slotName) => {
993
+ const slotItems = slots[slotName];
994
+ const slotItemsUsages = await Promise.all(
995
+ slotItems.filter((slotItem) => {
996
+ if (!slotItem) return false;
997
+ if (slotItem.type !== "text") {
998
+ if (!slotItem.patternId) return false;
999
+ if (!slotItem.templateId) return false;
1000
+ if (slotItem.type === "template-demo" && !slotItem.demoId) {
1001
+ return false;
1002
+ }
1003
+ }
1004
+ return true;
1005
+ }).map(async (slotItem) => {
1006
+ if (slotItem.type === "text") {
1007
+ if (slotItems.length === 1 && slotName !== "children") {
1008
+ return `\`${slotItem.text}\``;
1009
+ }
1010
+ return slotItem.text;
1011
+ }
1012
+ if (slotItem.type === "template-reference") {
1013
+ const slottedTemplate = state.patterns[slotItem.patternId]?.templates.find((t) => t.id === slotItem.templateId);
1014
+ if (!slottedTemplate) {
1015
+ throw new Error(
1016
+ `Could not find slotted template: ${slotItem.patternId} ${slotItem.templateId}`
1017
+ );
1018
+ }
1019
+ const templateRefImport = await this.addUniqueValueToImportMap({
1020
+ importMap,
1021
+ path: slottedTemplate.path,
1022
+ alias: slottedTemplate.alias || "default"
1023
+ });
1024
+ return templateRefImport.name;
1025
+ }
1026
+ if (slotItem.type === "template-demo") {
1027
+ const thisDemo = slotItem.demo;
1028
+ if (!thisDemo) {
1029
+ throw new Error(
1030
+ `Could not find slotted template demo ${JSON.stringify(
1031
+ slotItem
1032
+ )}`
1033
+ );
1034
+ }
1035
+ const { usage: usage2 } = await this.getUsageAndImports({
1036
+ patternId: thisDemo.patternId,
1037
+ templateId: thisDemo.templateId,
1038
+ demo: thisDemo,
1039
+ state,
1040
+ importMap
1041
+ });
1042
+ return usage2;
1043
+ }
1044
+ const _exhaustiveCheck2 = slotItem;
1045
+ throw new Error(
1046
+ `Unknown slot item: ${JSON.stringify(slotItem)}`
1047
+ );
1048
+ })
1049
+ );
1050
+ return {
1051
+ slotName,
1052
+ slotItemsUsages
1053
+ };
1054
+ })
1055
+ );
1056
+ slotUsages.forEach(({ slotName, slotItemsUsages }) => {
1057
+ const slotOptionsComputed = slotsOptionsComputed?.[slotName];
1058
+ const { openTag, closeTag } = (0, import_renderers.createSlotOptionsHtmlTags)({
1059
+ slotOptionsComputed,
1060
+ classAttributeName: "className",
1061
+ stylesValueType: "object"
1062
+ });
1063
+ if (openTag) {
1064
+ if (slotName === "children") {
1065
+ children.push(openTag);
1066
+ } else {
1067
+ extraProps.push({
1068
+ key: slotName,
1069
+ value: openTag
1070
+ });
1071
+ }
1072
+ }
1073
+ slotItemsUsages.forEach((usage2) => {
1074
+ if (slotName === "children") {
1075
+ children.push(usage2);
1076
+ } else {
1077
+ extraProps.push({
1078
+ key: slotName,
1079
+ value: usage2
1080
+ });
1081
+ }
1082
+ });
1083
+ if (closeTag) {
1084
+ if (slotName === "children") {
1085
+ children.push(closeTag);
1086
+ } else {
1087
+ extraProps.push({
1088
+ key: slotName,
1089
+ value: closeTag
1090
+ });
1091
+ }
1092
+ }
1093
+ });
1094
+ }
1095
+ const usage = await getUsage({
1096
+ templateName,
1097
+ props,
1098
+ children: children.join("\n"),
1099
+ extraProps
1100
+ });
1101
+ return {
1102
+ usage,
1103
+ importMap
1104
+ };
1105
+ }
1106
+ if (demo.type === "template") {
1107
+ const { templateInfo } = demo;
1108
+ const { name: templateName } = await this.addUniqueValueToImportMap({
1109
+ importMap,
1110
+ path: templateInfo.path,
1111
+ alias: templateInfo.alias || "default"
1112
+ });
1113
+ const usage = await getUsage({ templateName });
1114
+ return {
1115
+ usage,
1116
+ importMap
1117
+ };
1118
+ }
1119
+ const _exhaustiveCheck = demo;
1120
+ throw new Error(
1121
+ `Unhandled demo type for ${patternId}-${templateId}: ${JSON.stringify(
1122
+ demo
1123
+ )}`
1124
+ );
1125
+ }, "getUsageAndImports");
1126
+ inferSpec = /* @__PURE__ */ __name(async ({
1127
+ template,
1128
+ templatePath
1129
+ }) => {
1130
+ const spec = await getReactDocs({
1131
+ src: template.path,
1132
+ exportName: template.alias || "default",
1133
+ resolveFromDir: this.config.data
1134
+ });
1135
+ if (spec !== false) {
1136
+ const totalProps = Object.keys(spec?.props?.properties || {}).length;
1137
+ const totalSlots = Object.keys(spec?.slots || {}).length;
1138
+ if (totalProps === 0 && totalSlots === 0) {
1139
+ return false;
1140
+ }
1141
+ }
1142
+ return spec;
1143
+ }, "inferSpec");
1144
+ watch = /* @__PURE__ */ __name(async () => {
1145
+ super.watch();
1146
+ import_app2.knapsackEvents.onPatternTemplateChanged(() => {
1147
+ clearInferSpecCache();
1148
+ });
1149
+ }, "watch");
1150
+ getTemplateMeta = /* @__PURE__ */ __name(async ({
1151
+ pattern,
1152
+ template
1153
+ }) => {
1154
+ const files = [];
1155
+ if (template?.spec?.props) {
1156
+ const schema = JSON.parse(JSON.stringify(template.spec.props));
1157
+ if (template?.spec?.slots) {
1158
+ Object.entries(template.spec.slots).forEach(([id, info]) => {
1159
+ schema.properties[id] = {
1160
+ typeof: "function",
1161
+ tsType: "React.ReactNode",
1162
+ description: info.allowedPatternIds ? `${info.description}. Only use: ${info.allowedPatternIds.join(
1163
+ ", "
1164
+ )}` : info.description
1165
+ };
1166
+ schema.required = schema.required ?? [];
1167
+ if (info.isRequired) schema.required.push(id);
1168
+ });
1169
+ }
1170
+ const typeDefs = await _KnapsackReactRenderer.convertSchemaToTypeScriptDefs({
1171
+ schema,
1172
+ title: `${this.changeCase(pattern.id)}Props`,
1173
+ // @todo pull in base url
1174
+ description: `[Knapsack Docs](http://localhost:3999/pattern/${pattern.id}/${template.id})`,
1175
+ patternId: pattern.id,
1176
+ templateId: template.id,
1177
+ postBanner: `import * as React from 'react';`
1178
+ });
1179
+ files.push({
1180
+ contents: typeDefs,
1181
+ encoding: "utf8",
1182
+ path: `${pattern.id}.${template.id}.spec.d.ts`
1183
+ });
1184
+ files.push({
1185
+ contents: JSON.stringify(schema, null, " "),
1186
+ encoding: "utf8",
1187
+ path: `${pattern.id}.${template.id}.spec.json`
1188
+ });
1189
+ }
1190
+ return files;
1191
+ }, "getTemplateMeta");
1192
+ alterTemplateMetaFiles = /* @__PURE__ */ __name(async ({
1193
+ files,
1194
+ metaDir
1195
+ }) => {
1196
+ const imports = [];
1197
+ const ext = ".spec.d.ts";
1198
+ files.forEach((file) => {
1199
+ if (file.path.endsWith(ext)) {
1200
+ const { base } = (0, import_path2.parse)(file.path);
1201
+ const [patternId, templateId] = base.split(".");
1202
+ const isFirst = templateId === this.id;
1203
+ const exportName = this.changeCase(`${patternId}Props`);
1204
+ const exportNameWithTemplateId = this.changeCase(
1205
+ `${patternId}-${templateId}Props`
1206
+ );
1207
+ imports.push(
1208
+ `export { ${isFirst ? exportName : `${exportName} as ${exportNameWithTemplateId}`} } from './${(0, import_path2.relative)(metaDir, file.path).replace(".d.ts", "")}';`
1209
+ );
1210
+ }
1211
+ });
1212
+ imports.push("");
1213
+ return [
1214
+ ...files,
1215
+ {
1216
+ contents: imports.join("\n"),
1217
+ encoding: "utf8",
1218
+ path: (0, import_path2.join)(metaDir, "react.d.ts")
1219
+ }
1220
+ ];
1221
+ }, "alterTemplateMetaFiles");
1222
+ getTemplateSuggestions = /* @__PURE__ */ __name(async ({
1223
+ newPath,
1224
+ state
1225
+ }) => {
1226
+ const usedSuggestions = Object.values(state.patterns).reduce(
1227
+ (acc, { templateDemos, templates }) => {
1228
+ templates.forEach(({ path: path2, alias, templateLanguageId }) => {
1229
+ if (templateLanguageId !== this.id) return;
1230
+ acc.push({ path: path2, alias });
1231
+ });
1232
+ templateDemos.forEach(
1233
+ ({ templateInfo: { path: path2, alias }, templateLanguageId }) => {
1234
+ if (templateLanguageId !== this.id) return;
1235
+ acc.push({ path: path2, alias });
1236
+ }
1237
+ );
1238
+ return acc;
1239
+ },
1240
+ []
1241
+ );
1242
+ const codeSrcs = new Set(this.getCodeSrcs());
1243
+ codeSrcs.delete(this.demoWrapperPath);
1244
+ codeSrcs.delete(errorCatcherPath);
1245
+ const allPaths = [
1246
+ .../* @__PURE__ */ new Set([
1247
+ newPath,
1248
+ ...Object.keys(this.pkgPathAliases || {}),
1249
+ ...codeSrcs
1250
+ ])
1251
+ ];
1252
+ const allSuggestions = await Promise.all(
1253
+ allPaths.map(async (path2) => {
1254
+ if (!path2) return [];
1255
+ try {
1256
+ const { exports: exports2, errorMsg } = await (0, import_file_utils3.getJsExportNames)({
1257
+ path: path2,
1258
+ resolveFromDir: this.dataDir,
1259
+ pkgPathAliases: this.pkgPathAliases
1260
+ });
1261
+ if (errorMsg) {
1262
+ throw new Error(errorMsg);
1263
+ }
1264
+ return exports2.filter((e) => e === "default" || (0, import_utils3.isFirstLetterCapital)(e)).map((name) => ({
1265
+ alias: name,
1266
+ path: path2
1267
+ }));
1268
+ } catch (e) {
1269
+ import_app2.log.verbose(
1270
+ `Error getting import names for ${path2}: ${e.message}`,
1271
+ null,
1272
+ this.logPrefix
1273
+ );
1274
+ return [];
1275
+ }
1276
+ })
1277
+ ).then((results) => {
1278
+ return results.flat();
1279
+ });
1280
+ const suggestions = allSuggestions.filter((s) => {
1281
+ return !usedSuggestions.find(
1282
+ (us) => us.alias === s.alias && us.path === s.path
1283
+ );
1284
+ });
1285
+ return {
1286
+ suggestions
1287
+ };
1288
+ }, "getTemplateSuggestions");
1289
+ };
1290
+ // Annotate the CommonJS export names for ESM import in node:
1291
+ 0 && (module.exports = {
1292
+ KnapsackReactRenderer
1293
+ });
53
1294
  //# sourceMappingURL=index.js.map