@fluffjs/cli 0.1.14 → 0.1.15
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/Cli.d.ts +6 -1
- package/Cli.js +98 -86
- package/ComponentCompiler.js +1 -1
- package/DevServer.js +2 -2
- package/Typeguards.d.ts +6 -0
- package/Typeguards.js +6 -0
- package/package.json +1 -1
package/Cli.d.ts
CHANGED
|
@@ -22,7 +22,12 @@ export declare class Cli {
|
|
|
22
22
|
private buildTarget;
|
|
23
23
|
private serve;
|
|
24
24
|
private serveTarget;
|
|
25
|
-
private
|
|
25
|
+
private resolveEntryPoint;
|
|
26
|
+
private getEsbuildEntryConfig;
|
|
27
|
+
private getJsBundleName;
|
|
28
|
+
private collectStyles;
|
|
29
|
+
private loadTsConfig;
|
|
30
|
+
private generateEntryContent;
|
|
26
31
|
private findAllTsFiles;
|
|
27
32
|
private findFiles;
|
|
28
33
|
private matchesPatterns;
|
package/Cli.js
CHANGED
|
@@ -302,49 +302,16 @@ Examples:
|
|
|
302
302
|
if (this.noMinify) {
|
|
303
303
|
bundleOptions.minify = false;
|
|
304
304
|
}
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
: this.generateEntryPoint(srcDir, target.exclude);
|
|
308
|
-
let inlineStyles = '';
|
|
309
|
-
if (target.styles && target.styles.length > 0) {
|
|
310
|
-
const styleContents = [];
|
|
311
|
-
for (const stylePath of target.styles) {
|
|
312
|
-
const fullPath = path.resolve(srcDir, stylePath);
|
|
313
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
314
|
-
console.log(` ✓ Style: ${stylePath}`);
|
|
315
|
-
styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
const styleFiles = this.findFiles(srcDir, [stylePath]);
|
|
319
|
-
if (styleFiles.length === 0) {
|
|
320
|
-
console.warn(` ⚠ Style not found: ${fullPath}`);
|
|
321
|
-
}
|
|
322
|
-
for (const styleFile of styleFiles) {
|
|
323
|
-
console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
|
|
324
|
-
styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (styleContents.length > 0) {
|
|
329
|
-
inlineStyles = styleContents.join('\n');
|
|
330
|
-
if (bundleOptions.minify) {
|
|
331
|
-
const cssResult = await esbuild.transform(inlineStyles, {
|
|
332
|
-
loader: 'css',
|
|
333
|
-
minify: true
|
|
334
|
-
});
|
|
335
|
-
inlineStyles = cssResult.code;
|
|
336
|
-
}
|
|
337
|
-
console.log(' ✓ Bundled global styles');
|
|
338
|
-
}
|
|
339
|
-
}
|
|
305
|
+
const entry = this.resolveEntryPoint(target, srcDir);
|
|
306
|
+
const inlineStyles = await this.collectStyles(target, srcDir, bundleOptions.minify ?? true);
|
|
340
307
|
console.log(' Building with esbuild...');
|
|
341
|
-
const tsconfigRaw = target
|
|
342
|
-
? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
|
|
343
|
-
: '{}';
|
|
308
|
+
const tsconfigRaw = this.loadTsConfig(target, projectRoot);
|
|
344
309
|
const result = await esbuild.build({
|
|
345
|
-
|
|
310
|
+
...this.getEsbuildEntryConfig(entry),
|
|
346
311
|
bundle: true,
|
|
347
|
-
|
|
312
|
+
...(entry.useStdin
|
|
313
|
+
? { outfile: path.join(outDir, 'fluff-app.js') }
|
|
314
|
+
: { outdir: outDir, entryNames: '[name]' }),
|
|
348
315
|
format: 'esm',
|
|
349
316
|
platform: 'browser',
|
|
350
317
|
target: bundleOptions.target ?? 'es2022',
|
|
@@ -413,7 +380,7 @@ Examples:
|
|
|
413
380
|
}
|
|
414
381
|
}
|
|
415
382
|
if (target.assets) {
|
|
416
|
-
await this.copyAssets(target.assets, projectRoot, srcDir, outDir);
|
|
383
|
+
await this.copyAssets(target.assets, projectRoot, srcDir, outDir, target.indexHtml);
|
|
417
384
|
}
|
|
418
385
|
console.log(`✅ Target '${target.name}' built successfully!`);
|
|
419
386
|
}
|
|
@@ -503,40 +470,14 @@ Examples:
|
|
|
503
470
|
}
|
|
504
471
|
}
|
|
505
472
|
}
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
: this.generateEntryPoint(srcDir, target.exclude);
|
|
509
|
-
let inlineStyles = '';
|
|
510
|
-
if (target.styles && target.styles.length > 0) {
|
|
511
|
-
const styleContents = [];
|
|
512
|
-
for (const stylePath of target.styles) {
|
|
513
|
-
const fullPath = path.resolve(srcDir, stylePath);
|
|
514
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
515
|
-
console.log(` ✓ Style: ${stylePath}`);
|
|
516
|
-
styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
const styleFiles = this.findFiles(srcDir, [stylePath]);
|
|
520
|
-
if (styleFiles.length === 0) {
|
|
521
|
-
console.warn(` ⚠ Style not found: ${fullPath}`);
|
|
522
|
-
}
|
|
523
|
-
for (const styleFile of styleFiles) {
|
|
524
|
-
console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
|
|
525
|
-
styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (styleContents.length > 0) {
|
|
530
|
-
inlineStyles = styleContents.join('\n');
|
|
531
|
-
}
|
|
532
|
-
}
|
|
473
|
+
const entry = this.resolveEntryPoint(target, srcDir);
|
|
474
|
+
const inlineStyles = await this.collectStyles(target, srcDir, false);
|
|
533
475
|
if (target.indexHtml) {
|
|
534
476
|
const indexHtmlPath = path.join(srcDir, target.indexHtml);
|
|
535
477
|
if (fs.existsSync(indexHtmlPath)) {
|
|
536
478
|
const indexHtml = fs.readFileSync(indexHtmlPath, 'utf-8');
|
|
537
479
|
const transformed = await IndexHtmlTransformer.transform(indexHtml, {
|
|
538
|
-
jsBundle:
|
|
539
|
-
.replace('.ts', '.js'),
|
|
480
|
+
jsBundle: this.getJsBundleName(entry),
|
|
540
481
|
cssBundle: undefined,
|
|
541
482
|
inlineStyles: inlineStyles || undefined,
|
|
542
483
|
gzip: false,
|
|
@@ -547,16 +488,16 @@ Examples:
|
|
|
547
488
|
}
|
|
548
489
|
}
|
|
549
490
|
if (target.assets) {
|
|
550
|
-
this.copyAssetsForServe(target.assets, projectRoot, srcDir, outDir);
|
|
491
|
+
this.copyAssetsForServe(target.assets, projectRoot, srcDir, outDir, target.indexHtml);
|
|
551
492
|
}
|
|
552
493
|
console.log(`🚀 Starting dev server for '${target.name}'...`);
|
|
553
|
-
const tsconfigRaw = target
|
|
554
|
-
? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
|
|
555
|
-
: '{}';
|
|
494
|
+
const tsconfigRaw = this.loadTsConfig(target, projectRoot);
|
|
556
495
|
const ctx = await esbuild.context({
|
|
557
|
-
|
|
496
|
+
...this.getEsbuildEntryConfig(entry),
|
|
558
497
|
bundle: true,
|
|
559
|
-
|
|
498
|
+
...(entry.useStdin
|
|
499
|
+
? { outfile: path.join(outDir, 'fluff-app.js') }
|
|
500
|
+
: { outdir: outDir, entryNames: '[name]' }),
|
|
560
501
|
format: 'esm',
|
|
561
502
|
platform: 'browser',
|
|
562
503
|
target: 'es2022',
|
|
@@ -605,7 +546,72 @@ Examples:
|
|
|
605
546
|
console.log(' Press Ctrl+C to stop\n');
|
|
606
547
|
}
|
|
607
548
|
}
|
|
608
|
-
|
|
549
|
+
resolveEntryPoint(target, srcDir) {
|
|
550
|
+
const useStdin = !target.entryPoint;
|
|
551
|
+
const entryPointFile = target.entryPoint ? path.join(srcDir, target.entryPoint) : null;
|
|
552
|
+
const generatedEntry = useStdin ? this.generateEntryContent(srcDir, target.exclude) : null;
|
|
553
|
+
return { useStdin, entryPointFile, generatedEntry };
|
|
554
|
+
}
|
|
555
|
+
getEsbuildEntryConfig(entry) {
|
|
556
|
+
if (entry.useStdin && entry.generatedEntry) {
|
|
557
|
+
return {
|
|
558
|
+
stdin: {
|
|
559
|
+
contents: entry.generatedEntry.contents,
|
|
560
|
+
resolveDir: entry.generatedEntry.resolveDir,
|
|
561
|
+
loader: 'ts'
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
return { entryPoints: [entry.entryPointFile ?? ''] };
|
|
566
|
+
}
|
|
567
|
+
getJsBundleName(entry) {
|
|
568
|
+
if (entry.useStdin) {
|
|
569
|
+
return 'fluff-app.js';
|
|
570
|
+
}
|
|
571
|
+
return path.basename(entry.entryPointFile ?? '').replace('.ts', '.js');
|
|
572
|
+
}
|
|
573
|
+
async collectStyles(target, srcDir, minify) {
|
|
574
|
+
if (!target.styles || target.styles.length === 0) {
|
|
575
|
+
return '';
|
|
576
|
+
}
|
|
577
|
+
const styleContents = [];
|
|
578
|
+
for (const stylePath of target.styles) {
|
|
579
|
+
const fullPath = path.resolve(srcDir, stylePath);
|
|
580
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
581
|
+
console.log(` ✓ Style: ${stylePath}`);
|
|
582
|
+
styleContents.push(fs.readFileSync(fullPath, 'utf-8'));
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
const styleFiles = this.findFiles(srcDir, [stylePath]);
|
|
586
|
+
if (styleFiles.length === 0) {
|
|
587
|
+
console.warn(` ⚠ Style not found: ${fullPath}`);
|
|
588
|
+
}
|
|
589
|
+
for (const styleFile of styleFiles) {
|
|
590
|
+
console.log(` ✓ Style: ${path.relative(srcDir, styleFile)}`);
|
|
591
|
+
styleContents.push(fs.readFileSync(styleFile, 'utf-8'));
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (styleContents.length === 0) {
|
|
596
|
+
return '';
|
|
597
|
+
}
|
|
598
|
+
let inlineStyles = styleContents.join('\n');
|
|
599
|
+
if (minify) {
|
|
600
|
+
const cssResult = await esbuild.transform(inlineStyles, {
|
|
601
|
+
loader: 'css',
|
|
602
|
+
minify: true
|
|
603
|
+
});
|
|
604
|
+
inlineStyles = cssResult.code;
|
|
605
|
+
}
|
|
606
|
+
console.log(' ✓ Bundled global styles');
|
|
607
|
+
return inlineStyles;
|
|
608
|
+
}
|
|
609
|
+
loadTsConfig(target, projectRoot) {
|
|
610
|
+
return target.tsConfigPath
|
|
611
|
+
? fs.readFileSync(path.resolve(projectRoot, target.tsConfigPath), 'utf-8')
|
|
612
|
+
: '{}';
|
|
613
|
+
}
|
|
614
|
+
generateEntryContent(srcDir, exclude = []) {
|
|
609
615
|
const tsFiles = this.findAllTsFiles(srcDir, exclude);
|
|
610
616
|
for (const f of tsFiles) {
|
|
611
617
|
console.log(` ✓ ${path.relative(srcDir, f)}`);
|
|
@@ -617,9 +623,7 @@ Examples:
|
|
|
617
623
|
});
|
|
618
624
|
const program = t.program(importDecls);
|
|
619
625
|
const entryContent = generate(program, { compact: false }).code;
|
|
620
|
-
|
|
621
|
-
fs.writeFileSync(entryPath, entryContent);
|
|
622
|
-
return entryPath;
|
|
626
|
+
return { contents: entryContent, resolveDir: srcDir };
|
|
623
627
|
}
|
|
624
628
|
findAllTsFiles(dir, userExclude = []) {
|
|
625
629
|
const files = [];
|
|
@@ -632,7 +636,8 @@ Examples:
|
|
|
632
636
|
walk(fullPath);
|
|
633
637
|
}
|
|
634
638
|
else if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
635
|
-
const relativePath = path.relative(dir, fullPath)
|
|
639
|
+
const relativePath = path.relative(dir, fullPath)
|
|
640
|
+
.replace(/\\/g, '/');
|
|
636
641
|
const isExcluded = excludePatterns.some(pattern => this.matchGlob(entry.name, pattern) || this.matchGlob(relativePath, pattern));
|
|
637
642
|
if (!isExcluded) {
|
|
638
643
|
files.push(fullPath);
|
|
@@ -666,7 +671,8 @@ Examples:
|
|
|
666
671
|
matchesPatterns(filePath, patterns, baseDir) {
|
|
667
672
|
for (const pattern of patterns) {
|
|
668
673
|
const patternPath = path.join(baseDir, pattern);
|
|
669
|
-
if (fs.existsSync(patternPath) && fs.statSync(patternPath)
|
|
674
|
+
if (fs.existsSync(patternPath) && fs.statSync(patternPath)
|
|
675
|
+
.isDirectory()) {
|
|
670
676
|
const normalizedFile = filePath.replace(/\\/g, '/');
|
|
671
677
|
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
672
678
|
if (normalizedFile.startsWith(normalizedPattern + '/') || normalizedFile === normalizedPattern) {
|
|
@@ -684,11 +690,12 @@ Examples:
|
|
|
684
690
|
const isMatch = picomatch(pattern, { dot: false });
|
|
685
691
|
return isMatch(normalizedPath);
|
|
686
692
|
}
|
|
687
|
-
async copyAssets(assets, projectRoot, srcDir, outDir) {
|
|
693
|
+
async copyAssets(assets, projectRoot, srcDir, outDir, indexHtml) {
|
|
688
694
|
const compiler = new ComponentCompiler();
|
|
689
695
|
for (const asset of assets) {
|
|
690
696
|
const assetPath = path.resolve(srcDir, asset);
|
|
691
|
-
if (fs.existsSync(assetPath) && fs.statSync(assetPath)
|
|
697
|
+
if (fs.existsSync(assetPath) && fs.statSync(assetPath)
|
|
698
|
+
.isDirectory()) {
|
|
692
699
|
const dirName = path.basename(assetPath);
|
|
693
700
|
const targetDir = path.join(outDir, dirName);
|
|
694
701
|
await this.copyDirectoryRecursive(assetPath, targetDir, compiler);
|
|
@@ -704,6 +711,8 @@ Examples:
|
|
|
704
711
|
if (filePath.endsWith('.component.css'))
|
|
705
712
|
continue;
|
|
706
713
|
const relativePath = path.relative(srcDir, filePath);
|
|
714
|
+
if (indexHtml && relativePath === indexHtml)
|
|
715
|
+
continue;
|
|
707
716
|
const outPath = path.join(outDir, relativePath);
|
|
708
717
|
const outFileDir = path.dirname(outPath);
|
|
709
718
|
if (!fs.existsSync(outFileDir)) {
|
|
@@ -723,10 +732,11 @@ Examples:
|
|
|
723
732
|
}
|
|
724
733
|
}
|
|
725
734
|
}
|
|
726
|
-
copyAssetsForServe(assets, projectRoot, srcDir, outDir) {
|
|
735
|
+
copyAssetsForServe(assets, projectRoot, srcDir, outDir, indexHtml) {
|
|
727
736
|
for (const asset of assets) {
|
|
728
737
|
const assetPath = path.resolve(srcDir, asset);
|
|
729
|
-
if (fs.existsSync(assetPath) && fs.statSync(assetPath)
|
|
738
|
+
if (fs.existsSync(assetPath) && fs.statSync(assetPath)
|
|
739
|
+
.isDirectory()) {
|
|
730
740
|
const dirName = path.basename(assetPath);
|
|
731
741
|
const targetDir = path.join(outDir, dirName);
|
|
732
742
|
this.copyDirectoryRecursiveSync(assetPath, targetDir);
|
|
@@ -743,6 +753,8 @@ Examples:
|
|
|
743
753
|
if (filePath.endsWith('.ts'))
|
|
744
754
|
continue;
|
|
745
755
|
const relativePath = path.relative(srcDir, filePath);
|
|
756
|
+
if (indexHtml && relativePath === indexHtml)
|
|
757
|
+
continue;
|
|
746
758
|
const outPath = path.join(outDir, relativePath);
|
|
747
759
|
const outFileDir = path.dirname(outPath);
|
|
748
760
|
if (!fs.existsSync(outFileDir)) {
|
package/ComponentCompiler.js
CHANGED
|
@@ -3,8 +3,8 @@ import { parse } from '@babel/parser';
|
|
|
3
3
|
import * as t from '@babel/types';
|
|
4
4
|
import * as esbuild from 'esbuild';
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
-
import * as parse5 from 'parse5';
|
|
7
6
|
import { minify as minifyHtml } from 'html-minifier-terser';
|
|
7
|
+
import * as parse5 from 'parse5';
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import { SourceMapConsumer, SourceMapGenerator } from 'source-map';
|
|
10
10
|
import classTransformPlugin from './babel-plugin-class-transform.js';
|
package/DevServer.js
CHANGED
package/Typeguards.d.ts
CHANGED
|
@@ -20,5 +20,11 @@ export declare class Typeguards {
|
|
|
20
20
|
startOffset: number;
|
|
21
21
|
endOffset: number;
|
|
22
22
|
}>;
|
|
23
|
+
static hasPipeN(value: unknown): value is {
|
|
24
|
+
n: unknown;
|
|
25
|
+
};
|
|
26
|
+
static hasPipeA(value: unknown): value is {
|
|
27
|
+
a: unknown[];
|
|
28
|
+
};
|
|
23
29
|
}
|
|
24
30
|
//# sourceMappingURL=Typeguards.d.ts.map
|
package/Typeguards.js
CHANGED
|
@@ -27,4 +27,10 @@ export class Typeguards {
|
|
|
27
27
|
static isAttrsRecord(value) {
|
|
28
28
|
return value !== null && typeof value === 'object';
|
|
29
29
|
}
|
|
30
|
+
static hasPipeN(value) {
|
|
31
|
+
return value !== null && typeof value === 'object' && 'n' in value;
|
|
32
|
+
}
|
|
33
|
+
static hasPipeA(value) {
|
|
34
|
+
return value !== null && typeof value === 'object' && 'a' in value && Array.isArray(value.a);
|
|
35
|
+
}
|
|
30
36
|
}
|