@genexus/mercury 0.12.9 → 0.13.1

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.
Files changed (102) hide show
  1. package/dist/bundles/css/all.css +1 -1
  2. package/dist/bundles/css/base/base.css +1 -1
  3. package/dist/bundles/css/base/icons.css +1 -1
  4. package/dist/bundles/css/chameleon/scrollbar.css +1 -1
  5. package/dist/bundles/css/components/accordion.css +1 -1
  6. package/dist/bundles/css/components/button.css +1 -1
  7. package/dist/bundles/css/components/chat.css +1 -1
  8. package/dist/bundles/css/components/checkbox.css +1 -1
  9. package/dist/bundles/css/components/code.css +1 -1
  10. package/dist/bundles/css/components/combo-box.css +1 -1
  11. package/dist/bundles/css/components/dialog.css +1 -1
  12. package/dist/bundles/css/components/dropdown.css +1 -1
  13. package/dist/bundles/css/components/edit.css +1 -1
  14. package/dist/bundles/css/components/flexible-layout.css +1 -1
  15. package/dist/bundles/css/components/icon.css +1 -1
  16. package/dist/bundles/css/components/layout-splitter.css +1 -1
  17. package/dist/bundles/css/components/list-box.css +1 -1
  18. package/dist/bundles/css/components/markdown-viewer.css +1 -1
  19. package/dist/bundles/css/components/navigation-list.css +1 -1
  20. package/dist/bundles/css/components/pills.css +1 -1
  21. package/dist/bundles/css/components/radio-group.css +1 -1
  22. package/dist/bundles/css/components/segmented-control.css +1 -1
  23. package/dist/bundles/css/components/sidebar.css +1 -1
  24. package/dist/bundles/css/components/slider.css +1 -1
  25. package/dist/bundles/css/components/switch.css +1 -1
  26. package/dist/bundles/css/components/tab.css +1 -1
  27. package/dist/bundles/css/components/tabular-grid.css +1 -1
  28. package/dist/bundles/css/components/ticket-list.css +1 -1
  29. package/dist/bundles/css/components/tooltip.css +1 -1
  30. package/dist/bundles/css/components/tree-view.css +1 -1
  31. package/dist/bundles/css/components/widget.css +1 -1
  32. package/dist/bundles/css/resets/box-sizing.css +1 -1
  33. package/dist/bundles/css/utils/elevation.css +1 -1
  34. package/dist/bundles/css/utils/form--full.css +1 -1
  35. package/dist/bundles/css/utils/form.css +1 -1
  36. package/dist/bundles/css/utils/layout.css +1 -1
  37. package/dist/bundles/css/utils/spacing.css +1 -1
  38. package/dist/bundles/css/utils/typography.css +1 -1
  39. package/dist/bundles/js/all.js +1 -0
  40. package/dist/bundles/js/base/base.js +1 -0
  41. package/dist/bundles/js/base/icons.js +1 -0
  42. package/dist/bundles/js/bundle-mappings.js +231 -0
  43. package/dist/bundles/js/chameleon/scrollbar.js +1 -0
  44. package/dist/bundles/js/components/accordion.js +1 -0
  45. package/dist/bundles/js/components/button.js +1 -0
  46. package/dist/bundles/js/components/chat.js +1 -0
  47. package/dist/bundles/js/components/checkbox.js +1 -0
  48. package/dist/bundles/js/components/code.js +1 -0
  49. package/dist/bundles/js/components/combo-box.js +1 -0
  50. package/dist/bundles/js/components/dialog.js +1 -0
  51. package/dist/bundles/js/components/dropdown.js +1 -0
  52. package/dist/bundles/js/components/edit.js +1 -0
  53. package/dist/bundles/js/components/flexible-layout.js +1 -0
  54. package/dist/bundles/js/components/icon.js +1 -0
  55. package/dist/bundles/js/components/layout-splitter.js +1 -0
  56. package/dist/bundles/js/components/list-box.js +1 -0
  57. package/dist/bundles/js/components/markdown-viewer.js +1 -0
  58. package/dist/bundles/js/components/navigation-list.js +1 -0
  59. package/dist/bundles/js/components/pills.js +1 -0
  60. package/dist/bundles/js/components/radio-group.js +1 -0
  61. package/dist/bundles/js/components/segmented-control.js +1 -0
  62. package/dist/bundles/js/components/sidebar.js +1 -0
  63. package/dist/bundles/js/components/slider.js +1 -0
  64. package/dist/bundles/js/components/switch.js +1 -0
  65. package/dist/bundles/js/components/tab.js +1 -0
  66. package/dist/bundles/js/components/tabular-grid.js +1 -0
  67. package/dist/bundles/js/components/ticket-list.js +1 -0
  68. package/dist/bundles/js/components/tooltip.js +1 -0
  69. package/dist/bundles/js/components/tree-view.js +1 -0
  70. package/dist/bundles/js/components/widget.js +1 -0
  71. package/dist/bundles/js/resets/box-sizing.js +1 -0
  72. package/dist/bundles/js/utils/elevation.js +1 -0
  73. package/dist/bundles/js/utils/form--full.js +1 -0
  74. package/dist/bundles/js/utils/form.js +1 -0
  75. package/dist/bundles/js/utils/layout.js +1 -0
  76. package/dist/bundles/js/utils/spacing.js +1 -0
  77. package/dist/bundles/js/utils/typography.js +1 -0
  78. package/dist/bundles.d.ts +153 -146
  79. package/dist/bundles.js +1 -1
  80. package/dist/cli/bundle.d.ts +2 -0
  81. package/dist/cli/bundle.js +20 -0
  82. package/dist/cli/internal/constants.d.ts +28 -0
  83. package/dist/cli/internal/constants.js +33 -0
  84. package/dist/cli/internal/create-bundles-with-custom-paths.d.ts +2 -0
  85. package/dist/cli/internal/create-bundles-with-custom-paths.js +67 -0
  86. package/dist/cli/internal/file-management.d.ts +4 -0
  87. package/dist/cli/internal/file-management.js +20 -0
  88. package/dist/cli/internal/print-utils.d.ts +18 -0
  89. package/dist/cli/internal/print-utils.js +33 -0
  90. package/dist/cli/internal/transpile-bundle-and-create-mappings.d.ts +3 -0
  91. package/dist/cli/internal/transpile-bundle-and-create-mappings.js +85 -0
  92. package/dist/cli/internal/types.d.ts +21 -0
  93. package/dist/cli/internal/types.js +1 -0
  94. package/dist/cli/internal/utils.d.ts +11 -0
  95. package/dist/cli/internal/utils.js +42 -0
  96. package/dist/cli/internal/validate-args.d.ts +2 -0
  97. package/dist/cli/internal/validate-args.js +119 -0
  98. package/dist/cli/mercury.d.ts +2 -0
  99. package/dist/cli/mercury.js +14 -0
  100. package/dist/mercury.scss +2 -0
  101. package/dist/types.d.ts +3 -0
  102. package/package.json +13 -3
