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

Sign up to get free protection for your applications and to get access to all the features.
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