@wavemaker/react-codegen 11.14.1-rc.240 → 11.14.2-rc.6311

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 (73) hide show
  1. package/build-react-web.js +8 -3
  2. package/build-react-web.js.map +1 -1
  3. package/command.js +1 -1
  4. package/command.js.map +1 -1
  5. package/index.js +2 -0
  6. package/index.js.map +1 -1
  7. package/package-lock.json +13 -13
  8. package/package.json +1 -1
  9. package/src/app.generator.js +16 -7
  10. package/src/app.generator.js.map +1 -1
  11. package/src/download-packages.js +193 -0
  12. package/src/download-packages.js.map +1 -0
  13. package/src/gen-app-override-css.js +316 -245
  14. package/src/gen-app-override-css.js.map +1 -1
  15. package/src/genappoverridecssold-file.js +311 -0
  16. package/src/genappoverridecssold-file.js.map +1 -0
  17. package/src/handlebar-helpers.js +186 -0
  18. package/src/handlebar-helpers.js.map +1 -1
  19. package/src/transpile/bind.ex.transformer.js +30 -0
  20. package/src/transpile/bind.ex.transformer.js.map +1 -1
  21. package/src/transpile/components/container/panel.transformer.js +0 -1
  22. package/src/transpile/components/container/panel.transformer.js.map +1 -1
  23. package/src/transpile/components/container/wizardaction.transformer.js +34 -19
  24. package/src/transpile/components/container/wizardaction.transformer.js.map +1 -1
  25. package/src/transpile/components/container/wizardstep.transformer.js +62 -5
  26. package/src/transpile/components/container/wizardstep.transformer.js.map +1 -1
  27. package/src/transpile/components/data/form/form-field.transformer.js +27 -1
  28. package/src/transpile/components/data/form/form-field.transformer.js.map +1 -1
  29. package/src/transpile/components/data/list/list-transformer.js +29 -2
  30. package/src/transpile/components/data/list/list-transformer.js.map +1 -1
  31. package/src/transpile/components/data/live-filter-field.transformer.js +13 -1
  32. package/src/transpile/components/data/live-filter-field.transformer.js.map +1 -1
  33. package/src/transpile/components/data/liveform.transformer.js +15 -4
  34. package/src/transpile/components/data/liveform.transformer.js.map +1 -1
  35. package/src/transpile/components/data/table/table-column.transformer.js +40 -3
  36. package/src/transpile/components/data/table/table-column.transformer.js.map +1 -1
  37. package/src/transpile/components/data/table/table-row-action.transformer.js +1 -1
  38. package/src/transpile/components/dialogs/dialog-actions.transformer.js +19 -0
  39. package/src/transpile/components/dialogs/dialog-actions.transformer.js.map +1 -1
  40. package/src/transpile/components/dialogs/dialog.transformer.js +0 -11
  41. package/src/transpile/components/dialogs/dialog.transformer.js.map +1 -1
  42. package/src/transpile/components/input/checkbox-set.transformer.js +1 -1
  43. package/src/transpile/components/input/checkbox-set.transformer.js.map +1 -1
  44. package/src/transpile/components/input/checkbox.transformer.js +29 -1
  45. package/src/transpile/components/input/checkbox.transformer.js.map +1 -1
  46. package/src/transpile/components/input/currency.transformer.js +1 -1
  47. package/src/transpile/components/input/currency.transformer.js.map +1 -1
  48. package/src/transpile/components/input/radio-set.transformer.js +1 -1
  49. package/src/transpile/components/input/radio-set.transformer.js.map +1 -1
  50. package/src/transpile/components/input/switch.transformer.js.map +1 -1
  51. package/src/transpile/components/nav/nav.transformer.js +33 -1
  52. package/src/transpile/components/nav/nav.transformer.js.map +1 -1
  53. package/src/transpile/components/navigation/menu.transformer.js.map +1 -1
  54. package/src/transpile/components/navigation/popover.transformer.js +1 -1
  55. package/src/transpile/components/navigation/popover.transformer.js.map +1 -1
  56. package/src/transpile/components/utils.js +19 -6
  57. package/src/transpile/components/utils.js.map +1 -1
  58. package/src/transpile/style/dimension-style.parser.js +13 -2
  59. package/src/transpile/style/dimension-style.parser.js.map +1 -1
  60. package/src/transpile/style/style.parser.js +1 -1
  61. package/src/transpile/style/style.parser.js.map +1 -1
  62. package/src/transpile/style.transformer.js +1 -1
  63. package/src/transpile/style.transformer.js.map +1 -1
  64. package/src/transpile/transpile.js +42 -20
  65. package/src/transpile/transpile.js.map +1 -1
  66. package/src/utils.js +6 -2
  67. package/src/utils.js.map +1 -1
  68. package/src/variables/variable.transformer.js +165 -7
  69. package/src/variables/variable.transformer.js.map +1 -1
  70. package/templates/component/component.hbs +0 -10
  71. package/templates/component/partial.hbs +0 -3
  72. package/templates/project/app/components.css +5 -0
  73. package/templates/project/package.json +3 -3