@@ -0,0 +1,67 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ // @ts-expect-error: This file does exists after the bundle transpilation process
4
+ import { bundleMappings } from "../../bundles/js/bundle-mappings.js";
5
+ import { BASE_BUNDLE, BASE_GLOBANT_BUNDLE, BUNDLE_MAPPING_TO_HASH_FILE } from "./constants.js";
6
+ import { getBundleNameWithHash, getHash, replacePlaceholdersInBundle } from "./utils.js";
7
+ import { printBundleToHashMappingsWasCreated, printBundleWasCreated } from "./print-utils.js";
8
+ const findLargestPath = () => {
9
+ let largestBundleLength = 0;
10
+ bundleMappings.forEach(entry => {
11
+ largestBundleLength = Math.max(largestBundleLength, entry.bundleName.length);
12
+ });
13
+ return largestBundleLength;
14
+ };
15
+ const getActualBundleName = (bundleName) => bundleName === BASE_BUNDLE || bundleName === BASE_GLOBANT_BUNDLE
16
+ ? BASE_BUNDLE
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;
22
+ const outDir = path.join(args.outDirPath);
23
+ const CREATED_DIRS = new Set();
24
+ const largestBundleLength = findLargestPath();
25
+ let bundleMappingToHashObjectEntries = "";
26
+ bundleMappings.forEach(entry => {
27
+ const { bundleName, fileDir, transpiledBundle } = entry;
28
+ if (shouldSkipBundleCreation(bundleName, globant)) {
29
+ return;
30
+ }
31
+ const actualBundleName = getActualBundleName(bundleName);
32
+ const compiledBundleWithoutPlaceholders = replacePlaceholdersInBundle(transpiledBundle, fontFacePath, iconsPath);
33
+ const hash = getHash(compiledBundleWithoutPlaceholders);
34
+ if (fileDir && !CREATED_DIRS.has(fileDir)) {
35
+ fs.mkdirSync(path.join(outDir, fileDir), { recursive: true });
36
+ CREATED_DIRS.add(fileDir);
37
+ }
38
+ const bundleNameWithHash = avoidHash.has(actualBundleName)
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;
59
+ });
60
+ bundleMappingToHashObjectEntries = `export const bundleToHashMappings = {\n${bundleMappingToHashObjectEntries}\n} as const;\n`;
61
+ const bundleMappingFilePath = path.join(outDir, BUNDLE_MAPPING_TO_HASH_FILE);
62
+ fs.writeFileSync(bundleMappingFilePath, bundleMappingToHashObjectEntries);
63
+ printBundleToHashMappingsWasCreated({
64
+ outDir,
65
+ filePath: bundleMappingFilePath
66
+ });
67
+ };
@@ -0,0 +1,4 @@
1
+ import type { FileMetadata } from "./types";
2
+ export declare const ensureDirectoryExistsAndItsClear: (dirPath: string) => void;
3
+ export declare function walkSync(dir: string): Generator<FileMetadata>;
4
+ export declare const copyDirectories: (srcDir: string, outDir: string) => void;
@@ -0,0 +1,20 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ export const ensureDirectoryExistsAndItsClear = (dirPath) => {
4
+ if (fs.existsSync(dirPath)) {
5
+ fs.rmSync(dirPath, { recursive: true });
6
+ }
7
+ fs.mkdirSync(dirPath, { recursive: true });
8
+ };
9
+ export function* walkSync(dir) {
10
+ const files = fs.readdirSync(dir, { withFileTypes: true });
11
+ for (const file of files) {
12
+ if (file.isDirectory()) {
13
+ yield* walkSync(path.join(dir, file.name));
14
+ }
15
+ else {
16
+ yield { dir, fileName: file.name, filePath: path.join(dir, file.name) };
17
+ }
18
+ }
19
+ }
20
+ export const copyDirectories = (srcDir, outDir) => fs.cpSync(srcDir, outDir, { recursive: true });
@@ -0,0 +1,18 @@
1
+ export declare const printBundleWasCreated: (args: {
2
+ outDir: string;
3
+ bundleName: string;
4
+ largestBundleLength: number;
5
+ filePathToCreateBundle: string;
6
+ compiledBundleWithoutPlaceholders: string;
7
+ }) => void;
8
+ export declare const printBundleToHashMappingsWasCreated: (args: {
9
+ outDir: string;
10
+ filePath: string;
11
+ }) => void;
12
+ export declare const printBundleWasTranspiled: (filePath: string) => void;
13
+ export declare const printArgumentDoesNotExistsError: (arg: string) => void;
14
+ export declare const printDuplicatedArgumentError: (arg: string) => void;
15
+ export declare const printInvalidArgumentError: (arg: string) => void;
16
+ export declare const printMissingFontPathArgumentWarning: () => void;
17
+ export declare const printMissingIconsPathArgumentWarning: () => void;
18
+ export declare const printMissingOutDirPathArgumentWarning: () => void;
@@ -0,0 +1,33 @@
1
+ import { styleText } from "node:util";
2
+ import { getFileSize } from "./utils.js";
3
+ import { DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, DEFAULT_OUT_DIR_PATH, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
4
+ export const printBundleWasCreated = (args) => console.log(styleText("greenBright", " Created: ") +
5
+ styleText("white", args.outDir) +
6
+ styleText("whiteBright", args.filePathToCreateBundle.replace(args.outDir, "")) +
7
+ styleText("cyan", " ".repeat(1 + args.largestBundleLength - args.bundleName.length) +
8
+ getFileSize(args.compiledBundleWithoutPlaceholders)));
9
+ export const printBundleToHashMappingsWasCreated = (args) => console.log("\n" +
10
+ styleText("greenBright", " Created: ") +
11
+ styleText("white", args.outDir) +
12
+ styleText("whiteBright", args.filePath.replace(args.outDir, "")));
13
+ export const printBundleWasTranspiled = (filePath) => console.log(styleText("greenBright", " Transpiled: ") +
14
+ styleText("white", SCSS_BUNDLES_OUT_DIR) +
15
+ styleText("whiteBright", filePath.replace(SCSS_BUNDLES_OUT_DIR, "")));
16
+ export const printArgumentDoesNotExistsError = (arg) => console.log(styleText("red", " error ") +
17
+ styleText("gray", "Argument does not exists: ") +
18
+ `'${arg}'`);
19
+ export const printDuplicatedArgumentError = (arg) => console.log(styleText("red", " error ") +
20
+ styleText("gray", "Duplicated argument type: ") +
21
+ `'${arg}'`);
22
+ export const printInvalidArgumentError = (arg) => console.log(styleText("red", " error ") +
23
+ styleText("gray", "Invalid argument: ") +
24
+ `'${arg}'`);
25
+ export const printMissingFontPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --font-face-path argument. The path ") +
26
+ styleText("cyan", `'${DEFAULT_FONT_FACE_PATH}'`) +
27
+ styleText("yellow", " will be used as default."));
28
+ export const printMissingIconsPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --icons-path argument. The path ") +
29
+ styleText("cyan", `'${DEFAULT_ICONS_PATH}'`) +
30
+ styleText("yellow", " will be used as default."));
31
+ export const printMissingOutDirPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --outDir argument. The path ") +
32
+ styleText("cyan", `'${DEFAULT_OUT_DIR_PATH}'`) +
33
+ styleText("yellow", " will be used as default."));
@@ -0,0 +1,3 @@
1
+ import { FileMetadata } from "./types.js";
2
+ export declare const transpileCssBundleWithPlaceholder: (fileMetadata: FileMetadata) => void;
3
+ export declare const createBundleMappingsFile: () => void;
@@ -0,0 +1,85 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import * as sass from "sass";
4
+ import { BASE_BUNDLE_WITH_BACK_SLASH, BASE_GLOBANT_CSS_FILE, BASE_GLOBANT_FILE, BASE_GLOBANT_JS_FILE, BASE_GLOBANT_SCSS_FILE, BASE_SCSS_FILE, BUNDLE_MAPPING_ENTRIES, BUNDLE_MAPPING_FILE, CSS_BUNDLES_OUT_DIR, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, JS_BUNDLES_OUT_DIR, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
5
+ import { getBundleNameWithoutSpecialChars, replacePlaceholdersInBundle } from "./utils.js";
6
+ import { printBundleWasTranspiled } from "./print-utils.js";
7
+ const transpileBundle = (filePath, globant) => sass.compile(filePath, {
8
+ loadPaths: [globant ? "src/config/globant" : "src/config/default"],
9
+ style: "compressed"
10
+ }).css;
11
+ const CSS_CREATED_DIRS = new Set();
12
+ const JS_CREATED_DIRS = new Set();
13
+ const BUNDLES = [];
14
+ const addBaseGlobantFile = (fileMetadata, cssOutDir, jsOutDir) => {
15
+ const { filePath } = fileMetadata;
16
+ BUNDLES.push({
17
+ fileDir: fileMetadata.dir
18
+ .replace(SCSS_BUNDLES_OUT_DIR, "")
19
+ .replace("\\", "/"),
20
+ bundleNameWithBackSlash: filePath
21
+ .replace(SCSS_BUNDLES_OUT_DIR, "")
22
+ .replace(BASE_SCSS_FILE, BASE_GLOBANT_FILE)
23
+ });
24
+ const transpiledBundle = transpileBundle(filePath, true);
25
+ // Store the CSS file with its default values
26
+ fs.writeFileSync(path.join(cssOutDir, BASE_GLOBANT_CSS_FILE), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
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));
30
+ };
31
+ export const transpileCssBundleWithPlaceholder = (fileMetadata) => {
32
+ const { fileName, filePath } = fileMetadata;
33
+ const cssOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_OUT_DIR, CSS_BUNDLES_OUT_DIR);
34
+ const jsOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_OUT_DIR, JS_BUNDLES_OUT_DIR);
35
+ const fileNameCssExt = fileName.replace(".scss", ".css");
36
+ const fileNameJsExt = fileName.replace(".scss", ".js");
37
+ const bundleNameWithBackSlash = filePath
38
+ .replace(SCSS_BUNDLES_OUT_DIR, "")
39
+ .replace(".scss", "");
40
+ BUNDLES.push({
41
+ fileDir: fileMetadata.dir
42
+ .replace(SCSS_BUNDLES_OUT_DIR, "")
43
+ .replace("\\", "/"),
44
+ bundleNameWithBackSlash
45
+ });
46
+ // Create the file directory if it does not exists
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
+ // Store the CSS file with its default values
55
+ fs.writeFileSync(path.join(cssOutDir, fileNameCssExt), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
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 === BASE_BUNDLE_WITH_BACK_SLASH) {
60
+ addBaseGlobantFile(fileMetadata, cssOutDir, jsOutDir);
61
+ }
62
+ };
63
+ const createBundleEntryInMappingFile = (bundleName, fileDir, transpiledBundleRef) => ` {
64
+ ${BUNDLE_MAPPING_ENTRIES.BUNDLE_NAME}: "${bundleName}",
65
+ ${BUNDLE_MAPPING_ENTRIES.FILE_DIR}: "${fileDir}",
66
+ ${BUNDLE_MAPPING_ENTRIES.TRANSPILED_BUNDLE}: ${transpiledBundleRef}
67
+ }`;
68
+ export const createBundleMappingsFile = () => {
69
+ let bundleAssociationImports = "";
70
+ let bundleMappingObjectEntries = "";
71
+ BUNDLES.forEach(bundleMetadata => {
72
+ const bundleName = bundleMetadata.bundleNameWithBackSlash
73
+ .replaceAll("\\", "/")
74
+ .substring(1);
75
+ const transpiledBundleRef = getBundleNameWithoutSpecialChars(bundleName);
76
+ const bundleEntry = createBundleEntryInMappingFile(bundleName, bundleMetadata.fileDir, transpiledBundleRef);
77
+ bundleAssociationImports += `import { bundle as ${transpiledBundleRef} } from "./${bundleName}.js";\n`;
78
+ // Concat entries in the object
79
+ bundleMappingObjectEntries +=
80
+ bundleMappingObjectEntries === "" ? bundleEntry : ",\n" + bundleEntry;
81
+ });
82
+ bundleMappingObjectEntries = `\nexport const bundleMappings = [\n${bundleMappingObjectEntries}\n];`;
83
+ // Create the JS file that contains all mappings for the bundle
84
+ fs.writeFileSync(path.join(JS_BUNDLES_OUT_DIR, BUNDLE_MAPPING_FILE), bundleAssociationImports + bundleMappingObjectEntries);
85
+ };
@@ -0,0 +1,21 @@
1
+ export type BundleMetadata = {
2
+ fileDir: string;
3
+ bundleNameWithBackSlash: string;
4
+ };
5
+ export type BundleAssociationMetadata = {
6
+ bundleName: string;
7
+ fileDir: string;
8
+ transpiledBundle: string;
9
+ };
10
+ export type FileMetadata = {
11
+ dir: string;
12
+ fileName: string;
13
+ filePath: string;
14
+ };
15
+ export type CLIArguments = {
16
+ avoidHash: Set<string>;
17
+ globant: boolean;
18
+ iconsPath: string;
19
+ fontFacePath: string;
20
+ outDirPath: string;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export declare const getFileSize: (fileContent: string) => string;
2
+ export declare const getHash: (fileContent: string) => string;
3
+ export declare const getBundleNameWithHash: <B extends string, H extends string>(bundleName: B, hash: H) => `${B}-${H}`;
4
+ export declare const replacePlaceholdersInBundle: (transpiledBundle: string, fontFaceValue: string, iconsValue: string) => string;
5
+ /**
6
+ * @example
7
+ * "base/icons" --> "baseIcons"
8
+ * "utils/form--full" --> "utilsFormFull"
9
+ */
10
+ export declare const getBundleNameWithoutSpecialChars: (bundleName: string) => string;
11
+ export declare const measureTime: (callback: () => void) => void;
@@ -0,0 +1,42 @@
1
+ import crypto from "node:crypto";
2
+ import { styleText } from "node:util";
3
+ import { FONT_FACE_PATH_PLACEHOLDER, ICONS_PATH_PLACEHOLDER, KB, SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX } from "./constants.js";
4
+ export const getFileSize = (fileContent) => {
5
+ const fileLength = fileContent.length;
6
+ if (fileLength < KB) {
7
+ return fileLength + "B";
8
+ }
9
+ const fileLengthInKB = fileLength / KB;
10
+ if (fileLengthInKB < KB) {
11
+ return fileLengthInKB + "KB";
12
+ }
13
+ const fileLengthInMB = fileLengthInKB / KB;
14
+ if (fileLengthInMB < KB) {
15
+ return fileLengthInMB.toFixed(3) + "MB";
16
+ }
17
+ const fileLengthInGB = fileLengthInMB / KB;
18
+ return fileLengthInGB.toFixed(3) + "GB";
19
+ };
20
+ export const getHash = (fileContent) => crypto.createHash("md5").update(fileContent).digest("hex").substring(16);
21
+ export const getBundleNameWithHash = (bundleName, hash) => `${bundleName}-${hash}`;
22
+ export const replacePlaceholdersInBundle = (transpiledBundle, fontFaceValue, iconsValue) => transpiledBundle
23
+ .replaceAll(ICONS_PATH_PLACEHOLDER, iconsValue)
24
+ .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) => {
39
+ console.time(styleText("green", "Done in"));
40
+ callback();
41
+ console.timeEnd(styleText("green", "Done in"));
42
+ };
@@ -0,0 +1,2 @@
1
+ import type { CLIArguments } from "./types";
2
+ export declare const getArguments: () => CLIArguments | undefined;
@@ -0,0 +1,119 @@
1
+ import { DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, DEFAULT_OUT_DIR_PATH, SEPARATE_BY_COMMA_REGEX } from "./constants.js";
2
+ import { printArgumentDoesNotExistsError, printDuplicatedArgumentError, printInvalidArgumentError, printMissingFontPathArgumentWarning, printMissingIconsPathArgumentWarning, printMissingOutDirPathArgumentWarning } from "./print-utils.js";
3
+ const ARGUMENT_VALUE_AND_NAME_SEPARATOR_REGEX = /\s*=\s*/g;
4
+ const ERROR_IN_CHECK = false;
5
+ const SUCCESS_CHECK = true;
6
+ const [, , ...args] = process.argv;
7
+ const AVOID_HASH_ARGUMENTS = new Set(["--avoid-hash", "--ah", "-ah"]);
8
+ const ICONS_PATH_ARGUMENTS = new Set(["--icons-path", "--icons", "--i", "-i"]);
9
+ const FONT_FACE_PATH_ARGUMENTS = new Set([
10
+ "--font-face-path",
11
+ "--font-face",
12
+ "--f",
13
+ "-f"
14
+ ]);
15
+ const OUT_DIR_ARGUMENTS = new Set(["--outdir", "--o", "-o"]);
16
+ const GLOBANT_ARGUMENTS = new Set(["--globant", "--gl", "-gl"]);
17
+ const isAvoidHashArgument = (arg) => AVOID_HASH_ARGUMENTS.has(arg.toLowerCase());
18
+ const isFontFaceArgument = (arg) => FONT_FACE_PATH_ARGUMENTS.has(arg.toLowerCase());
19
+ const isGlobantArgument = (arg) => GLOBANT_ARGUMENTS.has(arg.toLowerCase());
20
+ const isIconsArgument = (arg) => ICONS_PATH_ARGUMENTS.has(arg.toLowerCase());
21
+ const isOutDirArgument = (arg) => OUT_DIR_ARGUMENTS.has(arg.toLowerCase());
22
+ let hasAvoidHash = false;
23
+ let hasGlobant = false;
24
+ let hasFontFacePath = false;
25
+ let hasIconsPath = false;
26
+ let hasOutDirPath = false;
27
+ let anyWarning = false;
28
+ let avoidHash = [];
29
+ let fontFacePath = "";
30
+ let iconsPath = "";
31
+ let outDirPath = "";
32
+ const checkArgument = (argument) => {
33
+ if (isGlobantArgument(argument)) {
34
+ if (hasGlobant) {
35
+ printDuplicatedArgumentError(argument);
36
+ return ERROR_IN_CHECK;
37
+ }
38
+ hasGlobant = true;
39
+ return SUCCESS_CHECK;
40
+ }
41
+ const argNameWithValue = argument.split(ARGUMENT_VALUE_AND_NAME_SEPARATOR_REGEX);
42
+ if (argNameWithValue.length !== 2) {
43
+ printInvalidArgumentError(argument);
44
+ return ERROR_IN_CHECK;
45
+ }
46
+ const argName = argNameWithValue[0];
47
+ const argValue = argNameWithValue[1];
48
+ if (isAvoidHashArgument(argName)) {
49
+ if (hasAvoidHash) {
50
+ printDuplicatedArgumentError(argument);
51
+ return ERROR_IN_CHECK;
52
+ }
53
+ avoidHash = argValue.split(SEPARATE_BY_COMMA_REGEX);
54
+ hasAvoidHash = true;
55
+ return SUCCESS_CHECK;
56
+ }
57
+ if (isFontFaceArgument(argName)) {
58
+ if (hasFontFacePath) {
59
+ printDuplicatedArgumentError(argument);
60
+ return ERROR_IN_CHECK;
61
+ }
62
+ fontFacePath = argValue;
63
+ hasFontFacePath = true;
64
+ return SUCCESS_CHECK;
65
+ }
66
+ if (isIconsArgument(argName)) {
67
+ if (hasIconsPath) {
68
+ printDuplicatedArgumentError(argument);
69
+ return ERROR_IN_CHECK;
70
+ }
71
+ iconsPath = argValue;
72
+ hasIconsPath = true;
73
+ return SUCCESS_CHECK;
74
+ }
75
+ if (isOutDirArgument(argName)) {
76
+ if (hasOutDirPath) {
77
+ printDuplicatedArgumentError(argument);
78
+ return ERROR_IN_CHECK;
79
+ }
80
+ outDirPath = argValue;
81
+ hasOutDirPath = true;
82
+ return SUCCESS_CHECK;
83
+ }
84
+ printArgumentDoesNotExistsError(argument);
85
+ return ERROR_IN_CHECK;
86
+ };
87
+ export const getArguments = () => {
88
+ for (let index = 0; index < args.length; index++) {
89
+ if (checkArgument(args[index]) === ERROR_IN_CHECK) {
90
+ return undefined;
91
+ }
92
+ }
93
+ if (!fontFacePath) {
94
+ printMissingFontPathArgumentWarning();
95
+ fontFacePath = DEFAULT_FONT_FACE_PATH;
96
+ anyWarning = true;
97
+ }
98
+ if (!iconsPath) {
99
+ printMissingIconsPathArgumentWarning();
100
+ iconsPath = DEFAULT_ICONS_PATH;
101
+ anyWarning = true;
102
+ }
103
+ if (!outDirPath) {
104
+ printMissingOutDirPathArgumentWarning();
105
+ outDirPath = DEFAULT_OUT_DIR_PATH;
106
+ anyWarning = true;
107
+ }
108
+ // Print a line break to better visualize warnings
109
+ if (anyWarning) {
110
+ console.log("");
111
+ }
112
+ return {
113
+ avoidHash: new Set(avoidHash),
114
+ globant: hasGlobant,
115
+ fontFacePath,
116
+ iconsPath,
117
+ outDirPath
118
+ };
119
+ };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { createBundlesWithCustomPaths } from "./internal/create-bundles-with-custom-paths.js";
3
+ import { ensureDirectoryExistsAndItsClear } from "./internal/file-management.js";
4
+ import { getArguments } from "./internal/validate-args.js";
5
+ import { measureTime } from "./internal/utils.js";
6
+ measureTime(() => {
7
+ // Improve process visualization
8
+ console.log("");
9
+ const args = getArguments();
10
+ if (args) {
11
+ ensureDirectoryExistsAndItsClear(args.outDirPath);
12
+ createBundlesWithCustomPaths(args);
13
+ }
14
+ });
package/dist/mercury.scss CHANGED
@@ -4309,6 +4309,8 @@
4309
4309
  --code__border: var(--mer-border__width--sm) solid
