@haxtheweb/create 10.0.5 → 10.0.7

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/README.md CHANGED
@@ -184,7 +184,6 @@ rollup.config.js
184
184
 
185
185
  # File extension
186
186
  # (Must start with *, as seen below)
187
- *.html
188
187
  *.md
189
188
  *.yml
190
189
  *.json
package/dist/create.js CHANGED
@@ -29,14 +29,23 @@ exec('git --version', error => {
29
29
  }
30
30
  });
31
31
  async function main() {
32
+ let wcReg = {};
33
+ let regPath = path.join(__dirname, './lib/wc-registry.json');
34
+ if (fs.existsSync(regPath)) {
35
+ try {
36
+ wcReg = JSON.parse(fs.readFileSync(regPath));
37
+ } catch (e) {
38
+ // no registry for testing, probably busted package
39
+ }
40
+ }
32
41
  var commandRun = {};
33
- _commander.program.option('--').option('--v', 'Verbose output').option('--debug', 'Output for developers').option('--format <char>', 'Output format; json (default), yaml').option('--path <char>', 'where to perform operation').option('--npm-client <char>', 'npm client to use (must be installed) npm, yarn, pnpm', 'npm').option('--y', 'yes to all questions').option('--skip', 'skip frills like animations').option('--quiet', 'remove console logging').option('--auto', 'yes to all questions, alias of y').option('--no-i', 'prevent interactions / sub-process, good for scripting').option('--to-file <char>', 'redirect command output to a file').option('--no-extras', 'skip all extra / automatic command processing').option('--root <char>', 'root location to execute the command from')
42
+ _commander.program.option('--').option('--v', 'Verbose output').option('--debug', 'Output for developers').option('--format <char>', 'Output format; json (default), yaml').option('--path <char>', 'where to perform operation').option('--name <char>', 'name of the project/web component').option('--npm-client <char>', 'npm client to use (must be installed) npm, yarn, pnpm', 'npm').option('--y', 'yes to all questions').option('--skip', 'skip frills like animations').option('--quiet', 'remove console logging').option('--auto', 'yes to all questions, alias of y').option('--no-i', 'prevent interactions / sub-process, good for scripting').option('--to-file <char>', 'redirect command output to a file').option('--no-extras', 'skip all extra / automatic command processing').option('--root <char>', 'root location to execute the command from')
34
43
 
35
44
  // options for webcomponent
36
45
  .option('--org <char>', 'organization for package.json').option('--author <char>', 'author for site / package.json').option('--writeHaxProperties', 'Write haxProperties for the element')
37
46
 
38
47
  // options for site
39
- .option('--import-site <char>', 'URL of site to import').option('--import-structure <char>', `import method to use:\n\rpressbooksToSite\n\relmslnToSite\n\rhaxcmsToSite\n\rnotionToSite\n\rgitbookToSite\n\revolutionToSite\n\rhtmlToSite\n\rdocxToSite`).option('--node-op <char>', 'node operation to perform').option('--item-id <char>', 'node ID to operate on').option('--name <char>', 'name of the project').option('--domain <char>', 'published domain name').option('--title-scrape <char>', 'CSS Selector for `title` in resource').option('--content-scrape <char>', 'CSS Selector for `body` in resource').option('--items-import <char>', 'import items from a file / site').option('--recipe <char>', 'path to recipe file').option('--custom-theme-name <char>', 'custom theme name').option('--custom-theme-template <char>', 'custom theme template; (options: base, polaris-flex, polaris-sidebar)').version(await HAXCMS.getHAXCMSVersion()).helpCommand(true);
48
+ .option('--import-site <char>', 'URL of site to import').option('--import-structure <char>', `import method to use:\n\rpressbooksToSite\n\relmslnToSite\n\rhaxcmsToSite\n\rnotionToSite\n\rgitbookToSite\n\revolutionToSite\n\rhtmlToSite\n\rdocxToSite`).option('--node-op <char>', 'node operation to perform').option('--item-id <char>', 'node ID to operate on').option('--domain <char>', 'published domain name').option('--title-scrape <char>', 'CSS Selector for `title` in resource').option('--content-scrape <char>', 'CSS Selector for `body` in resource').option('--items-import <char>', 'import items from a file / site').option('--recipe <char>', 'path to recipe file').option('--custom-theme-name <char>', 'custom theme name').option('--custom-theme-template <char>', 'custom theme template; (options: base, polaris-flex, polaris-sidebar)').version(await HAXCMS.getHAXCMSVersion()).helpCommand(true);
40
49
 
41
50
  // default command which runs interactively
42
51
  _commander.program.command('start').description('Select which hax sub-program to run').action(() => {
@@ -68,19 +77,24 @@ async function main() {
68
77
  _commander.program.option(`--${(0, _utils.camelToDash)(siteNodeOps[i].value)} <char>`, `${siteNodeOps[i].label}`);
69
78
  siteProg.option(`--${(0, _utils.camelToDash)(siteNodeOps[i].value)} <char>`, `${siteNodeOps[i].label}`);
70
79
  }
80
+
71
81
  // webcomponent program
72
- _commander.program.command('webcomponent').description('Create Lit based web components, with HAX recommendations').argument('[name]', 'name of the project').action(name => {
82
+ let strWebcomponentActions = '';
83
+ (0, _webcomponent.webcomponentActions)().forEach(action => {
84
+ strWebcomponentActions += `${action.value} - ${action.label}` + "\n\r";
85
+ });
86
+ _commander.program.command('wc').alias('webcomponent').description('Create Lit based web components, with HAX recommendations').argument('[action]', 'Actions to perform on web component include:' + "\n\r" + strWebcomponentActions).action(action => {
73
87
  commandRun = {
74
88
  command: 'webcomponent',
75
89
  arguments: {},
76
90
  options: {}
77
91
  };
78
92
  // if name set, populate
79
- if (name) {
80
- commandRun.arguments.name = name;
93
+ if (action) {
94
+ commandRun.arguments.action = action;
81
95
  commandRun.options.skip = true;
82
96
  }
83
- }).option('--path <char>', 'path the project should be created in').option('--org <char>', 'organization for package.json').option('--author <char>', 'author for site / package.json').option('--writeHaxProperties', 'Write haxProperties for the element').option('--to-file <char>', 'redirect command output to a file').option('--no-extras', 'skip all extra / automatic command processing').option('--no-i', 'prevent interactions / sub-process, good for scripting').option('--root <char>', 'root location to execute the command from').version(await HAXCMS.getHAXCMSVersion());
97
+ }).option('--path <char>', 'path the project should be created in').option('--org <char>', 'organization for package.json').option('--author <char>', 'author for site / package.json').option('--name <char>', 'name of the web component').option('--writeHaxProperties', 'Write haxProperties for the element').option('--to-file <char>', 'redirect command output to a file').option('--no-extras', 'skip all extra / automatic command processing').option('--no-i', 'prevent interactions / sub-process, good for scripting').option('--root <char>', 'root location to execute the command from').version(await HAXCMS.getHAXCMSVersion());
84
98
 
85
99
  // audit program
86
100
  _commander.program.command('audit').description('Audits web components for compliance with DDD (HAX design system)').action(() => {
@@ -283,14 +297,8 @@ async function main() {
283
297
  activeProject = project.type;
284
298
  // silly but this way we don't have to take options for quitting
285
299
  if (project.type !== 'quit') {
286
- // also silly temp spot
287
- let themes = await (0, _site.siteThemeList)();
288
- const custom = {
289
- value: 'custom-theme',
290
- label: 'Create Custom Theme'
291
- };
292
- // Append custom option to list of core themes
293
- themes.push(custom);
300
+ // global spot for core themes list
301
+ let coreThemes = await (0, _site.siteThemeList)(true);
294
302
  project = await p.group({
295
303
  type: ({
296
304
  results
@@ -322,7 +330,7 @@ async function main() {
322
330
  name: ({
323
331
  results
324
332
  }) => {
325
- if (!commandRun.arguments.action && !commandRun.arguments.name) {
333
+ if (!commandRun.arguments.action) {
326
334
  let placeholder = "mysite";
327
335
  let message = "Site name:";
328
336
  if (commandRun.command === "webcomponent" || results.type === "webcomponent") {
@@ -337,15 +345,22 @@ async function main() {
337
345
  if (!value) {
338
346
  return "Name is required (tab writes default)";
339
347
  }
348
+ if (value.toLocaleLowerCase() !== value) {
349
+ return "Name must be lowercase";
350
+ }
340
351
  if (/^\d/.test(value)) {
341
352
  return "Name cannot start with a number";
342
353
  }
343
354
  if (value.indexOf(' ') !== -1) {
344
- return "No spaces allowed in project name";
355
+ return "No spaces allowed in name";
345
356
  }
346
- if (results.type === "webcomponent" && value.indexOf('-') === -1 && value.indexOf('-') !== 0 && value.indexOf('-') !== value.length - 1) {
357
+ if (results.type === "webcomponent" && (value.indexOf('-') === -1 || value.replace('--', '') !== value || value[0] === '-' || value[value.length - 1] === '-')) {
347
358
  return "Name must include at least one `-` and must not start or end name.";
348
359
  }
360
+ // test that this is not an existing element we use in the registry
361
+ if (results.type === "webcomponent" && wcReg[value]) {
362
+ return "Name is already a web component in the wc-registry published for HAX.";
363
+ }
349
364
  // assumes auto was selected in CLI
350
365
  let joint = process.cwd();
351
366
  if (commandRun.options.path) {
@@ -359,6 +374,44 @@ async function main() {
359
374
  }
360
375
  });
361
376
  }
377
+ if (commandRun.arguments.action) {
378
+ let value = commandRun.arguments.action;
379
+ if (!value) {
380
+ _commander.program.error(_picocolors.default.red("Name is required (tab writes default)"));
381
+ process.exit(1);
382
+ }
383
+ if (value.toLocaleLowerCase() !== value) {
384
+ _commander.program.error(_picocolors.default.red("Name must be lowercase"));
385
+ process.exit(1);
386
+ }
387
+ if (/^\d/.test(value)) {
388
+ _commander.program.error(_picocolors.default.red("Name cannot start with a number"));
389
+ }
390
+ if (value.indexOf(' ') !== -1) {
391
+ _commander.program.error(_picocolors.default.red("No spaces allowed in name"));
392
+ process.exit(1);
393
+ }
394
+ if (results.type === "webcomponent" && (value.indexOf('-') === -1 || value.replace('--', '') !== value || value[0] === '-' || value[value.length - 1] === '-')) {
395
+ _commander.program.error(_picocolors.default.red("Name must include at least one `-` and must not start or end name."));
396
+ process.exit(1);
397
+ }
398
+ // test that this is not an existing element we use in the registry
399
+ if (results.type === "webcomponent" && wcReg[value]) {
400
+ _commander.program.error(_picocolors.default.red("Name is already a web component in the wc-registry published for HAX."));
401
+ process.exit(1);
402
+ }
403
+ // assumes auto was selected in CLI
404
+ let joint = process.cwd();
405
+ if (commandRun.options.path) {
406
+ joint = commandRun.options.path;
407
+ } else if (results.path) {
408
+ joint = results.path;
409
+ }
410
+ if (fs.existsSync(path.join(joint, value))) {
411
+ _commander.program.error(_picocolors.default.red(`${path.join(joint, value)} exists, rename this project`));
412
+ process.exit(1);
413
+ }
414
+ }
362
415
  },
363
416
  org: ({
364
417
  results
@@ -394,15 +447,20 @@ async function main() {
394
447
  if (results.type === "site" && !commandRun.options.theme) {
395
448
  // support having no theme but autoselecting
396
449
  if (commandRun.options.auto && commandRun.options.skip) {
397
- commandRun.options.theme = themes[0].value;
450
+ commandRun.options.theme = coreThemes[0].value;
398
451
  } else {
399
452
  return p.select({
400
453
  message: "Theme:",
401
454
  required: false,
402
- options: themes,
403
- initialValue: themes[0]
455
+ options: coreThemes,
456
+ initialValue: coreThemes[0]
404
457
  });
405
458
  }
459
+ } else if (results.type === "site" && commandRun.options.theme) {
460
+ if (coreThemes.filter(item => item.value === commandRun.options.theme).length === 0) {
461
+ _commander.program.error(_picocolors.default.red('Theme is not in the list of valid themes'));
462
+ process.exit(1);
463
+ }
406
464
  }
407
465
  },
408
466
  customThemeName: async ({
@@ -411,13 +469,13 @@ async function main() {
411
469
  if (results.theme === "custom-theme") {
412
470
  let tmpCustomName = await p.text({
413
471
  message: 'Theme Name:',
414
- placeholder: `${results.name}`,
472
+ placeholder: `custom-${commandRun.arguments.action ? commandRun.arguments.action : results.name}-theme`,
415
473
  required: false,
416
474
  validate: value => {
417
475
  if (!value) {
418
476
  return "Theme name is required (tab writes default)";
419
477
  }
420
- if (themes.some(theme => theme.value === value)) {
478
+ if (coreThemes.some(theme => theme.value === value)) {
421
479
  return "Theme name is already in use";
422
480
  }
423
481
  if (/^\d/.test(value)) {
@@ -432,6 +490,24 @@ async function main() {
432
490
  }
433
491
  });
434
492
  return tmpCustomName;
493
+ } else if (results.type === "site") {
494
+ // need to validate theme from CLI arguments
495
+ let value = `${commandRun.options.customThemeName ? commandRun.options.customThemeName : results.name ? results.name : commandRun.arguments.action}`;
496
+ if (!value) {
497
+ _commander.program.error(_picocolors.default.red("Theme name is required (tab writes default)"));
498
+ }
499
+ if (coreThemes.some(theme => theme.value === value)) {
500
+ _commander.program.error(_picocolors.default.red("Theme name is already in use"));
501
+ }
502
+ if (/^\d/.test(value)) {
503
+ _commander.program.error(_picocolors.default.red("Theme name cannot start with a number"));
504
+ }
505
+ if (/[A-Z]/.test(value)) {
506
+ _commander.program.error(_picocolors.default.red("No uppercase letters allowed in theme name"));
507
+ }
508
+ if (value.indexOf(' ') !== -1) {
509
+ _commander.program.error(_picocolors.default.red("No spaces allowed in theme name"));
510
+ }
435
511
  }
436
512
  },
437
513
  customThemeTemplate: ({
@@ -508,7 +584,7 @@ async function main() {
508
584
  });
509
585
  // merge cli options with project options assume this is NOT a monorepo
510
586
  // but spread will overwrite if needed
511
- if (commandRun.command === 'webcomponent' && !commandRun.arguments.name) {
587
+ if (commandRun.command === 'webcomponent' && !commandRun.arguments.action) {
512
588
  project = {
513
589
  isMonorepo: false,
514
590
  ...project,
@@ -524,16 +600,22 @@ async function main() {
524
600
  }
525
601
  project.year = new Date().getFullYear();
526
602
  project.version = await HAXCMS.getHAXCMSVersion();
603
+ if (!project.name && commandRun.arguments.action) {
604
+ project.name = commandRun.arguments.action;
605
+ }
606
+
527
607
  // resolve site vs multi-site
528
608
  switch (project.type) {
529
609
  case 'site':
530
- if (!project.name && commandRun.arguments.action) {
531
- project.name = commandRun.arguments.action;
610
+ // only set path if not already set, normalize across clack and commander
611
+ if (commandRun.options.path && !project.path) {
612
+ project.path = commandRun.options.path;
613
+ }
614
+ if (!project.path) {
615
+ project.path = process.cwd();
532
616
  }
533
- // only set path if not already set
534
617
  if (!commandRun.options.path) {
535
- commandRun.options.path = process.cwd();
536
- project.path = commandRun.options.path;
618
+ commandRun.options.path = project.path;
537
619
  }
538
620
  await (0, _site.siteProcess)(commandRun, project);
539
621
  break;
@@ -8,9 +8,12 @@ var _nodeFs = require("node:fs");
8
8
  var _nodePath = _interopRequireDefault(require("node:path"));
9
9
  var _picocolors = _interopRequireDefault(require("picocolors"));
10
10
  var p = _interopRequireWildcard(require("@clack/prompts"));
11
+ var _commander = require("commander");
11
12
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
12
13
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ let checksPassed = true;
16
+
14
17
  /**
15
18
  * @description Runs the audit command, to be called when `hax audit` command is run
16
19
  */
@@ -28,6 +31,7 @@ function auditCommandDetected(commandRun) {
28
31
 
29
32
  📘 For more information about DDD variables and capabilities: ${_picocolors.default.underline(_picocolors.default.cyan(`https://haxtheweb.org/documentation/ddd`))}
30
33
  `);
34
+ returnCode();
31
35
  }
32
36
 
33
37
  /**
@@ -258,11 +262,24 @@ function auditFile(fileLocation, fileName) {
258
262
  });
259
263
  if (data.length !== 0) {
260
264
  console.table(data);
265
+ checksPassed = false;
261
266
  } else {
262
267
  p.note("No changes needed!");
263
268
  }
264
269
  }
265
270
 
271
+ /**
272
+ * @description returns code for automation purposes. 0 = compliant, 1 = not compliant
273
+ */
274
+ function returnCode() {
275
+ if (!checksPassed) {
276
+ // Not-compliant
277
+ _commander.program.error(_picocolors.default.red("Component not compliant with DDD"));
278
+ process.exit(1);
279
+ }
280
+ process.exit(0); // Compliant
281
+ }
282
+
266
283
  // ! Audit Helpers
267
284
 
268
285
  /**
@@ -588,7 +588,7 @@ async function siteCommandDetected(commandRun) {
588
588
  // these have fixed possible values
589
589
  else if (['parent', 'theme'].includes(nodeProp)) {
590
590
  let l = nodeProp === 'parent' ? "-- no parent --" : "-- no theme --";
591
- let list = nodeProp === 'parent' ? await siteItemsOptionsList(activeHaxsite, page.id) : await siteThemeList();
591
+ let list = nodeProp === 'parent' ? await siteItemsOptionsList(activeHaxsite, page.id) : await siteThemeList(true);
592
592
  propValue = await p.select({
593
593
  message: `${nodeProp}:`,
594
594
  defaultValue: val,
@@ -744,8 +744,8 @@ async function siteCommandDetected(commandRun) {
744
744
  case "site:theme":
745
745
  try {
746
746
  //theme
747
- let list = await siteThemeList();
748
747
  activeHaxsite = await hax.systemStructureContext();
748
+ let list = await siteThemeList(true, activeHaxsite.directory);
749
749
  let val = activeHaxsite.manifest.metadata.theme.element;
750
750
  if (!commandRun.options.theme) {
751
751
  commandRun.options.theme = await p.select({
@@ -755,11 +755,71 @@ async function siteCommandDetected(commandRun) {
755
755
  options: list
756
756
  });
757
757
  }
758
+ if (commandRun.options.theme === "custom-theme") {
759
+ if (!commandRun.options.customThemeName) {
760
+ commandRun.options.customThemeName = await p.text({
761
+ message: 'Theme Name:',
762
+ placeholder: `custom-${activeHaxsite.name}-theme`,
763
+ required: false,
764
+ validate: value => {
765
+ if (!value) {
766
+ return "Theme name is required (tab writes default)";
767
+ }
768
+ if (list.some(theme => theme.value === value)) {
769
+ return "Theme name is already in use";
770
+ }
771
+ if (/^\d/.test(value)) {
772
+ return "Theme name cannot start with a number";
773
+ }
774
+ if (/[A-Z]/.test(value)) {
775
+ return "No uppercase letters allowed in theme name";
776
+ }
777
+ if (value.indexOf(' ') !== -1) {
778
+ return "No spaces allowed in theme name";
779
+ }
780
+ }
781
+ });
782
+ }
783
+ if (!commandRun.options.customThemeTemplate) {
784
+ const options = [{
785
+ value: 'base',
786
+ label: 'Vanilla Theme with Hearty Documentation'
787
+ }, {
788
+ value: 'polaris-flex',
789
+ label: 'Minimalist Theme with Horizontal Nav'
790
+ }, {
791
+ value: 'polaris-sidebar',
792
+ label: 'Content-Focused Theme with Flexible Sidebar'
793
+ }];
794
+ commandRun.options.customThemeTemplate = await p.select({
795
+ message: 'Template:',
796
+ required: false,
797
+ options: options,
798
+ initialValue: options[0]
799
+ });
800
+ }
801
+ }
758
802
  let themes = await HAXCMS.getThemes();
759
- if (themes && commandRun.options.theme && themes[commandRun.options.theme]) {
760
- activeHaxsite.manifest.metadata.theme = themes[commandRun.options.theme];
761
- activeHaxsite.manifest.save(false);
762
- recipe.log(siteLoggingName, (0, _logging.commandString)(commandRun));
803
+ if (themes && commandRun.options.theme) {
804
+ if (themes[commandRun.options.theme]) {
805
+ activeHaxsite.manifest.metadata.theme = themes[commandRun.options.theme];
806
+ activeHaxsite.manifest.save(false);
807
+ recipe.log(siteLoggingName, (0, _logging.commandString)(commandRun));
808
+ } else if (commandRun.options.theme === "custom-theme") {
809
+ commandRun.options.name = activeHaxsite.name;
810
+ commandRun.options.directory = activeHaxsite.directory;
811
+ // temporary for proof of concept
812
+ commandRun.options.npmClient = 'npm';
813
+ await customSiteTheme(commandRun, {});
814
+ } else if (!themes[commandRun.options.theme]) {
815
+ let themeObj = {
816
+ element: commandRun.options.theme,
817
+ path: "./custom/build/custom.es6.js",
818
+ name: (0, _utils.dashToCamel)(commandRun.options.theme)
819
+ };
820
+ activeHaxsite.manifest.metadata.theme = themeObj;
821
+ activeHaxsite.manifest.save(false);
822
+ }
763
823
  }
764
824
  } catch (e) {
765
825
  (0, _logging.log)(e.stderr);
@@ -1197,6 +1257,9 @@ async function siteProcess(commandRun, project, port = '3000') {
1197
1257
  });
1198
1258
  // matching the common object elsewhere tho different reference in this command since it creates from nothing
1199
1259
  // capture this if use input on the fly
1260
+ if (!commandRun.arguments.action) {
1261
+ commandRun.arguments.action = project.name;
1262
+ }
1200
1263
  commandRun.options.theme = project.theme;
1201
1264
  recipe.log(siteLoggingName, (0, _logging.commandString)(commandRun));
1202
1265
  if (commandRun.options.v) {
@@ -1222,6 +1285,16 @@ async function siteProcess(commandRun, project, port = '3000') {
1222
1285
  await exec(`cd ${project.path}/${project.name} && git init && git add -A && git commit -m "first commit" && git branch -M main${project.gitRepo ? ` && git remote add origin ${project.gitRepo}` : ''}`);
1223
1286
  } catch (e) {}
1224
1287
  }
1288
+ // ensure dot files is there because it doesn't copy for some reason for sites :\
1289
+ if (!fs.existsSync(`${project.path}/${project.name}/.gitignore`)) {
1290
+ await fs.copyFileSync(`${process.mainModule.path}/templates/sitedotfiles/_gitignore`, `${project.path}/${project.name}/.gitignore`);
1291
+ }
1292
+ if (!fs.existsSync(`${project.path}/${project.name}/._npmignore`)) {
1293
+ await fs.copyFileSync(`${process.mainModule.path}/templates/sitedotfiles/_npmignore`, `${project.path}/${project.name}/.npmignore`);
1294
+ }
1295
+ if (!fs.existsSync(`${project.path}/${project.name}/._surgeignore`)) {
1296
+ await fs.copyFileSync(`${process.mainModule.path}/templates/sitedotfiles/_surgeignore`, `${project.path}/${project.name}/.surgeignore`);
1297
+ }
1225
1298
  // options for install, git and other extras
1226
1299
  // can't launch if we didn't install first so launch implies installation
1227
1300
  if (project.extras && project.extras.includes && project.extras.includes('launch')) {
@@ -1269,14 +1342,53 @@ async function siteItemsOptionsList(activeHaxsite, skipId = null) {
1269
1342
  }
1270
1343
  return optionItems;
1271
1344
  }
1272
- async function siteThemeList() {
1273
- let themes = await HAXCMS.getThemes();
1345
+ async function siteThemeList(coreOnly = true, directory = null) {
1274
1346
  let items = [];
1275
- for (var i in themes) {
1276
- items.push({
1277
- value: i,
1278
- label: themes[i].name
1279
- });
1347
+ if (coreOnly) {
1348
+ items = [{
1349
+ value: 'clean-one',
1350
+ label: 'Clean One'
1351
+ }, {
1352
+ value: 'clean-two',
1353
+ label: 'Clean Two'
1354
+ }, {
1355
+ value: 'clean-portfolio-theme',
1356
+ label: 'Clean Portfolio'
1357
+ }, {
1358
+ value: 'haxor-slevin',
1359
+ label: 'Haxor Blog'
1360
+ }, {
1361
+ value: 'polaris-flex-theme',
1362
+ label: 'Polaris - Flex'
1363
+ }, {
1364
+ value: 'polaris-flex-sidebar',
1365
+ label: 'Polaris - Flex Sidebar'
1366
+ }, {
1367
+ value: 'polaris-invent-theme',
1368
+ label: 'Polaris - Invent'
1369
+ }, {
1370
+ value: 'custom-theme',
1371
+ label: 'Create Custom Theme'
1372
+ }];
1373
+ if (fs.existsSync(`${directory}/custom/custom-elements.json`)) {
1374
+ let customThemeArray = JSON.parse(fs.readFileSync(`${directory}/custom/custom-elements.json`, 'utf8')).modules;
1375
+ for (var i in customThemeArray) {
1376
+ if (customThemeArray[i].declarations[0].superclass.name === "PolarisFlexTheme" || customThemeArray[i].declarations[0].superclass.name === "HAXCMSLitElementTheme") {
1377
+ items.push({
1378
+ value: customThemeArray[i].declarations[0].tagName,
1379
+ label: customThemeArray[i].declarations[0].name
1380
+ });
1381
+ }
1382
+ }
1383
+ }
1384
+ } else {
1385
+ let themes = await HAXCMS.getThemes();
1386
+ for (var i in themes) {
1387
+ items.push({
1388
+ value: i,
1389
+ label: themes[i].name
1390
+ });
1391
+ }
1280
1392
  }
1281
1393
  return items;
1282
1394
  }
@@ -1287,7 +1399,7 @@ async function customSiteTheme(commandRun, project) {
1287
1399
  // validate start and end tags for theme name
1288
1400
  if (/^custom/.test(project.customThemeName) && !/^custom-/.test(project.customThemeName)) {
1289
1401
  project.customThemeName = project.customThemeName.replace(/^custom/, "custom-");
1290
- } else if (!/^custom-/.test(project.className)) {
1402
+ } else if (!/^custom-/.test(project.customThemeName)) {
1291
1403
  project.customThemeName = `custom-${project.customThemeName}`;
1292
1404
  }
1293
1405
  if (/theme$/.test(project.customThemeName) && !/-theme$/.test(project.customThemeName)) {
@@ -1300,10 +1412,30 @@ async function customSiteTheme(commandRun, project) {
1300
1412
  project.className = (0, _utils.dashToCamel)(project.customThemeName);
1301
1413
 
1302
1414
  // path to hax site
1303
- var sitePath = `${project.path}/${commandRun.options.name ? commandRun.options.name : project.name}`;
1415
+ var sitePath;
1416
+ if (!commandRun.options.directory) {
1417
+ sitePath = `${commandRun.options.path ? commandRun.options.path : project.path}/${commandRun.options.name ? commandRun.options.name : project.name}`;
1418
+ } else {
1419
+ // existing sites
1420
+ sitePath = commandRun.options.directory;
1421
+ }
1304
1422
 
1305
1423
  // path to new theme file
1306
1424
  const filePath = `${sitePath}/custom/src/${project.customThemeName}.js`;
1425
+ if (!project.year) {
1426
+ project.year = new Date().getFullYear();
1427
+ }
1428
+ if (!project.author) {
1429
+ try {
1430
+ let value = await exec(`git config user.name`);
1431
+ project.author = value.stdout.trim();
1432
+ } catch (e) {
1433
+ (0, _logging.log)(`
1434
+ git user name not configured. Run the following to do this:\n
1435
+ git config --global user.name "namehere"\n
1436
+ git config --global user.email "email@here`, 'debug');
1437
+ }
1438
+ }
1307
1439
 
1308
1440
  // theme template to use
1309
1441
  const themeTemplate = commandRun.options.customThemeTemplate ? commandRun.options.customThemeTemplate : project.customThemeTemplate;
@@ -1338,14 +1470,14 @@ async function customSiteTheme(commandRun, project) {
1338
1470
  // add theme to site.json
1339
1471
  let themeObj = {
1340
1472
  element: project.customThemeName,
1341
- path: filePath,
1473
+ path: "./custom/build/custom.es6.js",
1342
1474
  name: project.className
1343
1475
  };
1344
1476
  activeHaxsite.manifest.metadata.theme = themeObj;
1345
1477
  activeHaxsite.manifest.save(false);
1346
1478
 
1347
1479
  // install and build theme dependencies
1348
- await exec(`cd ${sitePath}/custom/ && ${commandRun.options.npmClient} install && ${commandRun.options.npmClient} run build && cd ${sitePath}`);
1480
+ await exec(`cd ${sitePath}/custom/ && ${commandRun.options.npmClient} install && ${commandRun.options.npmClient} run build && ${commandRun.options.npmClient} run analyze && cd ${sitePath}`);
1349
1481
  }
1350
1482
 
1351
1483
  // @fork of the hax core util for this so that we avoid api difference between real dom and parse nodejs dom