@haxtheweb/create 9.0.11 → 9.0.12

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
@@ -1,10 +1,17 @@
1
+ [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
2
+ [![Lit](https://img.shields.io/badge/-Lit-324fff?style=flat&logo=data:image/svg%2bxml;base64,PHN2ZyBmaWxsPSIjZmZmIiB2aWV3Qm94PSIwIDAgMTYwIDIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTYwIDgwdjgwbC00MC00MHptLTQwIDQwdjgwbDQwLTQwem0wLTgwdjgwbC00MC00MHptLTQwIDQwdjgwbDQwLTQwem0tNDAtNDB2ODBsNDAtNDB6bTQwLTQwdjgwbC00MC00MHptLTQwIDEyMHY4MGwtNDAtNDB6bS00MC00MHY4MGw0MC00MHoiLz48L3N2Zz4%3D)](https://lit.dev/)
3
+ [![#HAXTheWeb](https://img.shields.io/badge/-HAXTheWeb-999999FF?style=flat&logo=data:image/svg%2bxml;base64,PHN2ZyBpZD0iZmVhMTExZTAtMjEwZC00Y2QwLWJhMWQtZGZmOTQyODc0Njg1IiBkYXRhLW5hbWU9IkxheWVyIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDE4NC40IDEzNS45NyI+PGRlZnM+PHN0eWxlPi5lMWJjMjAyNS0xODAwLTRkYzItODc4NS1jNDZlZDEwM2Y0OTJ7ZmlsbDojMjMxZjIwO308L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iZTFiYzIwMjUtMTgwMC00ZGMyLTg3ODUtYzQ2ZWQxMDNmNDkyIiBkPSJNNzguMDcsODMuNDVWNTVIODYuMnY4LjEzaDE2LjI2djQuMDdoNC4wN1Y4My40NUg5OC40VjY3LjE5SDg2LjJWODMuNDVaIi8+PHBvbHlnb24gcG9pbnRzPSIxNTMuMTMgNjMuNyAxNTMuMTMgNTEuMzkgMTQwLjU0IDUxLjM5IDE0MC41NCAzOS4wOSAxMjcuOTUgMzkuMDkgMTI3Ljk1IDI2Ljc5IDEwMi43OCAyNi43OSAxMDIuNzggMzkuMDkgMTE1LjM2IDM5LjA5IDExNS4zNiA1MS4zOSAxMjcuOTUgNTEuMzkgMTI3Ljk1IDYzLjcgMTQwLjU0IDYzLjcgMTQwLjU0IDc2IDEyNy4zNiA3NiAxMjcuMzYgODguMyAxMTQuNzggODguMyAxMTQuNzggMTAwLjYxIDEwMi4xOSAxMDAuNjEgMTAyLjE5IDExMi45MSAxMjcuMzYgMTEyLjkxIDEyNy4zNiAxMDAuNjEgMTM5Ljk1IDEwMC42MSAxMzkuOTUgODguMyAxNTIuNTQgODguMyAxNTIuNTQgNzYgMTY1LjcyIDc2IDE2NS43MiA2My43IDE1My4xMyA2My43Ii8+PHBvbHlnb24gcG9pbnRzPSIzMy4xMyA2My43IDMzLjEzIDUxLjM5IDQ1LjcyIDUxLjM5IDQ1LjcyIDM5LjA5IDU4LjMxIDM5LjA5IDU4LjMxIDI2Ljc5IDgzLjQ4IDI2Ljc5IDgzLjQ4IDM5LjA5IDcwLjg5IDM5LjA5IDcwLjg5IDUxLjM5IDU4LjMxIDUxLjM5IDU4LjMxIDYzLjcgNDUuNzIgNjMuNyA0NS43MiA3NiA1OC44OSA3NiA1OC44OSA4OC4zIDcxLjQ4IDg4LjMgNzEuNDggMTAwLjYxIDg0LjA3IDEwMC42MSA4NC4wNyAxMTIuOTEgNTguODkgMTEyLjkxIDU4Ljg5IDEwMC42MSA0Ni4zMSAxMDAuNjEgNDYuMzEgODguMyAzMy43MiA4OC4zIDMzLjcyIDc2IDIwLjU0IDc2IDIwLjU0IDYzLjcgMzMuMTMgNjMuNyIvPjwvc3ZnPg==)](https://haxtheweb.org/)
4
+ [![Published on npm](https://img.shields.io/npm/v/@haxtheweb/create?style=flat)](https://www.npmjs.com/package/@haxtheweb/create)
5
+ [![build](https://github.com/haxtheweb/create/workflows/build/badge.svg)](https://github.com/haxtheweb/create/actions)
6
+ [![X](https://img.shields.io/twitter/follow/haxtheweb.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=haxtheweb)
7
+
1
8
  # HAX The CLI
2
9
  Rapidly build web components for the Web that work with HAX. HAX The Web's CLI tools empower you to rapidly..
3
10
 
4
11
  ```bash
5
12
  # this allows you to then use hax command
6
13
  npm install @haxtheweb/create --global
7
- # then run
14
+ # then run this for interactive prompt
8
15
  hax start
9
16
  ```
10
17
 
@@ -12,11 +19,12 @@ hax start
12
19
 
13
20
  ## Default / global / new context
14
21
  - `hax start` - fun ascii art and interactive CLI (via [clack](https://www.clack.cc/) )
15
- - `hax --name my-element --y` - Make a new HAX capable, i18n wired, Design system (DDD) driven web component
22
+ - `hax webcomponent my-element --y` - Make a new HAX capable, i18n wired, Design system (DDD) driven web component
16
23
  - if in a monorepo root, will place in correct location / inherit settings
17
24
  - `hax site mysite --y` - create a new HAXsite (HAXcms, single site)
18
25
 
19
26
  ## --help
27
+ Run `hax help` or `hax webcomponent --help` or `hax site --help` for up-to-date listing
20
28
  ```
21
29
  Usage: hax [options] [command]
22
30
 
@@ -70,12 +78,8 @@ Commands:
70
78
  npx @haxtheweb/create
71
79
  # this is same as above, better windows CLI support
72
80
  npm init @haxtheweb
73
- ```
74
-
75
- ## Usage in other programs
76
- https://stackoverflow.com/questions/69208298/use-node-bins-without-installing-the-package-globally explains it but you should be able to use the CLI as part of another project as follows:
77
- ```json
78
- {
81
+ - Try Hax: https://hax.cloud
82
+ - HAXCellence https://haxtheweb.org/what-is-hax
79
83
  "scripts": {
80
84
  "hax": "hax"
81
85
  }
@@ -109,3 +113,25 @@ Build a HAX site that can be published and transported anywhere. Your users migh
109
113
  - Ability to import via URL just like the front-end
110
114
  - Theme development starting point to be able to build themes locally
111
115
  - Primed to publish to gh-pages, vercel and more
116
+
117
+ # Get Help / Issues / Support
118
+ - Discord Channel - https://bit.ly/hax-discord
119
+ - Unified issue queue - https://github.com/haxtheweb/issues/issues
120
+ - Using Merlin directly in any HAX spaces and type "Issue" to jump start a report!
121
+
122
+ ## Watch and Learn more about HAX here:
123
+ - Try Hax: https://hax.cloud
124
+ - HAXCellence https://haxtheweb.org/what-is-hax
125
+ - Youtube channel - https://www.youtube.com/@haxtheweb
126
+
127
+ # Related links and tech
128
+ - [NPM Package list](https://www.npmjs.com/org/haxtheweb)
129
+ - [HAXcms (NodeJS)](https://github.com/haxtheweb/haxcms-nodejs)
130
+ - [HAXcms (PHP)](https://github.com/haxtheweb/haxcms-php)
131
+ - [Storybook docs](https://open-apis.hax.cloud/)
132
+ - [HAX [dot] PSU](https://hax.psu.edu)
133
+ - [HAX doc site](https://haxtheweb.org/)
134
+ - [HAX + 11ty](https://github.com/haxtheweb/hax11ty)
135
+
136
+
137
+ ![HAX Traveler: World Changer](https://raw.githubusercontent.com/haxtheweb/art/refs/heads/main/haxtheweb/hax-traveler-world-changer.jpg)
package/dist/create.js CHANGED
@@ -28,10 +28,10 @@ exec('git --version', error => {
28
28
  });
29
29
  async function main() {
30
30
  var commandRun = {};
31
- _commander.program.option('--').option('--v', 'Verbose output for developers').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('--auto', 'yes to all questions, alias of y')
31
+ _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('--auto', 'yes to all questions, alias of y')
32
32
 
33
33
  // options for webcomponent
34
- .option('--org <char>', 'organization for package.json').option('--author <char>', 'author for site / package.json')
34
+ .option('--org <char>', 'organization for package.json').option('--author <char>', 'author for site / package.json').option('--writeHaxProperties', 'Write haxProperties for the element')
35
35
 
36
36
  // options for site
37
37
  .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').helpCommand(true);
@@ -80,14 +80,14 @@ async function main() {
80
80
  commandRun.arguments.name = name;
81
81
  commandRun.options.skip = true;
82
82
  }
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');
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');
84
84
  // process program arguments
85
85
  _commander.program.parse();
86
86
  commandRun.options = {
87
87
  ...commandRun.options,
88
88
  ..._commander.program.opts()
89
89
  };
90
- if (commandRun.options.v) {
90
+ if (commandRun.options.debug) {
91
91
  console.log(commandRun);
92
92
  }
93
93
  // auto and y assume same thing
@@ -109,9 +109,14 @@ async function main() {
109
109
  if (!commandRun.options.path && commandRun.options.skip) {
110
110
  commandRun.options.path = process.cwd();
111
111
  }
112
- if (commandRun.options.auto) {
113
- commandRun.options.org = '';
114
- commandRun.options.author = author;
112
+ // if we skip stuff then set org/author automatically
113
+ if (commandRun.options.skip || commandRun.options.auto) {
114
+ if (!commandRun.options.org) {
115
+ commandRun.options.org = '';
116
+ }
117
+ if (!commandRun.options.author) {
118
+ commandRun.options.author = author;
119
+ }
115
120
  }
116
121
  let packageData = {};
117
122
  let testPackages = [path.join(process.cwd(), 'package.json'), path.join(process.cwd(), '../', 'package.json'), path.join(process.cwd(), '../', '../', 'package.json')];
@@ -121,7 +126,10 @@ async function main() {
121
126
  let packLoc = testPackages.shift();
122
127
  if (fs.existsSync(packLoc)) {
123
128
  try {
124
- packageData = JSON.parse(fs.readFileSync(`${process.cwd()}/package.json`));
129
+ packageData = {
130
+ ...JSON.parse(fs.readFileSync(packLoc)),
131
+ ...packageData
132
+ };
125
133
  // assume we are working on a web component / existing if we find this key
126
134
  if (packageData.hax && packageData.hax.cli) {
127
135
  commandRun.program = 'webcomponent';
@@ -129,6 +137,8 @@ async function main() {
129
137
  // leverage these values if they exist downstream
130
138
  if (packageData.npmClient) {
131
139
  commandRun.options.npmClient = packageData.npmClient;
140
+ } else {
141
+ commandRun.options.npmClient = 'npm';
132
142
  }
133
143
  // see if we're in a monorepo
134
144
  if (packageData.useWorkspaces && packageData.workspaces && packageData.workspaces.packages && packageData.workspaces.packages[0]) {
@@ -149,12 +159,15 @@ async function main() {
149
159
  }
150
160
  }
151
161
  }
162
+ if (commandRun.options.debug) {
163
+ console.log(packageData);
164
+ }
152
165
  // CLI works within context of the site if one is detected, otherwise we can do other thingss
153
166
  if (await hax.systemStructureContext()) {
154
167
  commandRun.program = 'site';
155
168
  commandRun.options.skip = true;
156
169
  await (0, _site.siteCommandDetected)(commandRun);
157
- } else if (packageData && packageData.hax && packageData.hax.cli && packageData.scripts.start) {
170
+ } else if (packageData && (packageData.customElements || packageData.hax && packageData.hax.cli) && packageData.scripts.start) {
158
171
  commandRun.program = 'webcomponent';
159
172
  commandRun.options.skip = true;
160
173
  await (0, _webcomponent.webcomponentCommandDetected)(commandRun, packageData);
@@ -198,7 +211,7 @@ async function main() {
198
211
  label: '🏗️ Create a Web Component'
199
212
  }, {
200
213
  value: 'site',
201
- label: '🏡 Create a HAXcms site (single)'
214
+ label: '🏡 Create a HAXsite'
202
215
  }, {
203
216
  value: 'quit',
204
217
  label: '🚪 Quit'
@@ -8,11 +8,14 @@ exports.siteActions = siteActions;
8
8
  exports.siteCommandDetected = siteCommandDetected;
9
9
  exports.siteItemsOptionsList = siteItemsOptionsList;
10
10
  exports.siteNodeOperations = siteNodeOperations;
11
+ exports.siteNodeStatsOperations = siteNodeStatsOperations;
11
12
  exports.siteProcess = siteProcess;
12
13
  exports.siteThemeList = siteThemeList;
13
14
  var _promises = require("node:timers/promises");
14
15
  var p = _interopRequireWildcard(require("@clack/prompts"));
15
16
  var _picocolors = _interopRequireDefault(require("picocolors"));
17
+ var _jsYaml = require("js-yaml");
18
+ var _nodeHtmlParser = require("node-html-parser");
16
19
  var _statements = require("../statements.js");
17
20
  var _microFrontendRegistry = require("../micro-frontend-registry.js");
18
21
  var haxcmsNodejsCli = _interopRequireWildcard(require("@haxtheweb/haxcms-nodejs/dist/cli.js"));
@@ -36,10 +39,27 @@ exec('surge --version', error => {
36
39
  sysSurge = false;
37
40
  }
38
41
  });
39
- const fakeSend = {
40
- send: json => console.log(json),
41
- sendStatus: data => console.log(data)
42
- };
42
+
43
+ // fake response class so we can capture the response from the headless route as opposed to print to console
44
+ // this way we can handle as data or if use is requesting output format to change we can respond
45
+ class Res {
46
+ constructor() {
47
+ this.query = {};
48
+ this.data = null;
49
+ this.statusCode = null;
50
+ }
51
+ send(data) {
52
+ this.data = data;
53
+ return this;
54
+ }
55
+ status(status) {
56
+ this.statusCode = status;
57
+ return this;
58
+ }
59
+ setHeader() {
60
+ return this;
61
+ }
62
+ }
43
63
  function siteActions() {
44
64
  return [{
45
65
  value: 'start',
@@ -53,6 +73,9 @@ function siteActions() {
53
73
  }, {
54
74
  value: 'theme',
55
75
  label: "Change theme"
76
+ }, {
77
+ value: 'node:stats',
78
+ label: "Page stats"
56
79
  }, {
57
80
  value: 'node:add',
58
81
  label: "Add page"
@@ -62,6 +85,9 @@ function siteActions() {
62
85
  }, {
63
86
  value: 'node:delete',
64
87
  label: "Delete page"
88
+ }, {
89
+ value: 'file:list',
90
+ label: "List files"
65
91
  }];
66
92
  }
67
93
  async function siteCommandDetected(commandRun) {
@@ -138,6 +164,56 @@ async function siteCommandDetected(commandRun) {
138
164
  console.log(e.stderr);
139
165
  }
140
166
  break;
167
+ case "node:stats":
168
+ try {
169
+ if (!commandRun.options.itemId) {
170
+ commandRun.options.itemId = await p.select({
171
+ message: `Select an item to edit`,
172
+ required: true,
173
+ options: [{
174
+ value: null,
175
+ label: "-- edit nothing, exit --"
176
+ }, ...(await siteItemsOptionsList(activeHaxsite))]
177
+ });
178
+ }
179
+ if (commandRun.options.itemId) {
180
+ let nodeOps = siteNodeStatsOperations();
181
+ let page = activeHaxsite.loadNode(commandRun.options.itemId);
182
+ // select which aspect of this we are editing
183
+ if (!commandRun.options.nodeOp) {
184
+ commandRun.options.nodeOp = await p.select({
185
+ message: `${page.title} (${page.id}) - Node operations`,
186
+ required: true,
187
+ options: [{
188
+ value: null,
189
+ label: "-- Exit --"
190
+ }, ...nodeOps]
191
+ });
192
+ }
193
+ if (commandRun.options.nodeOp && siteNodeStatsOperations(commandRun.options.nodeOp)) {
194
+ switch (commandRun.options.nodeOp) {
195
+ case 'details':
196
+ console.log(page);
197
+ break;
198
+ case 'html':
199
+ console.log(await activeHaxsite.getPageContent(page));
200
+ break;
201
+ case 'schema':
202
+ // next up
203
+ let html = await activeHaxsite.getPageContent(page);
204
+ let dom = (0, _nodeHtmlParser.parse)(html);
205
+ console.log(dom);
206
+ break;
207
+ case 'md':
208
+ // @todo use the built in endpoints broker
209
+ break;
210
+ }
211
+ }
212
+ }
213
+ } catch (e) {
214
+ console.log(e.stderr);
215
+ }
216
+ break;
141
217
  case "node:add":
142
218
  try {
143
219
  // @todo accept title if not supplied
@@ -365,6 +441,18 @@ async function siteCommandDetected(commandRun) {
365
441
  console.log(e.stderr);
366
442
  }
367
443
  break;
444
+ case "file:list":
445
+ let res = new Res();
446
+ await hax.RoutesMap.get.listFiles({
447
+ query: activeHaxsite.name,
448
+ filename: commandRun.options.filename
449
+ }, res);
450
+ if (commandRun.options.format === 'yaml') {
451
+ console.log((0, _jsYaml.dump)(res.data));
452
+ } else {
453
+ console.log(res.data);
454
+ }
455
+ break;
368
456
  case "quit":
369
457
  // quit
370
458
  process.exit(0);
@@ -377,6 +465,30 @@ async function siteCommandDetected(commandRun) {
377
465
  }
378
466
  (0, _statements.communityStatement)();
379
467
  }
468
+ function siteNodeStatsOperations(search = null) {
469
+ let obj = [{
470
+ value: 'details',
471
+ label: "Details"
472
+ }, {
473
+ value: 'html',
474
+ label: "Page as HTML source"
475
+ }, {
476
+ value: 'schema',
477
+ label: "Page as HAXElementSchema"
478
+ }, {
479
+ value: 'md',
480
+ label: "Page as Markdown"
481
+ }];
482
+ if (search) {
483
+ for (const op of obj) {
484
+ if (op.value === search) {
485
+ return true;
486
+ }
487
+ }
488
+ return false;
489
+ }
490
+ return obj;
491
+ }
380
492
  function siteNodeOperations(search = null) {
381
493
  let obj = [{
382
494
  value: 'title',
@@ -417,26 +529,6 @@ function siteNodeOperations(search = null) {
417
529
  return obj;
418
530
  }
419
531
 
420
- // fake response clas so we can capture the response from the headless route as opposed to print to console
421
- class Res {
422
- constructor() {
423
- this.query = {};
424
- this.data = null;
425
- this.statusCode = null;
426
- }
427
- send(data) {
428
- this.data = data;
429
- return this;
430
- }
431
- status(status) {
432
- this.statusCode = status;
433
- return this;
434
- }
435
- setHeader() {
436
- return this;
437
- }
438
- }
439
-
440
532
  // broker a call to the open-api repo which is an express based wrapper for vercel (originally)
441
533
  // this ensures the calls are identical and yet are converted to something the CLI can leverage
442
534
  async function openApiBroker(call, body) {
@@ -447,7 +539,6 @@ async function openApiBroker(call, body) {
447
539
  // dynamic import... this might upset some stuff later bc it's not a direct reference
448
540
  // but it's working locally at least.
449
541
  const handler = await (specifier => new Promise(r => r(specifier)).then(s => _interopRequireWildcard(require(s))))(`${mfItem.endpoint.replace('/api/', '/dist/')}.js`);
450
- // start the fake response
451
542
  let res = new Res();
452
543
  let req = {
453
544
  body: JSON.stringify(body),
@@ -509,9 +600,17 @@ async function siteProcess(commandRun, project, port = '3000') {
509
600
  }
510
601
  }
511
602
  HAXCMS.cliWritePath = `${project.path}`;
603
+ let res = new Res();
512
604
  await hax.RoutesMap.post.createSite({
513
605
  body: siteRequest
514
- }, fakeSend);
606
+ }, res);
607
+ if (commandRun.options.v) {
608
+ if (commandRun.options.format === 'yaml') {
609
+ console.log((0, _jsYaml.dump)(res.data));
610
+ } else {
611
+ console.log(res.data);
612
+ }
613
+ }
515
614
  s.stop((0, _statements.merlinSays)(`${project.name} created!`));
516
615
  await (0, _promises.setTimeout)(500);
517
616
  if (project.gitRepo && !commandRun.options.isMonorepo) {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.webcomponentCommandDetected = webcomponentCommandDetected;
8
+ exports.webcomponentGenerateHAXSchema = webcomponentGenerateHAXSchema;
8
9
  exports.webcomponentProcess = webcomponentProcess;
9
10
  var fs = _interopRequireWildcard(require("node:fs"));
10
11
  var _promises = require("node:timers/promises");
@@ -27,6 +28,110 @@ exec('git --version', error => {
27
28
  sysGit = false;
28
29
  }
29
30
  });
31
+ class HAXWiring {
32
+ /**
33
+ * Return a haxProperties prototype / example structure
34
+ */
35
+ prototypeHaxProperties = () => {
36
+ // example properties valid for HAX context menu.
37
+ let props = {
38
+ api: "1",
39
+ type: "element",
40
+ editingElement: "core",
41
+ hideDefaultSettings: false,
42
+ canScale: true,
43
+ canEditSource: true,
44
+ contentEditable: false,
45
+ gizmo: {
46
+ title: "Tag name",
47
+ description: "",
48
+ icon: "icons:android",
49
+ color: "purple",
50
+ tags: ["Other"],
51
+ handles: [{
52
+ type: "data",
53
+ type_exclusive: false,
54
+ url: "src"
55
+ }],
56
+ meta: {
57
+ author: "auto"
58
+ },
59
+ requiresChildren: false,
60
+ requiresParent: false
61
+ },
62
+ settings: {
63
+ configure: [{
64
+ slot: "",
65
+ title: "Inner content",
66
+ description: "The slotted content that lives inside the tag",
67
+ inputMethod: "textfield",
68
+ icon: "android",
69
+ required: true,
70
+ validationType: "text"
71
+ }, {
72
+ slot: "button",
73
+ title: "Button content",
74
+ description: "The content that can override the button",
75
+ inputMethod: "textfield",
76
+ icon: "android",
77
+ required: true,
78
+ validationType: "text"
79
+ }, {
80
+ property: "title",
81
+ title: "Title",
82
+ description: "",
83
+ inputMethod: "textfield",
84
+ icon: "android",
85
+ required: true,
86
+ validationType: "text"
87
+ }, {
88
+ property: "primaryColor",
89
+ title: "Title",
90
+ description: "",
91
+ inputMethod: "textfield",
92
+ icon: "android",
93
+ required: false,
94
+ validation: ".*",
95
+ validationType: "text"
96
+ }],
97
+ advanced: [{
98
+ property: "secondaryColor",
99
+ title: "Secondary color",
100
+ description: "An optional secondary color used in certain edge cases.",
101
+ inputMethod: "colorpicker",
102
+ icon: "color"
103
+ }, {
104
+ property: "endPoint",
105
+ title: "API endpoint",
106
+ description: "An optional endpoint to hit and load in more data dymaically.",
107
+ inputMethod: "textfield",
108
+ icon: "android",
109
+ validation: "[a-z0-9]",
110
+ validationType: "url"
111
+ }],
112
+ developer: []
113
+ },
114
+ saveOptions: {
115
+ wipeSlot: false,
116
+ unsetAttributes: ["end-point", "secondary-color"]
117
+ },
118
+ documentation: {
119
+ howTo: "https://haxtheweb.org/welcome",
120
+ purpose: "https://haxtheweb.org/welcome"
121
+ },
122
+ demoSchema: [{
123
+ tag: "my-tag",
124
+ content: "<p>inner html</p>",
125
+ properties: {
126
+ endPoint: "https://cdn2.thecatapi.com/images/9j5.jpg",
127
+ primaryColor: "yellow",
128
+ title: "A cat"
129
+ }
130
+ }]
131
+ };
132
+ return props;
133
+ };
134
+ }
30
135
 
31
136
  // processing an element
32
137
  async function webcomponentProcess(commandRun, project, port = "8000") {
@@ -117,7 +222,7 @@ async function webcomponentProcess(commandRun, project, port = "8000") {
117
222
  await exec(`cd ${project.path}/${project.name} && ${commandRun.options.npmClient} install`);
118
223
  }
119
224
  } catch (e) {
120
- console.log(e);
225
+ console.warn(e);
121
226
  }
122
227
  s.stop((0, _statements.merlinSays)(`Everything is installed. It's go time`));
123
228
  }
@@ -155,8 +260,12 @@ ${_picocolors.default.underline(_picocolors.default.cyan(`http://localhost:${por
155
260
  // autodetect webcomponent
156
261
  async function webcomponentCommandDetected(commandRun, packageData = {}, port = "8000") {
157
262
  p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` HAXTheWeb : Webcomponent detected `))}`);
158
- p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Name: ${packageData.name} `))}`);
159
- p.note(`${(0, _statements.merlinSays)(`I have summoned a sub-process daemon 👹`)}
263
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Web component name: ${packageData.name} `))}`);
264
+ // if we support customElement analyzer (hax wcs do) then generate if asked
265
+ if (commandRun.options.writeHaxProperties && packageData.customElements) {
266
+ webcomponentGenerateHAXSchema(commandRun, packageData);
267
+ } else {
268
+ p.note(`${(0, _statements.merlinSays)(`I have summoned a sub-process daemon 👹`)}
160
269
 
161
270
  🚀 Running your ${_picocolors.default.bold('webcomponent')} ${_picocolors.default.bold(packageData.name)}:
162
271
  ${_picocolors.default.underline(_picocolors.default.cyan(`http://localhost:${port}`))}
@@ -169,16 +278,111 @@ async function webcomponentCommandDetected(commandRun, packageData = {}, port =
169
278
 
170
279
  ⌨️ To exit 🧙 Merlin press: ${_picocolors.default.bold(_picocolors.default.black(_picocolors.default.bgRed(` CTRL + C `)))}
171
280
  `);
172
- try {
173
- // ensure it's installed first, unless it's a monorepo
174
- if (!commandRun.options.isMonorepo) {
175
- let s = p.spinner();
176
- s.start((0, _statements.merlinSays)(`Installation magic (${commandRun.options.npmClient} install)`));
177
- await exec(`${commandRun.options.npmClient} install`);
178
- s.stop((0, _statements.merlinSays)(`Everything is installed. It's go time`));
281
+ try {
282
+ // ensure it's installed first, unless it's a monorepo. basic check for node_modules
283
+ // folder as far as if already installed so we don't double install needlessly
284
+ if (!commandRun.options.isMonorepo && !fs.existsSync("./node_modules")) {
285
+ let s = p.spinner();
286
+ s.start((0, _statements.merlinSays)(`Installation magic (${commandRun.options.npmClient} install)`));
287
+ await exec(`${commandRun.options.npmClient} install`);
288
+ s.stop((0, _statements.merlinSays)(`Everything is installed. It's go time`));
289
+ }
290
+ await exec(`${commandRun.options.npmClient} start`);
291
+ } catch (e) {
292
+ // don't log bc output is odd
179
293
  }
180
- await exec(`${commandRun.options.npmClient} start`);
181
- } catch (e) {
182
- // don't log bc output is odd
183
294
  }
295
+ }
296
+
297
+ // merge the web component factory libraries the user has installed
298
+ async function webcomponentGenerateHAXSchema(commandRun, packageData) {
299
+ // run analyzer automatically if we have it so that it's up to date
300
+ if (packageData.scripts.analyze) {
301
+ await exec(`${commandRun.options.npmClient} run analyze`);
302
+ }
303
+ if (fs.existsSync(`${process.cwd()}/${packageData.customElements}`)) {
304
+ const ceFileData = fs.readFileSync(`${process.cwd()}/${packageData.customElements}`, 'utf8', (error, data) => {
305
+ if (error) {
306
+ console.warn(error);
307
+ return;
308
+ }
309
+ return data;
310
+ });
311
+ let wiring = new HAXWiring();
312
+ if (commandRun.options.debug) {
313
+ console.log(ceFileData);
314
+ }
315
+ if (ceFileData) {
316
+ let ce = JSON.parse(ceFileData);
317
+ await ce.modules.forEach(async modules => {
318
+ await modules.declarations.forEach(async declarations => {
319
+ let props = wiring.prototypeHaxProperties();
320
+ props.gizmo.title = declarations.tagName.replace('-', ' ');
321
+ props.gizmo.tags = ["Other"];
322
+ props.gizmo.handles = [];
323
+ props.gizmo.meta.author = "HAXTheWeb core team";
324
+ delete props.gizmo.shortcutKey;
325
+ delete props.gizmo.requiresChildren;
326
+ delete props.gizmo.requiresParent;
327
+ props.settings.configure = [];
328
+ props.settings.advanced = [];
329
+ props.documentation = {
330
+ howTo: null,
331
+ purpose: null
332
+ };
333
+ props.saveOptions = {
334
+ unsetAttributes: []
335
+ };
336
+ props.demoSchema = [{
337
+ tag: declarations.tagName,
338
+ content: "",
339
+ properties: {}
340
+ }];
341
+ let propData = [];
342
+ if (declarations.attributes) {
343
+ propData = declarations.attributes;
344
+ }
345
+ // loop through and if props are things we can map then do it
346
+ await propData.forEach(async prop => {
347
+ if (["t", "colors", '_haxState', "elementVisible"].includes(prop.fieldName)) {
348
+ props.saveOptions.unsetAttributes.push(prop.fieldName);
349
+ } else {
350
+ let type = "textfield";
351
+ if (prop.type && prop.type.text) {
352
+ type = getInputMethodFromType(prop.type.text);
353
+ }
354
+ if (type) {
355
+ let propSchema = {
356
+ property: prop.fieldName,
357
+ title: prop.name,
358
+ description: "",
359
+ inputMethod: type
360
+ };
361
+ if (prop.default !== undefined) {
362
+ props.demoSchema[0].properties[prop.fieldName] = prop.default;
363
+ }
364
+ props.settings.configure.push(propSchema);
365
+ }
366
+ }
367
+ });
368
+ if (commandRun.options.v) {
369
+ console.log(JSON.stringify(props, null, 2));
370
+ }
371
+ fs.writeFileSync(`./lib/${declarations.tagName}.haxProperties.json`, JSON.stringify(props, null, 2));
372
+ console.log(`schema written to: ./lib/${declarations.tagName}.haxProperties.json`);
373
+ });
374
+ });
375
+ }
376
+ }
377
+ }
378
+ function getInputMethodFromType(type) {
379
+ switch (type) {
380
+ case "string":
381
+ return "textfield";
382
+ case "number":
383
+ return "number";
384
+ case "boolean":
385
+ return "boolean";
386
+ }
387
+ return false;
184
388
  }
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@babel/preset-env": "^7.16.4",
36
- "@custom-elements-manifest/analyzer": "^0.4.17",
36
+ "@custom-elements-manifest/analyzer": "^0.10.3",
37
37
  "@open-wc/building-rollup": "^3.0.2",
38
38
  "@rollup/plugin-babel": "^6.0.4",
39
39
  "@rollup/plugin-node-resolve": "^15.2.3",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haxtheweb/create",
3
- "version": "9.0.11",
3
+ "version": "9.0.12",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -42,20 +42,22 @@
42
42
  "dependencies": {
43
43
  "@clack/core": "0.3.4",
44
44
  "@clack/prompts": "0.7.0",
45
- "@haxtheweb/haxcms-nodejs": "^9.0.15",
45
+ "@haxtheweb/haxcms-nodejs": "^9.0.17",
46
46
  "@haxtheweb/open-apis": "^9.0.11",
47
+ "commander": "12.1.0",
48
+ "node-html-parser": "6.1.13",
47
49
  "ejs": "3.1.10",
48
- "picocolors": "1.0.1",
49
- "commander": "12.1.0"
50
+ "js-yaml": "4.1.0",
51
+ "picocolors": "1.0.1"
50
52
  },
51
53
  "devDependencies": {
52
- "nodemon": "^3.1.7",
53
54
  "@babel/cli": "^7.24.6",
54
55
  "@babel/core": "^7.24.6",
55
56
  "@babel/preset-env": "7.24.6",
56
57
  "@babel/register": "^7.24.6",
57
- "@custom-elements-manifest/analyzer": "^0.10.2",
58
+ "@custom-elements-manifest/analyzer": "^0.10.3",
58
59
  "babel-plugin-transform-dynamic-import": "^2.1.0",
59
- "commit-and-tag-version": "12.4.1"
60
+ "commit-and-tag-version": "12.4.1",
61
+ "nodemon": "^3.1.7"
60
62
  }
61
63
  }