@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 +34 -8
- package/dist/create.js +23 -10
- package/dist/lib/programs/site.js +125 -26
- package/dist/lib/programs/webcomponent.js +217 -13
- package/dist/templates/webcomponent/hax/package.json +1 -1
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
2
|
+
[](https://lit.dev/)
|
|
3
|
+
[](https://haxtheweb.org/)
|
|
4
|
+
[](https://www.npmjs.com/package/@haxtheweb/create)
|
|
5
|
+
[](https://github.com/haxtheweb/create/actions)
|
|
6
|
+
[](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
|
|
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
|
+

|
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.
|
|
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
|
|
113
|
-
|
|
114
|
-
commandRun.options.
|
|
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 =
|
|
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
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
},
|
|
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.
|
|
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(`
|
|
159
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
"
|
|
49
|
-
"
|
|
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.
|
|
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
|
}
|