4310
4310
  var(--mer-surface__elevation--03);
4311
4311
  --code__border-radius: var(--mer-border__radius--sm);
4312
+
4313
+ // TODO: Fix this. It MUST be two separated properties (padding-block and padding-inline)
4312
4314
  --code__padding: var(--mer-spacing--xs) var(--mer-spacing--sm);
4313
4315
 
4314
4316
  --ch-code__doctag: var(--code__color-blue);
package/dist/types.d.ts CHANGED
@@ -7,6 +7,9 @@ export type MercuryBundleComponentForm = "components/button" | "components/check
7
7
  export type MercuryBundleReset = "resets/box-sizing";
8
8
  export type MercuryBundleUtil = "utils/elevation" | "utils/form" | "utils/layout" | "utils/spacing" | "utils/typography" | "chameleon/scrollbar";
9
9
  export type MercuryBundleUtilFormFull = "utils/form--full";
10
+ export type MercuryBundleMapping = {
11
+ [key in MercuryBundleComponent | MercuryBundleComponentForm | MercuryBundleReset | MercuryBundleUtil | MercuryBundleUtilFormFull]: `${key}-${string}` | key;
12
+ };
10
13
  export type AssetsMetadata = {
11
14
  category: string;
12
15
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genexus/mercury",
3
- "version": "0.12.9",
3
+ "version": "0.13.1",
4
4
  "description": "Mercury is the design system designed for GeneXus IDE Web and GeneXus Next",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -9,6 +9,9 @@
9
9
  "dist/"
10
10
  ],
