@knapsack/renderer-react 4.70.0--canary.4513.12c8d13.0 → 4.70.0--canary.3797.b249674.0

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