@@ -33,276 +33,347 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.OVERRIDE_TOKENS_PATH = exports.APP_OVERRIDE_CSS_PATH = exports.DESIGN_TOKENS_DIR_NAME = void 0;
37
- exports.generateOverrideCSS = generateOverrideCSS;
38
- const fs = __importStar(require("fs"));
36
+ exports.generateOverrideCSS = void 0;
39
37
  const path = __importStar(require("path"));
40
- const project_service_1 = require("./project.service");
38
+ const fs = __importStar(require("fs"));
39
+ const url_1 = require("url");
40
+ const download_packages_1 = require("./download-packages");
41
41
  const utils_1 = require("./utils");
42
- // Constants
43
- exports.DESIGN_TOKENS_DIR_NAME = "design-tokens";
44
- exports.APP_OVERRIDE_CSS_PATH = `${exports.DESIGN_TOKENS_DIR_NAME}/app.override.css`;
45
- exports.OVERRIDE_TOKENS_PATH = `${exports.DESIGN_TOKENS_DIR_NAME}/overrides`;
46
- /**
47
- * Install a package if it's not already installed
48
- * @param projectRoot project root directory
49
- * @param packageName name of the package to install
50
- * @param version version of the package
51
- */
52
- async function installPackageIfNeeded(projectRoot, packageName, version) {
53
- const packagePath = path.join(projectRoot, "node_modules", packageName);
54
- if (!fs.existsSync(packagePath)) {
55
- console.log(`Installing ${packageName}@${version}...`);
56
- const installCmd = `npm install ${packageName}@${version} --save-dev --legacy-peer-deps`;
57
- (0, utils_1.executeSyncCmd)(`cd ${projectRoot} && ${installCmd}`, (errMsg) => {
58
- console.log(`Error installing ${packageName}:`, errMsg);
59
- throw Error(errMsg);
60
- }, `Installing ${packageName}: `);
61
- console.log(`Successfully installed ${packageName}@${version}`);
42
+ const dynamicImport = new Function("specifier", "return import(specifier);");
43
+ const importFromFile = async (modulePath) => {
44
+ const moduleUrl = (0, url_1.pathToFileURL)(modulePath).href;
45
+ return dynamicImport(moduleUrl);
46
+ };
47
+ const groupFilesByMode = (directory) => {
48
+ const modeGroups = {
49
+ default: [], // files without a mode in the name
50
+ };
51
+ const items = fs.readdirSync(directory);
52
+ items.forEach((item) => {
53
+ const itemPath = path.join(directory, item);
54
+ const stats = fs.statSync(itemPath);
55
+ if (stats.isDirectory()) {
56
+ // Recursively collect from subdirectories
57
+ const subGroup = groupFilesByMode(itemPath);
58
+ for (const mode in subGroup) {
59
+ if (!modeGroups[mode]) {
60
+ modeGroups[mode] = [];
61
+ }
62
+ modeGroups[mode].push(...subGroup[mode]);
63
+ }
64
+ }
65
+ else if (stats.isFile() && path.extname(itemPath) === ".json") {
66
+ const match = item.match(/\.([^.]+)\.json$/); // Matches ".dark.json" or ".light.json"
67
+ if (match) {
68
+ const mode = match[1]; // 'dark' or 'light' etc.
69
+ if (!modeGroups[mode]) {
70
+ modeGroups[mode] = [];
71
+ }
72
+ modeGroups[mode].push(itemPath);
73
+ }
74
+ else {
75
+ modeGroups.default.push(itemPath);
76
+ }
77
+ }
78
+ });
79
+ return modeGroups;
80
+ };
81
+ const generateModeConfigs = (modeGroups, sourceDir, cssVarCalcMixFormatter, componentVariantsFormatter) => {
82
+ const baseCssFormatName = (cssVarCalcMixFormatter && cssVarCalcMixFormatter.name) || "css/variables";
83
+ const variantCssFormatName = (componentVariantsFormatter && componentVariantsFormatter.name) || "css/variables";
84
+ const configs = [];
85
+ for (const mode in modeGroups) {
86
+ const tokenFiles = modeGroups[mode];
87
+ const buildPaths = tokenFiles.flatMap((filePath) => {
88
+ const relativePath = filePath.replace(sourceDir + "/", "");
89
+ return [
90
+ {
91
+ destination: relativePath.replace(/\.json$/, ".css"),
92
+ options: { outputReferences: true, selector: ":root" },
93
+ format: baseCssFormatName,
94
+ filter: function (token) {
95
+ var tokenPath;
96
+ // Extract file path from token['@'].filePath (used in some token formats) or fallback to token.filePath.
97
+ if (token["@"] && token["@"].filePath) {
98
+ tokenPath = token["@"].filePath;
99
+ }
100
+ else {
101
+ tokenPath = token.filePath;
102
+ }
103
+ // normalize paths for Windows
104
+ const normalizePath = (p) => (p ? p.replace(/\\/g, "/") : p);
105
+ tokenPath = normalizePath(tokenPath);
106
+ filePath = normalizePath(filePath);
107
+ // Only include tokens originating from "overrides" files (i.e., filter out foundation CSS tokens)
108
+ var isOverrideToken = (tokenPath && tokenPath.indexOf("overrides") !== -1) ||
109
+ (token.filePath && token.filePath.indexOf("overrides") !== -1);
110
+ // Ensure the token is written only to the correct CSS file
111
+ var matchesOutputFile = tokenPath &&
112
+ (filePath.includes(tokenPath) || filePath.includes(normalizePath(token.filePath))) &&
113
+ !token.path.includes("appearances") &&
114
+ !token.path.includes("states");
115
+ return isOverrideToken && matchesOutputFile;
116
+ },
117
+ },
118
+ {
119
+ destination: relativePath.replace(/\.json$/, "variant.css"),
120
+ options: { outputReferences: true, selector: ":root" },
121
+ format: variantCssFormatName,
122
+ filter: (token) => {
123
+ let tokenPath;
124
+ if (token["@"] && token["@"].filePath) {
125
+ tokenPath = token["@"].filePath;
126
+ }
127
+ else {
128
+ tokenPath = token.filePath;
129
+ }
130
+ const isOverrideToken = tokenPath && tokenPath.indexOf("overrides") !== -1;
131
+ const matchesOutputFile = tokenPath &&
132
+ (filePath.includes(tokenPath) || filePath.includes(token.filePath)) &&
133
+ (token.path.includes("appearances") || token.path.includes("states"));
134
+ return isOverrideToken && matchesOutputFile;
135
+ },
136
+ },
137
+ ];
138
+ });
139
+ configs.push({
140
+ mode,
141
+ files: buildPaths,
142
+ });
143
+ }
144
+ return configs;
145
+ };
146
+ const accessFile = (filePath) => {
147
+ const dirPath = path.dirname(filePath); // Get directory from file path
148
+ // Ensure the directory exists
149
+ if (!fs.existsSync(dirPath)) {
150
+ fs.mkdirSync(dirPath, { recursive: true });
151
+ console.log(`Directory created: ${dirPath}`);
152
+ }
153
+ fs.access(filePath, fs.constants.F_OK, err => {
154
+ if (err) {
155
+ console.log(`${filePath} does not exist. Creating file...`);
156
+ // File does not exist, create it
157
+ const fileContent = JSON.stringify({});
158
+ fs.writeFile(filePath, fileContent, err => {
159
+ if (err)
160
+ throw err;
161
+ console.log(`${filePath} was created successfully.`);
162
+ });
163
+ }
164
+ });
165
+ };
166
+ async function setupSymlink(from, to) {
167
+ try {
168
+ // Ensure the parent directory of the symlink exists
169
+ await fs.promises.mkdir(path.dirname(to), { recursive: true });
170
+ try {
171
+ if (fs.existsSync(to))
172
+ await fs.promises.unlink(to);
173
+ }
174
+ catch (unlinkErr) {
175
+ console.error("Error removing existing symlink:", unlinkErr);
176
+ }
177
+ // Create the symlink
178
+ const isWindows = process.platform === "win32";
179
+ const symlinkType = isWindows ? "junction" : "dir";
180
+ await fs.promises.symlink(from, to, symlinkType);
181
+ console.log("Symlink created successfully at:", to);
182
+ }
183
+ catch (err) {
184
+ console.error("Error creating symlink:", to, err);
185
+ }
186
+ }
187
+ // Function to generate Style Dictionary configuration
188
+ const getStyleDictionaryConfig = (files, tempFoundationTokensSymlink, mode, sourceDir) => {
189
+ if (!sourceDir.endsWith("/")) {
190
+ sourceDir += "/";
191
+ }
192
+ let sourcePattern = "";
193
+ if (mode === "default") {
194
+ // Files without any mode like dark/light in the name
195
+ sourcePattern = `${sourceDir}/src/main/webapp/${utils_1.OVERRIDE_TOKENS_PATH}/**/!(*.*).json`;
62
196
  }
63
197
  else {
64
- console.log(`${packageName} already installed`);
198
+ // Files like *.dark.json or *.light.json
199
+ sourcePattern = `${sourceDir}/src/main/webapp/${utils_1.OVERRIDE_TOKENS_PATH}/**/*.${mode}.json`;
200
+ }
201
+ return {
202
+ log: {
203
+ verbosity: "verbose",
204
+ },
205
+ source: [sourcePattern],
206
+ include: [
207
+ `${tempFoundationTokensSymlink.replace(/\\/g, "/")}/**/!(*.dark|*.light).json`,
208
+ `${sourceDir.replace(/\\/g, "/")}/src/main/webapp/${utils_1.OVERRIDE_TOKENS_PATH}/global/**/*.json`,
209
+ ],
210
+ platforms: {
211
+ css: {
212
+ transformGroup: "css",
213
+ prefix: "--wm",
214
+ files: files,
215
+ },
216
+ },
217
+ };
218
+ };
219
+ async function removeSymlink(symlinkPath) {
220
+ const resolvedPath = path.resolve(symlinkPath);
221
+ try {
222
+ const stats = fs.lstatSync(resolvedPath);
223
+ if (stats.isSymbolicLink()) {
224
+ await fs.promises.unlink(resolvedPath);
225
+ console.log("Symlink removed successfully:", resolvedPath);
226
+ }
227
+ else {
228
+ console.warn("Not a symlink, skipping unlink:", resolvedPath);
229
+ }
230
+ }
231
+ catch (err) {
232
+ console.error("Error during symlink removal:", err);
233
+ }
234
+ }
235
+ async function getCustomFormatters(STYLE_DICTIONARY_PATH, FOUNDATION_CSS_PATH) {
236
+ try {
237
+ // Import utils from Style Dictionary
238
+ const utilsModule = await importFromFile(`${STYLE_DICTIONARY_PATH}/node_modules/style-dictionary/lib/utils/index.js`);
239
+ const { usesReferences, getReferences } = utilsModule;
240
+ // Import formatter utility from foundation-css
241
+ const formatterModule = await importFromFile(`${FOUNDATION_CSS_PATH}/node_modules/@wavemaker/foundation-css/src/utils/style-dictionary-utils.js`);
242
+ const { cssVarCalcMixFormatter, componentVariantsFormatter } = formatterModule;
243
+ const platform = "web";
244
+ return {
245
+ cssVarCalcMixFormatter: cssVarCalcMixFormatter(usesReferences, getReferences),
246
+ componentVariantsFormatter: componentVariantsFormatter(usesReferences, getReferences, platform),
247
+ };
248
+ }
249
+ catch (error) {
250
+ console.error("Failed to load CssVarCalcMixFormatter:", error);
251
+ return null;
65
252
  }
66
253
  }
67
254
  /**
68
- * Process a single override JSON file to generate CSS variables
69
- * @param jsonFilePath path to the override JSON file
70
- * @param foundationTokensDir path to foundation tokens
71
- * @param baseDir base directory
72
- * @returns map of token name to value
255
+ * Processes an array of CSS files, merges :root blocks for light mode,
256
+ * and appends others with dynamic attribute selectors.
257
+ * @param {Array<{destination: string}>} files - List of file objects with destination paths.
258
+ * @returns {string} Combined CSS content after processing all files.
73
259
  */
74
- async function processOverrideFile(jsonFilePath, foundationTokensDir, baseDir) {
75
- const tokens = new Map();
76
- try {
77
- // Read override file
78
- const content = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8"));
79
- // Read foundation tokens for reference resolution
80
- const foundationTokens = new Map();
81
- function loadFoundationTokens(dir, prefix = "") {
82
- if (!fs.existsSync(dir))
83
- return;
84
- const items = fs.readdirSync(dir);
85
- items.forEach(item => {
86
- const itemPath = path.join(dir, item);
87
- const stat = fs.statSync(itemPath);
88
- if (stat.isDirectory()) {
89
- loadFoundationTokens(itemPath, prefix ? `${prefix}-${item}` : item);
260
+ function processCSSFiles(files, cssFileContent) {
261
+ for (const { destination } of files) {
262
+ try {
263
+ if (destination.endsWith(".css") && fs.existsSync(destination)) {
264
+ const fileContent = fs.readFileSync(destination, "utf-8");
265
+ const rootBlockPattern = /(:root\s*\{[^}]*\})/;
266
+ const fileName = path.basename(destination); // Get file name
267
+ const fileNameArgs = fileName.split("."); // Split by '.'
268
+ let modifiedCSS = fileContent;
269
+ // e.g., color.dark.css → add [color='dark']
270
+ if (fileNameArgs.length === 3 && fileNameArgs[1] !== "light") {
271
+ const attributeName = fileNameArgs[0];
272
+ const attributeValue = fileNameArgs[1];
273
+ modifiedCSS = fileContent.replace(/:root/g, `:root[${attributeName}='${attributeValue}']`);
274
+ cssFileContent += modifiedCSS + "\n";
90
275
  }
91
- else if (item.endsWith(".json") && !item.includes(".dark") && !item.includes(".light")) {
92
- try {
93
- const tokenContent = JSON.parse(fs.readFileSync(itemPath, "utf-8"));
94
- flattenTokens(tokenContent, foundationTokens, prefix ? `${prefix}-${path.basename(item, ".json")}` : path.basename(item, ".json"));
95
- }
96
- catch (error) {
97
- // Skip invalid JSON files
98
- }
99
- }
100
- });
101
- }
102
- function flattenTokens(obj, tokenMap, prefix = "") {
103
- for (const [key, value] of Object.entries(obj)) {
104
- if (value && typeof value === "object" && !Array.isArray(value)) {
105
- if (value.value !== undefined) {
106
- // This is a token definition
107
- const tokenName = prefix ? `${prefix}.${key}` : key;
108
- tokenMap.set(tokenName, value.value);
276
+ else {
277
+ // Merge :root blocks for light/default mode
278
+ const existingRootMatch = cssFileContent.match(rootBlockPattern);
279
+ const newRootMatch = fileContent.match(rootBlockPattern);
280
+ if (existingRootMatch && newRootMatch) {
281
+ const existingRoot = existingRootMatch[1];
282
+ const newVariables = newRootMatch[1].replace(/:root\s*\{|\}/g, "").trim();
283
+ const mergedRoot = existingRoot.replace("}", `\n${newVariables}\n}`);
284
+ cssFileContent = cssFileContent.replace(existingRoot, mergedRoot);
109
285
  }
110
286
  else {
111
- // Continue traversing
112
- const newPrefix = prefix ? `${prefix}.${key}` : key;
113
- flattenTokens(value, tokenMap, newPrefix);
287
+ cssFileContent += modifiedCSS + "\n";
114
288
  }
115
289
  }
290
+ // Delete the processed file
291
+ fs.unlink(destination, () => { });
116
292
  }
117
293
  }
118
- // Load foundation tokens
119
- loadFoundationTokens(foundationTokensDir);
120
- // Process override tokens
121
- function processTokens(obj, prefix = "") {
122
- for (const [key, value] of Object.entries(obj)) {
123
- if (value && typeof value === "object" && !Array.isArray(value)) {
124
- if (value.value !== undefined) {
125
- // This is a token definition - skip @ keys for token names
126
- const cleanKey = key === "@" ? "" : key;
127
- const tokenName = cleanKey
128
- ? `--wm-${prefix ? `${prefix}-${cleanKey}` : cleanKey}`
129
- : `--wm-${prefix}`;
130
- let tokenValue = value.value;
131
- // Resolve references like {color.white.@.value} to CSS variables
132
- if (typeof tokenValue === "string" &&
133
- tokenValue.includes("{") &&
134
- tokenValue.includes("}")) {
135
- const referenceMatch = tokenValue.match(/\{([^}]+)\}/g);
136
- if (referenceMatch) {
137
- referenceMatch.forEach(ref => {
138
- const refKey = ref.slice(1, -1); // Remove { }
139
- // Convert foundation token path to CSS variable name
140
- let cssVarName = refKey
141
- .replace(".@.value", "")
142
- .replace(".value", "")
143
- .replace(/\./g, "-");
144
- // Convert to CSS variable format
145
- const cssVariable = `var(--wm-${cssVarName})`;
146
- tokenValue = tokenValue.replace(ref, cssVariable);
147
- });
148
- }
149
- }
150
- tokens.set(tokenName, tokenValue);
151
- }
152
- else {
153
- // Continue traversing - skip @ keys in paths
154
- const cleanKey = key === "@" ? "" : key;
155
- const newPrefix = prefix && cleanKey ? `${prefix}-${cleanKey}` : cleanKey || prefix;
156
- processTokens(value, newPrefix);
157
- }
158
- }
159
- }
294
+ catch (error) {
295
+ console.error(`\nStyle dictionary, Error processing file ${destination}:`, error);
160
296
  }
161
- processTokens(content);
162
297
  }
163
- catch (error) {
164
- console.error(`Error processing ${jsonFilePath}:`, error);
165
- }
166
- return tokens;
298
+ return cssFileContent;
167
299
  }
168
- async function generateOverrideCSS(runtimeUIVersion, sourceDir, appTarget) {
169
- // Use existing LocalProjectService to check if this is a Prism project
170
- const projectService = new project_service_1.LocalProjectService(sourceDir + "/src/main/webapp");
171
- const isPrismProject = await projectService.getWmProjectType();
172
- if (isPrismProject) {
173
- const overridesDir = path.join(sourceDir + `/src/main/webapp/`, exports.OVERRIDE_TOKENS_PATH);
174
- const overrideCssFile = sourceDir + `/src/main/webapp/${exports.APP_OVERRIDE_CSS_PATH}`;
175
- if (fs.existsSync(overridesDir)) {
176
- console.log("CODEGEN REACT APP: generating override css...");
177
- // Use the react-codegen package directory as baseDir
178
- // __dirname will be the 'build/src' directory after compilation,
179
- // so we go up one level to get the react-codegen root
180
- const baseDir = path.resolve(__dirname, "..");
181
- console.log("baseDir for npm packages (react-codegen path):", baseDir);
182
- // Install required packages
183
- await installPackageIfNeeded(baseDir, "style-dictionary", "4.1.0");
184
- await installPackageIfNeeded(baseDir, "@wavemaker/foundation-css", runtimeUIVersion || "latest");
185
- const foundationTokensDir = path.join(baseDir, "node_modules", "@wavemaker", "foundation-css", "tokens");
186
- // Find all override JSON files
187
- const overrideFiles = [];
188
- function findOverrideFiles(dir) {
189
- if (!fs.existsSync(dir))
190
- return;
191
- const items = fs.readdirSync(dir);
192
- items.forEach(item => {
193
- const itemPath = path.join(dir, item);
194
- const stat = fs.statSync(itemPath);
195
- if (stat.isDirectory()) {
196
- findOverrideFiles(itemPath);
197
- }
198
- else if (item.endsWith(".json")) {
199
- overrideFiles.push(itemPath);
200
- }
201
- });
202
- }
203
- findOverrideFiles(overridesDir);
204
- console.log(`Processing ${overrideFiles.length} override files...`);
205
- // Collect all tokens with source tracking
206
- const defaultTokens = new Map();
207
- const lightTokens = new Map();
208
- const darkTokens = new Map();
209
- for (const overrideFile of overrideFiles) {
210
- const fileName = path.basename(overrideFile);
211
- const fileTokens = await processOverrideFile(overrideFile, foundationTokensDir, baseDir);
212
- // Sort tokens by mode
213
- if (fileName.includes(".light.")) {
214
- fileTokens.forEach((value, name) => {
215
- lightTokens.set(name, value);
216
- });
217
- }
218
- else if (fileName.includes(".dark.")) {
219
- fileTokens.forEach((value, name) => {
220
- darkTokens.set(name, value);
221
- });
300
+ const generateOverrideCSS = async (args, sourceDir, baseDir) => {
301
+ args = args || {};
302
+ const overridesDir = path.join(sourceDir + `/src/main/webapp/`, utils_1.OVERRIDE_TOKENS_PATH);
303
+ // Check if file exists
304
+ const overrideCssFile = sourceDir + `/src/main/webapp/${utils_1.APP_OVERRIDE_CSS_PATH}`;
305
+ accessFile(overrideCssFile);
306
+ if (fs.existsSync(overridesDir)) {
307
+ console.log("CODEGEN REACT APP: generating override css...");
308
+ let styleDictionaryPackageInfo = {
309
+ scope: "",
310
+ name: "style-dictionary",
311
+ version: "4.1.0",
312
+ packageJsonFile: "",
313
+ successMsg: "STYLE DICTIONARY SUCCESS",
314
+ infoMsg: "STYLE DICTIONARY PACKAGE : ",
315
+ skipPackageVersion: false,
316
+ };
317
+ styleDictionaryPackageInfo.baseDir = baseDir;
318
+ const STYLE_DICTIONARY_PATH = await (0, download_packages_1.downloadNPMPackage)(styleDictionaryPackageInfo);
319
+ let foundationCSSPackageInfo = {
320
+ scope: "@wavemaker",
321
+ name: "foundation-css",
322
+ version: args.runtimeUIVersion || "latest",
323
+ packageJsonFile: "",
324
+ successMsg: "Foundation-CSS SUCCESS",
325
+ infoMsg: "Foundation-CSS PACKAGE : ",
326
+ };
327
+ foundationCSSPackageInfo.baseDir = baseDir;
328
+ const FOUNDATION_CSS_PATH = await (0, download_packages_1.downloadNPMPackage)(foundationCSSPackageInfo);
329
+ console.log("FOUNDATION_CSS_PATH", FOUNDATION_CSS_PATH, "SourceDir", sourceDir);
330
+ await (async () => {
331
+ const StyleDictionary = await importFromFile(`${STYLE_DICTIONARY_PATH}/node_modules/style-dictionary/lib/StyleDictionary.js`).then(mod => mod.default);
332
+ const foundationTokensDir = path.join(FOUNDATION_CSS_PATH, "/node_modules/@wavemaker/foundation-css/src/tokens/web");
333
+ const { cssVarCalcMixFormatter, componentVariantsFormatter } = (await getCustomFormatters(STYLE_DICTIONARY_PATH, FOUNDATION_CSS_PATH));
334
+ if (!cssVarCalcMixFormatter || !componentVariantsFormatter) {
335
+ if (!cssVarCalcMixFormatter) {
336
+ console.error("cssVarCalcMixFormatter failed to load.");
222
337
  }
223
- else {
224
- fileTokens.forEach((value, name) => {
225
- defaultTokens.set(name, value);
226
- });
338
+ if (!componentVariantsFormatter) {
339
+ console.error("cssVariantFormatter failed to load.");
227
340
  }
228
341
  }
229
- // Generate final CSS with mode-specific attribute selectors like Angular
230
- const cssLines = [];
231
- // Add default tokens
232
- if (defaultTokens.size > 0) {
233
- cssLines.push(":root {");
234
- defaultTokens.forEach((value, name) => {
235
- cssLines.push(`${name}: ${value};`);
236
- });
237
- cssLines.push("}");
238
- }
239
- // Add light mode tokens with attribute selectors (like Angular does)
240
- if (lightTokens.size > 0) {
241
- if (cssLines.length > 0)
242
- cssLines.push("");
243
- cssLines.push(":root[color='light'] {");
244
- lightTokens.forEach((value, name) => {
245
- cssLines.push(`${name}: ${value};`);
246
- });
247
- cssLines.push("}");
248
- }
249
- // Add dark mode tokens with attribute selectors (like Angular does)
250
- if (darkTokens.size > 0) {
251
- if (cssLines.length > 0)
252
- cssLines.push("");
253
- cssLines.push(":root[color='dark'] {");
254
- darkTokens.forEach((value, name) => {
255
- cssLines.push(`${name}: ${value};`);
256
- });
257
- cssLines.push("}");
258
- }
259
- const totalTokens = defaultTokens.size + lightTokens.size + darkTokens.size;
260
- // Only generate CSS files if there are actual tokens
261
- if (totalTokens > 0) {
262
- const finalCSS = cssLines.join("\n");
263
- fs.writeFileSync(overrideCssFile, finalCSS);
264
- // Also copy to public directory for React app if appTarget is provided
265
- if (appTarget) {
266
- const publicCssPath = path.join(appTarget, "public", exports.APP_OVERRIDE_CSS_PATH);
267
- const publicDir = path.dirname(publicCssPath);
268
- const globalCSSPath = path.join(appTarget, "app", "globals.css");
269
- if (!fs.existsSync(publicDir)) {
270
- fs.mkdirSync(publicDir, { recursive: true });
342
+ cssVarCalcMixFormatter && StyleDictionary.registerFormat(cssVarCalcMixFormatter);
343
+ componentVariantsFormatter && StyleDictionary.registerFormat(componentVariantsFormatter);
344
+ const tempFoundationTokensSymlink = path.resolve(sourceDir, "src", "main", "webapp", utils_1.DESIGN_TOKENS_DIR_NAME, "temp-tokens");
345
+ const modeGroups = groupFilesByMode(overridesDir);
346
+ const modeConfigs = generateModeConfigs(modeGroups, sourceDir, cssVarCalcMixFormatter, componentVariantsFormatter);
347
+ let cssFileContent = "";
348
+ try {
349
+ console.log("\nSetting up foundation tokens symlink...");
350
+ await setupSymlink(foundationTokensDir, tempFoundationTokensSymlink);
351
+ for (const { mode, files } of modeConfigs) {
352
+ console.log(`\nBuilding CSS for mode: ${mode}...`);
353
+ try {
354
+ const config = getStyleDictionaryConfig(files, tempFoundationTokensSymlink, mode, sourceDir);
355
+ console.log(config, mode);
356
+ const sd = new StyleDictionary(config);
357
+ await sd.buildPlatform("css");
358
+ console.log(`Style Dictionary build completed for mode: ${mode}`);
359
+ cssFileContent = processCSSFiles(files, cssFileContent);
360
+ fs.writeFileSync(overrideCssFile, cssFileContent);
361
+ console.log(`CSS overrides generated successfully for mode: ${mode}`);
271
362
  }
272
- fs.writeFileSync(publicCssPath, finalCSS);
273
- console.log(`✅ CSS copied to React app public directory`);
274
- // Now that we've generated the override CSS, add its import to globals.css
275
- if (fs.existsSync(globalCSSPath)) {
276
- const content = fs.readFileSync(globalCSSPath, "utf-8");
277
- // Check if the import is already present
278
- if (!content.includes("public/design-tokens/app.override.css")) {
279
- // Add the import after the existing imports
280
- const lines = content.split("\n");
281
- let insertIndex = 0;
282
- // Find the last import line
283
- for (let i = 0; i < lines.length; i++) {
284
- if (lines[i].startsWith("@import")) {
285
- insertIndex = i + 1;
286
- }
287
- else if (lines[i].trim() === "" && insertIndex > 0) {
288
- insertIndex = i;
289
- break;
290
- }
291
- }
292
- // Insert the override CSS import
293
- lines.splice(insertIndex, 0, '@import "../public/design-tokens/app.override.css";');
294
- fs.writeFileSync(globalCSSPath, lines.join("\n"), "utf-8");
295
- console.log("✅ Added CSS override import to globals.css");
296
- }
363
+ catch (err) {
364
+ console.error(`Error during Style Dictionary build for mode: ${mode}`, err);
297
365
  }
298
366
  }
299
- console.log(`✅ Generated CSS with ${totalTokens} override tokens`);
300
- console.log("CODEGEN REACT APP: generating overrides success!");
367
+ console.log("CODEGEN REACT APP: generating overrides success !");
301
368
  }
302
- else {
303
- console.log("ℹ️ No design tokens found, skipping CSS generation");
369
+ catch (err) {
370
+ console.error("Error setting up symlink or processing modes:", err);
304
371
  }
305
- }
372
+ finally {
373
+ await removeSymlink(tempFoundationTokensSymlink);
374
+ }
375
+ })();
306
376
  }
307
- }
377
+ };
378
+ exports.generateOverrideCSS = generateOverrideCSS;
308
379
  //# sourceMappingURL=gen-app-override-css.js.map