11
11
  "type": "module",
12
+ "bin": {
13
+ "mercury": "./dist/cli/mercury.js"
14
+ },
12
15
  "exports": {
13
16
  ".": {
14
17
  "import": {
@@ -16,6 +19,12 @@
16
19
  "default": "./dist/index.js"
17
20
  }
18
21
  },
22
+ "./MERCURY_ASSETS.js": {
23
+ "import": {
24
+ "types": "./dist/assets/MERCURY_ASSETS.d.ts",
25
+ "default": "./dist/assets/MERCURY_ASSETS.js"
26
+ }
27
+ },
19
28
  "./assets-manager.js": {
20
29
  "import": {
21
30
  "types": "./dist/assets-manager.d.ts",
@@ -40,8 +49,8 @@
40
49
  "build": "npm run build.js && npm run icons-svg && npm run icons-sass && npm run build.scss && npm run copy-tasks && npm run showcase.scss",
41
50
  "build.js": "tsc && esbuild dist/*.js --allow-overwrite --minify --outdir=dist && esbuild dist/assets/*.js --allow-overwrite --minify --outdir=dist/assets",
42
51
  "build-no-svg": "npm run build.js && npm run build.scss && npm run copy-tasks",
43
- "build.scss": "scss-bundle -e ./src/mercury.scss -o dist/mercury.scss && npm run build.bundles && npm run copy-all.css",
44
- "build.bundles": "fse copy --all --keepExisting --errorOnExist --dereference --preserveTimestamps --quiet src/bundles/scss dist/bundles/scss && sass --load-path=src --no-source-map --style compressed dist/bundles/scss:dist/bundles/css",
52
+ "build.scss": "scss-bundle -e ./src/mercury.scss -o dist/mercury.scss && npm run build.bundles",
53
+ "build.bundles": "node dist/cli/bundle.js",
45
54
  "start": "vite --port 5200 --open showcase/button.html",
46
55
  "validate.ci": "npm run build-no-svg",
47
56
  "icons-svg": "ssg-svg --srcDir=src/icons/svg-source --outDir=src/assets/icons/_generated/ --configFilePath=src/icons/svg-source/.config/color-states.json --showcaseDir=showcase/icons/ --showcaseBaseHref=../assets/icons/ --logDir=./log --objectFilePath=src/assets/MERCURY_ASSETS.ts --defaultColorType=on-surface",
@@ -57,6 +66,7 @@
57
66
  "@atao60/fse-cli": "^0.1.9",
58
67
  "@genexus/chameleon-controls-library": "6.0.0-next.55",
59
68
  "@genexus/svg-sass-generator": "1.1.24",
69
+ "@types/node": "~22.10.5",
60
70
  "chokidar": "^3.6.0",
61
71
  "chokidar-cli": "^3.0.0",
62
72
  "esbuild": "0.24.0",