@knapsack/renderer-react 4.70.0--canary.4821.e250df4.0 → 4.70.0--canary.4821.82d27e9.0

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