@genexus/mercury 0.20.0 → 0.21.0
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/dist/bundles/css/all.css +1 -1
- package/dist/bundles/css/base/base-globant.css +1 -1
- package/dist/bundles/css/base/base.css +1 -1
- package/dist/bundles/css/components/accordion.css +1 -1
- package/dist/bundles/css/components/button.css +1 -1
- package/dist/bundles/css/components/chat.css +1 -1
- package/dist/bundles/css/components/code.css +1 -1
- package/dist/bundles/css/components/combo-box.css +1 -1
- package/dist/bundles/css/components/dialog.css +1 -1
- package/dist/bundles/css/components/dropdown.css +1 -1
- package/dist/bundles/css/components/edit.css +1 -1
- package/dist/bundles/css/components/flexible-layout.css +1 -1
- package/dist/bundles/css/components/icon.css +1 -1
- package/dist/bundles/css/components/list-box.css +1 -1
- package/dist/bundles/css/components/markdown-viewer.css +1 -1
- package/dist/bundles/css/components/navigation-list.css +1 -1
- package/dist/bundles/css/components/pills.css +1 -1
- package/dist/bundles/css/components/segmented-control.css +1 -1
- package/dist/bundles/css/components/slider.css +1 -1
- package/dist/bundles/css/components/switch.css +1 -1
- package/dist/bundles/css/components/tab.css +1 -1
- package/dist/bundles/css/components/tabular-grid.css +1 -1
- package/dist/bundles/css/components/tooltip.css +1 -1
- package/dist/bundles/css/utils/form--full.css +1 -1
- package/dist/bundles/css/utils/form.css +1 -1
- package/dist/bundles/css/utils/spacing.css +1 -1
- package/dist/cli/bundle.js +185 -17
- package/dist/cli/internal/constants.d.ts +3 -12
- package/dist/cli/internal/constants.js +4 -13
- package/dist/cli/internal/create-bundles-with-custom-paths.d.ts +10 -2
- package/dist/cli/internal/create-bundles-with-custom-paths.js +102 -55
- package/dist/cli/internal/file-management.d.ts +3 -2
- package/dist/cli/internal/file-management.js +45 -12
- package/dist/cli/internal/print-utils.d.ts +6 -6
- package/dist/cli/internal/print-utils.js +14 -12
- package/dist/cli/internal/transpile-bundle-and-create-mappings.d.ts +2 -3
- package/dist/cli/internal/transpile-bundle-and-create-mappings.js +37 -66
- package/dist/cli/internal/types.d.ts +0 -1
- package/dist/cli/internal/utils.d.ts +11 -8
- package/dist/cli/internal/utils.js +27 -22
- package/dist/cli/internal/validate-args.js +7 -1
- package/dist/cli/internal/watch-fs.d.ts +3 -0
- package/dist/cli/internal/watch-fs.js +92 -0
- package/dist/cli/mercury.js +2 -2
- package/package.json +17 -12
- package/dist/bundles/js/all.js +0 -1
- package/dist/bundles/js/base/base-globant.js +0 -1
- package/dist/bundles/js/base/base.js +0 -1
- package/dist/bundles/js/base/icons.js +0 -1
- package/dist/bundles/js/bundle-mappings.js +0 -237
- package/dist/bundles/js/chameleon/scrollbar.js +0 -1
- package/dist/bundles/js/components/accordion.js +0 -1
- package/dist/bundles/js/components/button.js +0 -1
- package/dist/bundles/js/components/chat.js +0 -1
- package/dist/bundles/js/components/checkbox.js +0 -1
- package/dist/bundles/js/components/code.js +0 -1
- package/dist/bundles/js/components/combo-box.js +0 -1
- package/dist/bundles/js/components/dialog.js +0 -1
- package/dist/bundles/js/components/dropdown.js +0 -1
- package/dist/bundles/js/components/edit.js +0 -1
- package/dist/bundles/js/components/flexible-layout.js +0 -1
- package/dist/bundles/js/components/icon.js +0 -1
- package/dist/bundles/js/components/layout-splitter.js +0 -1
- package/dist/bundles/js/components/list-box.js +0 -1
- package/dist/bundles/js/components/markdown-viewer.js +0 -1
- package/dist/bundles/js/components/navigation-list.js +0 -1
- package/dist/bundles/js/components/pills.js +0 -1
- package/dist/bundles/js/components/radio-group.js +0 -1
- package/dist/bundles/js/components/segmented-control.js +0 -1
- package/dist/bundles/js/components/sidebar.js +0 -1
- package/dist/bundles/js/components/slider.js +0 -1
- package/dist/bundles/js/components/switch.js +0 -1
- package/dist/bundles/js/components/tab.js +0 -1
- package/dist/bundles/js/components/tabular-grid.js +0 -1
- package/dist/bundles/js/components/ticket-list.js +0 -1
- package/dist/bundles/js/components/tooltip.js +0 -1
- package/dist/bundles/js/components/tree-view.js +0 -1
- package/dist/bundles/js/components/widget.js +0 -1
- package/dist/bundles/js/resets/box-sizing.js +0 -1
- package/dist/bundles/js/utils/elevation.js +0 -1
- package/dist/bundles/js/utils/form--full.js +0 -1
- package/dist/bundles/js/utils/form.js +0 -1
- package/dist/bundles/js/utils/layout.js +0 -1
- package/dist/bundles/js/utils/spacing.js +0 -1
- package/dist/bundles/js/utils/typography.js +0 -1
- package/dist/bundles/scss/all.scss +0 -8
- package/dist/bundles/scss/base/base.scss +0 -24
- package/dist/bundles/scss/base/icons.scss +0 -4
- package/dist/bundles/scss/chameleon/scrollbar.scss +0 -3
- package/dist/bundles/scss/components/accordion.scss +0 -3
- package/dist/bundles/scss/components/button.scss +0 -8
- package/dist/bundles/scss/components/chat.scss +0 -3
- package/dist/bundles/scss/components/checkbox.scss +0 -3
- package/dist/bundles/scss/components/code.scss +0 -3
- package/dist/bundles/scss/components/combo-box.scss +0 -3
- package/dist/bundles/scss/components/dialog.scss +0 -3
- package/dist/bundles/scss/components/dropdown.scss +0 -3
- package/dist/bundles/scss/components/edit.scss +0 -3
- package/dist/bundles/scss/components/flexible-layout.scss +0 -3
- package/dist/bundles/scss/components/icon.scss +0 -8
- package/dist/bundles/scss/components/layout-splitter.scss +0 -3
- package/dist/bundles/scss/components/list-box.scss +0 -3
- package/dist/bundles/scss/components/markdown-viewer.scss +0 -3
- package/dist/bundles/scss/components/navigation-list.scss +0 -3
- package/dist/bundles/scss/components/pills.scss +0 -3
- package/dist/bundles/scss/components/radio-group.scss +0 -3
- package/dist/bundles/scss/components/segmented-control.scss +0 -3
- package/dist/bundles/scss/components/sidebar.scss +0 -3
- package/dist/bundles/scss/components/slider.scss +0 -3
- package/dist/bundles/scss/components/switch.scss +0 -3
- package/dist/bundles/scss/components/tab.scss +0 -3
- package/dist/bundles/scss/components/tabular-grid.scss +0 -10
- package/dist/bundles/scss/components/ticket-list.scss +0 -3
- package/dist/bundles/scss/components/tooltip.scss +0 -3
- package/dist/bundles/scss/components/tree-view.scss +0 -3
- package/dist/bundles/scss/components/widget.scss +0 -3
- package/dist/bundles/scss/resets/box-sizing.scss +0 -3
- package/dist/bundles/scss/utils/elevation.scss +0 -4
- package/dist/bundles/scss/utils/form--full.scss +0 -20
- package/dist/bundles/scss/utils/form.scss +0 -4
- package/dist/bundles/scss/utils/layout.scss +0 -4
- package/dist/bundles/scss/utils/spacing.scss +0 -4
- package/dist/bundles/scss/utils/typography.scss +0 -9
- package/dist/mercury.scss +0 -24802
|
@@ -1,67 +1,114 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { BASE_BUNDLE, BASE_CSS_FILE, BASE_GLOBANT_BUNDLE, BASE_GLOBANT_CSS_FILE, BUNDLE_MAPPING_TO_HASH_FILE, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, HASH_AND_LETTER_LENGTH } from "./constants.js";
|
|
5
|
+
import { getFilesInDir } from "./file-management.js";
|
|
6
|
+
import { getBundleFolderAndFileBaseDir, getBundleName, getFileNameWithHash, getFileNameWithoutExt, getFileSize, getHash, sanitizeBundleName } from "./utils.js";
|
|
7
|
+
import { printBundleWasCreated, printBundleWasCreatedTableHeader } from "./print-utils.js";
|
|
8
|
+
export const createBundleWithCustomPath = (args, options, fileMetadata, avoidAllHashes, actualFilePath) => {
|
|
9
|
+
const { avoidHash, fontFacePath, iconsPath } = args;
|
|
10
|
+
const { bundleFolder, fileBaseDirToWrite } = options;
|
|
11
|
+
const fileNameWithoutExt = getFileNameWithoutExt(fileMetadata);
|
|
12
|
+
const bundleName = getBundleName(fileMetadata);
|
|
13
|
+
// Copy CSS bundle
|
|
14
|
+
let css = fs.readFileSync(actualFilePath ?? fileMetadata.filePath, {
|
|
15
|
+
encoding: "utf8"
|
|
12
16
|
});
|
|
13
|
-
|
|
17
|
+
if (fontFacePath !== DEFAULT_FONT_FACE_PATH) {
|
|
18
|
+
css = css.replaceAll(DEFAULT_FONT_FACE_PATH, fontFacePath);
|
|
19
|
+
}
|
|
20
|
+
if (iconsPath !== DEFAULT_ICONS_PATH) {
|
|
21
|
+
css = css.replaceAll(DEFAULT_ICONS_PATH, iconsPath);
|
|
22
|
+
}
|
|
23
|
+
const fileNameWithHash = avoidAllHashes || avoidHash.has(bundleName)
|
|
24
|
+
? fileNameWithoutExt
|
|
25
|
+
: getFileNameWithHash(fileNameWithoutExt, getHash(css));
|
|
26
|
+
const fileNameToWriteCss = `${fileNameWithHash}.css`;
|
|
27
|
+
const filePathWithHash = path.join(fileBaseDirToWrite, fileNameToWriteCss);
|
|
28
|
+
// Create the CSS bundle with hash
|
|
29
|
+
fs.writeFileSync(filePathWithHash, css);
|
|
30
|
+
return {
|
|
31
|
+
bundleName,
|
|
32
|
+
bundleNameWithHash: sanitizeBundleName(`${bundleFolder}/${fileNameWithHash}`),
|
|
33
|
+
fileSize: getFileSize(css)
|
|
34
|
+
};
|
|
14
35
|
};
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
: bundleName;
|
|
18
|
-
const shouldSkipBundleCreation = (bundleName, globant) => (bundleName === BASE_BUNDLE && globant) ||
|
|
19
|
-
(bundleName === BASE_GLOBANT_BUNDLE && !globant);
|
|
20
|
-
export const createBundlesWithCustomPaths = (args) => {
|
|
21
|
-
const { avoidHash, fontFacePath, iconsPath, globant } = args;
|
|
36
|
+
export const createBundlesWithCustomPaths = async (args, avoidAllHashes = false) => {
|
|
37
|
+
const hasGlobantVariant = args.globant;
|
|
22
38
|
const outDir = path.join(args.outDirPath);
|
|
23
39
|
const CREATED_DIRS = new Set();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
// This is a WA to have __filename and __dirname in ES modules
|
|
41
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
42
|
+
// Directory name where the script is located (<path from root to node_modules/@genexus/mercury>/dist/cli/)
|
|
43
|
+
const __dirname = path.dirname(__filename);
|
|
44
|
+
const cssOutput = path.join(__dirname, "../../bundles/css");
|
|
45
|
+
/**
|
|
46
|
+
* Files to transpile
|
|
47
|
+
*/
|
|
48
|
+
const allFilesToCopy = await getFilesInDir(cssOutput);
|
|
49
|
+
let largestBundleLength = BUNDLE_MAPPING_TO_HASH_FILE.length;
|
|
50
|
+
let largestFileSizeLength = 0;
|
|
51
|
+
allFilesToCopy.forEach(fileMetadata => {
|
|
52
|
+
const options = getBundleFolderAndFileBaseDir(fileMetadata, outDir);
|
|
53
|
+
largestBundleLength = Math.max(largestBundleLength, options.bundleFolder.length + fileMetadata.fileName.length);
|
|
54
|
+
});
|
|
55
|
+
if (!avoidAllHashes) {
|
|
56
|
+
largestBundleLength += HASH_AND_LETTER_LENGTH;
|
|
57
|
+
}
|
|
58
|
+
const copiedFiles = [];
|
|
59
|
+
allFilesToCopy.forEach(fileMetadata => {
|
|
60
|
+
const bundleName = getBundleName(fileMetadata);
|
|
61
|
+
const options = getBundleFolderAndFileBaseDir(fileMetadata, outDir);
|
|
62
|
+
const { fileBaseDirToWrite } = options;
|
|
63
|
+
let actualFilePath = fileMetadata.filePath;
|
|
64
|
+
if (!CREATED_DIRS.has(fileBaseDirToWrite)) {
|
|
65
|
+
CREATED_DIRS.add(fileBaseDirToWrite);
|
|
66
|
+
fs.mkdirSync(path.join(fileBaseDirToWrite), { recursive: true });
|
|
30
67
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
// There is no need to copy the base-globant.css file, since the base.css
|
|
69
|
+
// file already contains this file
|
|
70
|
+
if (hasGlobantVariant) {
|
|
71
|
+
if (bundleName === BASE_GLOBANT_BUNDLE) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Replace the content of the base bundle with the Globant variant
|
|
75
|
+
if (bundleName === BASE_BUNDLE) {
|
|
76
|
+
actualFilePath = actualFilePath.replace(BASE_CSS_FILE, BASE_GLOBANT_CSS_FILE);
|
|
77
|
+
}
|
|
37
78
|
}
|
|
38
|
-
|
|
39
|
-
? actualBundleName
|
|
40
|
-
: getBundleNameWithHash(actualBundleName, hash);
|
|
41
|
-
const filePathToCreateBundle = path.join(outDir, `${bundleNameWithHash}.css`);
|
|
42
|
-
fs.writeFileSync(filePathToCreateBundle, compiledBundleWithoutPlaceholders);
|
|
43
|
-
printBundleWasCreated({
|
|
44
|
-
outDir,
|
|
45
|
-
bundleName: actualBundleName,
|
|
46
|
-
compiledBundleWithoutPlaceholders,
|
|
47
|
-
filePathToCreateBundle,
|
|
48
|
-
// WA to improve style
|
|
49
|
-
largestBundleLength: largestBundleLength + (avoidHash.has(actualBundleName) ? 17 : 0)
|
|
50
|
-
});
|
|
51
|
-
// Store the bundle mapping.
|
|
52
|
-
// For example: "components/button" --> "components/button-9f82641938b85445"
|
|
53
|
-
const bundleToHashEntry = ` "${actualBundleName}": "${bundleNameWithHash}"`;
|
|
54
|
-
// Concat entries in the object
|
|
55
|
-
bundleMappingToHashObjectEntries +=
|
|
56
|
-
bundleMappingToHashObjectEntries === ""
|
|
57
|
-
? bundleToHashEntry
|
|
58
|
-
: ",\n" + bundleToHashEntry;
|
|
79
|
+
copiedFiles.push(createBundleWithCustomPath(args, options, fileMetadata, avoidAllHashes, actualFilePath));
|
|
59
80
|
});
|
|
60
|
-
|
|
81
|
+
copiedFiles.sort((a, b) => (a.bundleName <= b.bundleName ? -1 : 0));
|
|
82
|
+
const bundleMappingFileContent = `export const bundleToHashMappings = {\n${copiedFiles.map(entry => ` "${entry.bundleName}": "${entry.bundleNameWithHash}"`).join(",\n")}\n} as const;\n`;
|
|
83
|
+
const bundleMappingFileSize = getFileSize(bundleMappingFileContent);
|
|
61
84
|
const bundleMappingFilePath = path.join(outDir, BUNDLE_MAPPING_TO_HASH_FILE);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
85
|
+
// Compute the largest fileName length
|
|
86
|
+
largestFileSizeLength = copiedFiles.reduce((acc, copiedFile) => Math.max(acc, copiedFile.fileSize.length), bundleMappingFileSize.length);
|
|
87
|
+
printBundleWasCreatedTableHeader({
|
|
88
|
+
largestBundleLength: avoidAllHashes
|
|
89
|
+
? largestBundleLength
|
|
90
|
+
: largestBundleLength + 1,
|
|
91
|
+
outDir
|
|
92
|
+
});
|
|
93
|
+
// Print bundle created message
|
|
94
|
+
for (let index = 0; index < copiedFiles.length; index++) {
|
|
95
|
+
const entry = copiedFiles[index];
|
|
96
|
+
printBundleWasCreated({
|
|
97
|
+
bundleNameWithHash: `${entry.bundleNameWithHash}.css`,
|
|
98
|
+
fileSize: entry.fileSize,
|
|
99
|
+
largestBundleLength,
|
|
100
|
+
largestFileSizeLength,
|
|
101
|
+
outDir
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
fs.writeFileSync(bundleMappingFilePath, bundleMappingFileContent);
|
|
105
|
+
// Separate the TS file
|
|
106
|
+
console.log("");
|
|
107
|
+
printBundleWasCreated({
|
|
108
|
+
bundleNameWithHash: BUNDLE_MAPPING_TO_HASH_FILE,
|
|
109
|
+
fileSize: getFileSize(bundleMappingFileContent),
|
|
110
|
+
largestBundleLength,
|
|
111
|
+
largestFileSizeLength,
|
|
112
|
+
outDir
|
|
66
113
|
});
|
|
67
114
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FileMetadata } from "./types";
|
|
2
|
-
export declare const ensureDirectoryExistsAndItsClear: (dirPath: string) => void
|
|
3
|
-
export declare
|
|
2
|
+
export declare const ensureDirectoryExistsAndItsClear: (dirPath: string, filesToNotRemove?: Set<string>) => Promise<void>;
|
|
3
|
+
export declare const getFilesInDir: (dir: string) => Promise<FileMetadata[]>;
|
|
4
4
|
export declare const copyDirectories: (srcDir: string, outDir: string) => void;
|
|
5
|
+
export declare const refreshAngularBrowser: () => void;
|
|
@@ -1,20 +1,53 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { readdir, rm } from "node:fs/promises";
|
|
4
|
+
export const ensureDirectoryExistsAndItsClear = async (dirPath, filesToNotRemove) => {
|
|
5
|
+
// First build
|
|
6
|
+
if (!fs.existsSync(dirPath)) {
|
|
7
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
// Incremental rebuild keeps some file without any changes, so we must skip
|
|
11
|
+
// the file deletion
|
|
12
|
+
if (filesToNotRemove) {
|
|
13
|
+
const filesInDir = await getFilesInDir(dirPath);
|
|
14
|
+
await Promise.all(filesInDir.map(file => filesToNotRemove.has(file.filePath)
|
|
15
|
+
? Promise.resolve()
|
|
16
|
+
: rm(file.filePath)));
|
|
17
|
+
}
|
|
18
|
+
// Incremental rebuild did not include any file to exclude its removal
|
|
19
|
+
else {
|
|
5
20
|
fs.rmSync(dirPath, { recursive: true });
|
|
21
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
6
22
|
}
|
|
7
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
8
23
|
};
|
|
9
|
-
export
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
export const getFilesInDir = async (dir) => {
|
|
25
|
+
const filesAndDirs = await readdir(dir, {
|
|
26
|
+
withFileTypes: true,
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
const files = [];
|
|
30
|
+
for (let index = 0; index < filesAndDirs.length; index++) {
|
|
31
|
+
const file = filesAndDirs[index];
|
|
32
|
+
if (file.isFile()) {
|
|
33
|
+
files.push({
|
|
34
|
+
dir: file.parentPath,
|
|
35
|
+
fileName: file.name,
|
|
36
|
+
filePath: path.join(file.parentPath, file.name)
|
|
37
|
+
});
|
|
17
38
|
}
|
|
18
39
|
}
|
|
19
|
-
|
|
40
|
+
return files;
|
|
41
|
+
};
|
|
20
42
|
export const copyDirectories = (srcDir, outDir) => fs.cpSync(srcDir, outDir, { recursive: true });
|
|
43
|
+
export const refreshAngularBrowser = () => {
|
|
44
|
+
const ANGULAR_FILE_TO_TRIGGER_RELOAD = path.join(process.cwd(), "../showcase/src/index.html");
|
|
45
|
+
const FILE_CONTENT = fs.readFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, {
|
|
46
|
+
encoding: "utf8"
|
|
47
|
+
});
|
|
48
|
+
// Trigger a dummy write in the index.html
|
|
49
|
+
fs.writeFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, FILE_CONTENT + "\n");
|
|
50
|
+
// Rollback that write to not provoke any changes, but do it after the
|
|
51
|
+
// debounce of the Angular CLI has completed the queued HMR
|
|
52
|
+
setTimeout(() => fs.writeFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, FILE_CONTENT), 300);
|
|
53
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const printBundleWasCreatedTableHeader: (args: {
|
|
2
2
|
outDir: string;
|
|
3
|
-
bundleName: string;
|
|
4
3
|
largestBundleLength: number;
|
|
5
|
-
filePathToCreateBundle: string;
|
|
6
|
-
compiledBundleWithoutPlaceholders: string;
|
|
7
4
|
}) => void;
|
|
8
|
-
export declare const
|
|
5
|
+
export declare const printBundleWasCreated: (args: {
|
|
9
6
|
outDir: string;
|
|
10
|
-
|
|
7
|
+
bundleNameWithHash: string;
|
|
8
|
+
largestBundleLength: number;
|
|
9
|
+
largestFileSizeLength: number;
|
|
10
|
+
fileSize: string;
|
|
11
11
|
}) => void;
|
|
12
12
|
export declare const printBundleWasTranspiled: (filePath: string) => void;
|
|
13
13
|
export declare const printArgumentDoesNotExistsError: (arg: string) => void;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { styleText } from "node:util";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export const
|
|
10
|
-
styleText("greenBright",
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
import { DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, DEFAULT_OUT_DIR_PATH, SCSS_BUNDLES_INPUT_DIR, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const separator = () => styleText(["gray"], " | ");
|
|
5
|
+
export const printBundleWasCreatedTableHeader = (args) => console.log(styleText(["white", "bold"], "Files") +
|
|
6
|
+
" ".repeat(args.largestBundleLength + args.outDir.length - "Files".length) +
|
|
7
|
+
separator() +
|
|
8
|
+
styleText(["white", "bold"], "Raw size"));
|
|
9
|
+
export const printBundleWasCreated = (args) => console.log(styleText("white", args.outDir) +
|
|
10
|
+
styleText("greenBright", path.join(args.outDir, args.bundleNameWithHash).replace(args.outDir, "")) +
|
|
11
|
+
" ".repeat(Math.max(args.largestBundleLength - args.bundleNameWithHash.length, 0)) +
|
|
12
|
+
separator() +
|
|
13
|
+
" ".repeat(Math.max(args.largestFileSizeLength - args.fileSize.length, 0)) +
|
|
14
|
+
styleText("cyanBright", args.fileSize));
|
|
13
15
|
export const printBundleWasTranspiled = (filePath) => console.log(styleText("greenBright", " Transpiled: ") +
|
|
14
16
|
styleText("white", SCSS_BUNDLES_OUT_DIR) +
|
|
15
|
-
styleText("whiteBright", filePath.replace(
|
|
17
|
+
styleText("whiteBright", filePath.replace(SCSS_BUNDLES_INPUT_DIR, "")));
|
|
16
18
|
export const printArgumentDoesNotExistsError = (arg) => console.log(styleText("red", " error ") +
|
|
17
19
|
styleText("gray", "Argument does not exists: ") +
|
|
18
20
|
`'${arg}'`);
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { FileMetadata } from "./types
|
|
2
|
-
export declare const transpileCssBundleWithPlaceholder: (fileMetadata: FileMetadata) => void
|
|
3
|
-
export declare const createBundleMappingsFile: () => void;
|
|
1
|
+
import type { CLIArguments, FileMetadata } from "./types";
|
|
2
|
+
export declare const transpileCssBundleWithPlaceholder: (fileMetadata: FileMetadata, args?: CLIArguments) => Promise<void>;
|
|
@@ -1,86 +1,57 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import * as sass from "sass";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { printBundleWasTranspiled } from "./print-utils.js";
|
|
4
|
+
import { BASE_BUNDLE, BASE_GLOBANT_BUNDLE, BASE_GLOBANT_CSS_FILE, CSS_BUNDLES_OUT_DIR, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, SCSS_BUNDLES_INPUT_DIR, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
|
|
5
|
+
import { replacePlaceholdersInBundle, sanitizeBundleName } from "./utils.js";
|
|
7
6
|
const transpileBundle = (filePath, globant) => sass.compile(filePath, {
|
|
8
7
|
loadPaths: [globant ? "src/config/globant" : "src/config/default"],
|
|
9
8
|
style: "compressed"
|
|
10
9
|
}).css;
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const BUNDLES = [];
|
|
14
|
-
const addBaseGlobantFile = (fileMetadata, cssOutDir, jsOutDir) => {
|
|
10
|
+
let BUNDLES = [];
|
|
11
|
+
const transpileGlobantCssFile = async (fileMetadata, cssOutDir) => {
|
|
15
12
|
const { filePath } = fileMetadata;
|
|
16
13
|
BUNDLES.push({
|
|
17
14
|
fileDir: fileMetadata.dir
|
|
18
15
|
.replace(SCSS_BUNDLES_OUT_DIR, "")
|
|
19
|
-
.replace("\\", "/")
|
|
20
|
-
bundleNameWithBackSlash: filePath
|
|
21
|
-
.replace(SCSS_BUNDLES_OUT_DIR, "")
|
|
22
|
-
.replace(BASE_SCSS_FILE, BASE_GLOBANT_FILE)
|
|
16
|
+
.replace("\\", "/")
|
|
23
17
|
});
|
|
24
18
|
const transpiledBundle = transpileBundle(filePath, true);
|
|
25
19
|
// Store the CSS file with its default values
|
|
26
|
-
fs.
|
|
27
|
-
// Store the CSS file in a JS file with placeholders for the values
|
|
28
|
-
fs.writeFileSync(path.join(jsOutDir, BASE_GLOBANT_JS_FILE), `export const bundle = \`${transpiledBundle}\`;`);
|
|
29
|
-
printBundleWasTranspiled(filePath.replace(BASE_SCSS_FILE, BASE_GLOBANT_SCSS_FILE));
|
|
20
|
+
await fs.writeFile(path.join(cssOutDir, BASE_GLOBANT_CSS_FILE), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
|
|
30
21
|
};
|
|
31
|
-
export const transpileCssBundleWithPlaceholder = (fileMetadata) => {
|
|
32
|
-
const { fileName
|
|
33
|
-
|
|
34
|
-
const
|
|
22
|
+
export const transpileCssBundleWithPlaceholder = async (fileMetadata, args) => {
|
|
23
|
+
const { fileName } = fileMetadata;
|
|
24
|
+
let actualFilePath = fileMetadata.filePath;
|
|
25
|
+
const hasGlobantVariant = args?.globant ?? false;
|
|
26
|
+
const cssOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_INPUT_DIR, CSS_BUNDLES_OUT_DIR);
|
|
35
27
|
const fileNameCssExt = fileName.replace(".scss", ".css");
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
const bundleName = sanitizeBundleName(actualFilePath.replace(SCSS_BUNDLES_INPUT_DIR, "").replace(".scss", ""));
|
|
29
|
+
// There is no need to generate the base-globant.css file, since the base.css
|
|
30
|
+
// file already contains this file
|
|
31
|
+
if (hasGlobantVariant) {
|
|
32
|
+
if (bundleName === BASE_GLOBANT_BUNDLE) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Replace the content of the base bundle with the Globant variant
|
|
36
|
+
if (bundleName === BASE_BUNDLE) {
|
|
37
|
+
actualFilePath = actualFilePath.replace(BASE_BUNDLE, BASE_GLOBANT_BUNDLE);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// The Globant variant is not forced, so we are creating both bundles, the
|
|
41
|
+
// base/base and base/base-globant bundles
|
|
42
|
+
else if (bundleName === BASE_BUNDLE) {
|
|
43
|
+
transpileGlobantCssFile({
|
|
44
|
+
dir: fileMetadata.dir,
|
|
45
|
+
fileName: fileName.replace(BASE_BUNDLE, BASE_GLOBANT_BUNDLE),
|
|
46
|
+
filePath: actualFilePath
|
|
47
|
+
}, cssOutDir);
|
|
48
|
+
}
|
|
40
49
|
BUNDLES.push({
|
|
41
50
|
fileDir: fileMetadata.dir
|
|
42
|
-
.replace(
|
|
43
|
-
.replace("\\", "/")
|
|
44
|
-
bundleNameWithBackSlash
|
|
51
|
+
.replace(SCSS_BUNDLES_INPUT_DIR, "")
|
|
52
|
+
.replace("\\", "/")
|
|
45
53
|
});
|
|
46
|
-
|
|
47
|
-
if (!CSS_CREATED_DIRS.has(cssOutDir)) {
|
|
48
|
-
fs.mkdirSync(cssOutDir, { recursive: true });
|
|
49
|
-
fs.mkdirSync(jsOutDir, { recursive: true });
|
|
50
|
-
CSS_CREATED_DIRS.add(cssOutDir);
|
|
51
|
-
JS_CREATED_DIRS.add(jsOutDir);
|
|
52
|
-
}
|
|
53
|
-
const transpiledBundle = transpileBundle(filePath, false);
|
|
54
|
+
const transpiledBundle = transpileBundle(actualFilePath, hasGlobantVariant);
|
|
54
55
|
// Store the CSS file with its default values
|
|
55
|
-
fs.
|
|
56
|
-
// Store the CSS file in a JS file with placeholders for the values
|
|
57
|
-
fs.writeFileSync(path.join(jsOutDir, fileNameJsExt), `export const bundle = \`${transpiledBundle}\`;`);
|
|
58
|
-
printBundleWasTranspiled(filePath);
|
|
59
|
-
if (bundleNameWithBackSlash.replaceAll("/", "\\") ===
|
|
60
|
-
BASE_BUNDLE_WITH_BACK_SLASH) {
|
|
61
|
-
addBaseGlobantFile(fileMetadata, cssOutDir, jsOutDir);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
const createBundleEntryInMappingFile = (bundleName, fileDir, transpiledBundleRef) => ` {
|
|
65
|
-
${BUNDLE_MAPPING_ENTRIES.BUNDLE_NAME}: "${bundleName}",
|
|
66
|
-
${BUNDLE_MAPPING_ENTRIES.FILE_DIR}: "${fileDir}",
|
|
67
|
-
${BUNDLE_MAPPING_ENTRIES.TRANSPILED_BUNDLE}: ${transpiledBundleRef}
|
|
68
|
-
}`;
|
|
69
|
-
export const createBundleMappingsFile = () => {
|
|
70
|
-
let bundleAssociationImports = "";
|
|
71
|
-
let bundleMappingObjectEntries = "";
|
|
72
|
-
BUNDLES.forEach(bundleMetadata => {
|
|
73
|
-
const bundleName = bundleMetadata.bundleNameWithBackSlash
|
|
74
|
-
.replaceAll("\\", "/")
|
|
75
|
-
.substring(1);
|
|
76
|
-
const transpiledBundleRef = getBundleNameWithoutSpecialChars(bundleName);
|
|
77
|
-
const bundleEntry = createBundleEntryInMappingFile(bundleName, bundleMetadata.fileDir, transpiledBundleRef);
|
|
78
|
-
bundleAssociationImports += `import { bundle as ${transpiledBundleRef} } from "./${bundleName}.js";\n`;
|
|
79
|
-
// Concat entries in the object
|
|
80
|
-
bundleMappingObjectEntries +=
|
|
81
|
-
bundleMappingObjectEntries === "" ? bundleEntry : ",\n" + bundleEntry;
|
|
82
|
-
});
|
|
83
|
-
bundleMappingObjectEntries = `\nexport const bundleMappings = [\n${bundleMappingObjectEntries}\n];`;
|
|
84
|
-
// Create the JS file that contains all mappings for the bundle
|
|
85
|
-
fs.writeFileSync(path.join(JS_BUNDLES_OUT_DIR, BUNDLE_MAPPING_FILE), bundleAssociationImports + bundleMappingObjectEntries);
|
|
56
|
+
await fs.writeFile(path.join(cssOutDir, fileNameCssExt), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
|
|
86
57
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import type { FileMetadata } from "./types";
|
|
1
2
|
export declare const getFileSize: (fileContent: string) => string;
|
|
2
3
|
export declare const getHash: (fileContent: string) => string;
|
|
3
|
-
export declare const
|
|
4
|
+
export declare const getFileNameWithHash: <B extends string, H extends string>(bundleName: B, hash: H) => `${B}-${H}`;
|
|
4
5
|
export declare const replacePlaceholdersInBundle: (transpiledBundle: string, fontFaceValue: string, iconsValue: string) => string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
export declare const measureTime: (callback: (() => void) | (() => Promise<void>)) => Promise<void>;
|
|
7
|
+
export declare const sanitizeBundleName: (bundleName: string) => string;
|
|
8
|
+
export declare const getBundleFolder: (fileMetadata: FileMetadata) => string;
|
|
9
|
+
export declare const getBundleFolderAndFileBaseDir: (fileMetadata: FileMetadata, outDir: string) => {
|
|
10
|
+
bundleFolder: string;
|
|
11
|
+
fileBaseDirToWrite: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const getFileNameWithoutExt: (fileMetadata: FileMetadata) => string;
|
|
14
|
+
export declare const getBundleName: (fileMetadata: FileMetadata) => string;
|
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { styleText } from "node:util";
|
|
3
|
-
import { FONT_FACE_PATH_PLACEHOLDER, ICONS_PATH_PLACEHOLDER, KB
|
|
3
|
+
import { CSS_BUNDLES_OUT_DIR, FONT_FACE_PATH_PLACEHOLDER, HASH_LENGTH, ICONS_PATH_PLACEHOLDER, KB
|
|
4
|
+
// SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX
|
|
5
|
+
} from "./constants.js";
|
|
6
|
+
import path from "node:path";
|
|
4
7
|
export const getFileSize = (fileContent) => {
|
|
5
8
|
const fileLength = fileContent.length;
|
|
6
9
|
if (fileLength < KB) {
|
|
7
|
-
return fileLength + "
|
|
10
|
+
return fileLength + " bytes";
|
|
8
11
|
}
|
|
9
12
|
const fileLengthInKB = fileLength / KB;
|
|
10
13
|
if (fileLengthInKB < KB) {
|
|
11
|
-
return fileLengthInKB + "
|
|
14
|
+
return fileLengthInKB.toFixed(2) + " kB";
|
|
12
15
|
}
|
|
13
16
|
const fileLengthInMB = fileLengthInKB / KB;
|
|
14
17
|
if (fileLengthInMB < KB) {
|
|
15
|
-
return fileLengthInMB.toFixed(
|
|
18
|
+
return fileLengthInMB.toFixed(2) + " MB";
|
|
16
19
|
}
|
|
17
20
|
const fileLengthInGB = fileLengthInMB / KB;
|
|
18
|
-
return fileLengthInGB.toFixed(
|
|
21
|
+
return fileLengthInGB.toFixed(2) + " GB";
|
|
19
22
|
};
|
|
20
|
-
export const getHash = (fileContent) => crypto
|
|
21
|
-
|
|
23
|
+
export const getHash = (fileContent) => crypto
|
|
24
|
+
.createHash("md5")
|
|
25
|
+
.update(fileContent)
|
|
26
|
+
.digest("hex")
|
|
27
|
+
.substring(HASH_LENGTH);
|
|
28
|
+
export const getFileNameWithHash = (bundleName, hash) => `${bundleName}-${hash}`;
|
|
22
29
|
export const replacePlaceholdersInBundle = (transpiledBundle, fontFaceValue, iconsValue) => transpiledBundle
|
|
23
30
|
.replaceAll(ICONS_PATH_PLACEHOLDER, iconsValue)
|
|
24
31
|
.replaceAll(FONT_FACE_PATH_PLACEHOLDER, fontFaceValue);
|
|
25
|
-
|
|
26
|
-
* @example
|
|
27
|
-
* "base/icons" --> "baseIcons"
|
|
28
|
-
* "utils/form--full" --> "utilsFormFull"
|
|
29
|
-
*/
|
|
30
|
-
export const getBundleNameWithoutSpecialChars = (bundleName) => {
|
|
31
|
-
const bundleNameNoSpecialChars = bundleName
|
|
32
|
-
.split(SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX)
|
|
33
|
-
.map(subPath => subPath.charAt(0).toUpperCase() + subPath.slice(1))
|
|
34
|
-
.join("");
|
|
35
|
-
return (bundleNameNoSpecialChars.charAt(0).toLowerCase() +
|
|
36
|
-
bundleNameNoSpecialChars.slice(1));
|
|
37
|
-
};
|
|
38
|
-
export const measureTime = (callback) => {
|
|
32
|
+
export const measureTime = async (callback) => {
|
|
39
33
|
console.time(styleText("green", "Done in"));
|
|
40
|
-
callback();
|
|
34
|
+
await callback();
|
|
41
35
|
console.timeEnd(styleText("green", "Done in"));
|
|
42
36
|
};
|
|
37
|
+
export const sanitizeBundleName = (bundleName) => bundleName.replaceAll("\\", "/").replace(/^\//, "");
|
|
38
|
+
export const getBundleFolder = (fileMetadata) => fileMetadata.dir.split(CSS_BUNDLES_OUT_DIR)[1];
|
|
39
|
+
export const getBundleFolderAndFileBaseDir = (fileMetadata, outDir) => {
|
|
40
|
+
const bundleFolder = getBundleFolder(fileMetadata);
|
|
41
|
+
return {
|
|
42
|
+
bundleFolder,
|
|
43
|
+
fileBaseDirToWrite: path.join(outDir, bundleFolder)
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export const getFileNameWithoutExt = (fileMetadata) => fileMetadata.fileName.replace(/.css$/, "");
|
|
47
|
+
export const getBundleName = (fileMetadata) => sanitizeBundleName(`${getBundleFolder(fileMetadata)}/${getFileNameWithoutExt(fileMetadata)}`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, DEFAULT_OUT_DIR_PATH, SEPARATE_BY_COMMA_REGEX } from "./constants.js";
|
|
2
2
|
import { printArgumentDoesNotExistsError, printDuplicatedArgumentError, printInvalidArgumentError, printMissingFontPathArgumentWarning, printMissingIconsPathArgumentWarning, printMissingOutDirPathArgumentWarning } from "./print-utils.js";
|
|
3
|
+
import { sanitizeBundleName } from "./utils.js";
|
|
3
4
|
const ARGUMENT_VALUE_AND_NAME_SEPARATOR_REGEX = /\s*=\s*/g;
|
|
4
5
|
const ERROR_IN_CHECK = false;
|
|
5
6
|
const SUCCESS_CHECK = true;
|
|
@@ -40,6 +41,9 @@ const checkArgument = (argument) => {
|
|
|
40
41
|
}
|
|
41
42
|
const argNameWithValue = argument.split(ARGUMENT_VALUE_AND_NAME_SEPARATOR_REGEX);
|
|
42
43
|
if (argNameWithValue.length !== 2) {
|
|
44
|
+
if (argNameWithValue[0] === "--watch") {
|
|
45
|
+
return SUCCESS_CHECK;
|
|
46
|
+
}
|
|
43
47
|
printInvalidArgumentError(argument);
|
|
44
48
|
return ERROR_IN_CHECK;
|
|
45
49
|
}
|
|
@@ -109,8 +113,10 @@ export const getArguments = () => {
|
|
|
109
113
|
if (anyWarning) {
|
|
110
114
|
console.log("");
|
|
111
115
|
}
|
|
116
|
+
// Sanitize bundle names to avoid issues with "/" and "\" in paths
|
|
117
|
+
const sanitizedAvoidHash = new Set(avoidHash.map(bundleName => sanitizeBundleName(bundleName)));
|
|
112
118
|
return {
|
|
113
|
-
avoidHash: new Set(
|
|
119
|
+
avoidHash: new Set(sanitizedAvoidHash),
|
|
114
120
|
globant: hasGlobant,
|
|
115
121
|
fontFacePath,
|
|
116
122
|
iconsPath,
|