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