@edx/frontend-platform 4.0.2 → 4.1.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.
@@ -1,25 +1,29 @@
1
1
  # i18n/scripts
2
2
 
3
- This directory contains the `transifex-utils.js` file which is shared across all micro-frontends.
3
+ This directory contains the `transifex-utils.js` and `intl-imports.js` files which are shared across all micro-frontends.
4
4
 
5
- The package.json of `frontend-platform` includes the following section:
5
+ The package.json of `frontend-platform` includes the following sections:
6
6
 
7
7
  ```
8
8
  "bin": {
9
+ "intl-imports.js": "i18n/scripts/intl-imports.js"
9
10
  "transifex-utils.js": "i18n/scripts/transifex-utils.js"
10
11
  },
11
12
  ```
12
13
 
13
- This config block causes `transifex-utils.js` to be copied to the following path when `frontend-platform` is installed as a dependency of an micro-frontend:
14
+ This config block causes boths scripts to be copied to the following path when `frontend-platform` is installed as a
15
+ dependency of a micro-frontend:
14
16
 
15
17
  ```
18
+ /node_modules/.bin/intl-imports.js
16
19
  /node_modules/.bin/transifex-utils.js
17
20
  ```
18
21
 
19
- All micro-frontends have a `Makefile` with a line that loads `transifex-utils.js` from the above path:
22
+ All micro-frontends have a `Makefile` with a line that loads the scripts from the above path:
20
23
 
21
24
  ```
25
+ intl_imports = ./node_modules/.bin/intl-imports.js
22
26
  transifex_utils = ./node_modules/.bin/transifex-utils.js
23
27
  ```
24
28
 
25
- So if you delete `transifex-utils.js` or the `scripts` directory, you'll break all micro-frontend builds. Happy coding!
29
+ So if you delete either of the files or the `scripts` directory, you'll break all micro-frontend builds. Happy coding!
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+ var scriptHelpDocument = "\nNAME\n intl-imports.js \u2014 Script to generate the src/i18n/index.js file that exports messages from all the languages for Micro-frontends.\n\nSYNOPSIS\n intl-imports.js [DIRECTORY ...]\n\nDESCRIPTION\n This script is intended to run after 'atlas' has pulled the files.\n \n This expects to run inside a Micro-frontend root directory with the following structure:\n \n frontend-app-learning $ tree src/i18n/\n src/i18n/\n \u251C\u2500\u2500 index.js\n \u2514\u2500\u2500 messages\n \u251C\u2500\u2500 frontend-app-example\n \u2502 \u251C\u2500\u2500 ar.json\n \u2502 \u251C\u2500\u2500 es_419.json\n \u2502 \u2514\u2500\u2500 zh_CN.json\n \u251C\u2500\u2500 frontend-component-footer\n \u2502 \u251C\u2500\u2500 ar.json\n \u2502 \u251C\u2500\u2500 es_419.json\n \u2502 \u2514\u2500\u2500 zh_CN.json\n \u2514\u2500\u2500 frontend-component-header (empty directory)\n \n \n \n With the structure above it's expected to run with the following command in Makefile:\n \n \n $ node_modules/.bin/intl-imports.js frontend-component-footer frontend-component-header frontend-app-example\n \n \n It will generate two type of files:\n \n - Main src/i18n/index.js which overrides the Micro-frontend provided with a sample output of:\n \n \"\"\"\n import messagesFromFrontendComponentFooter from './messages/frontend-component-footer';\n // Skipped import due to missing './messages/frontend-component-footer/index.js' likely due to empty translations.\n import messagesFromFrontendAppExample from './messages/frontend-app-example';\n \n export default [\n messagesFromFrontendComponentFooter,\n messagesFromFrontendAppExample,\n ];\n \"\"\"\n \n - Each sub-directory has src/i18n/messages/frontend-component-header/index.js which is imported by the main file.:\n \n \"\"\"\n import messagesOfArLanguage from './ar.json';\n import messagesOfDeLanguage from './de.json';\n import messagesOfEs419Language from './es_419.json';\n export default {\n 'ar': messagesOfArLanguage,\n 'de': messagesOfDeLanguage,\n 'es-419': messagesOfEs419Language,\n };\n \"\"\"\n";
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+ var camelCase = require('lodash.camelcase');
6
+ var loggingPrefix = path.basename("".concat(__filename)); // the name of this JS file
7
+
8
+ // Header note for generated src/i18n/index.js file
9
+ var filesCodeGeneratorNoticeHeader = "// This file is generated by the openedx/frontend-platform's \"intl-import.js\" script.\n//\n// Refer to the i18n documents in https://docs.openedx.org/en/latest/developers/references/i18n.html to update\n// the file and use the Micro-frontend i18n pattern in new repositories.\n//\n";
10
+
11
+ /**
12
+ * Create frontend-app-example/index.js file with proper imports.
13
+ *
14
+ * @param directory - a directory name containing .json files from Transifex e.g. "frontend-app-example".
15
+ * @param log - Mockable process.stdout.write
16
+ * @param writeFileSync - Mockable fs.writeFileSync
17
+ * @param i18nDir - Path to `src/i18n` directory
18
+ *
19
+ * @return object - An object containing directory name and whether its "index.js" file was successfully written.
20
+ */
21
+ function generateSubdirectoryMessageFile(_ref) {
22
+ var directory = _ref.directory,
23
+ log = _ref.log,
24
+ writeFileSync = _ref.writeFileSync,
25
+ i18nDir = _ref.i18nDir;
26
+ var importLines = [];
27
+ var messagesLines = [];
28
+ var counter = {
29
+ nonEmptyLanguages: 0
30
+ };
31
+ var messagesDir = "".concat(i18nDir, "/messages"); // The directory of Micro-frontend i18n messages
32
+
33
+ try {
34
+ var files = fs.readdirSync("".concat(messagesDir, "/").concat(directory), {
35
+ withFileTypes: true
36
+ });
37
+ files.sort(); // Sorting ensures a consistent generated `index.js` order of imports cross-platforms.
38
+
39
+ var jsonFiles = files.filter(function (file) {
40
+ return file.isFile() && file.name.endsWith('.json');
41
+ });
42
+ if (!jsonFiles.length) {
43
+ log("".concat(loggingPrefix, ": Not creating '").concat(directory, "/index.js' because no .json translation files were found.\n"));
44
+ return {
45
+ directory: directory,
46
+ isWritten: false
47
+ };
48
+ }
49
+ jsonFiles.forEach(function (file) {
50
+ var filename = file.name;
51
+ // Gets `fr_CA` from `fr_CA.json`
52
+ var languageCode = filename.replace(/\.json$/, '');
53
+ // React-friendly language code fr_CA --> fr-ca
54
+ var reactIntlLanguageCode = languageCode.toLowerCase().replace(/_/g, '-');
55
+ // camelCase variable name
56
+ var messagesCamelCaseVar = camelCase("messages_Of_".concat(languageCode, "_Language"));
57
+ var filePath = "".concat(messagesDir, "/").concat(directory, "/").concat(filename);
58
+ try {
59
+ var entries = JSON.parse(fs.readFileSync(filePath, {
60
+ encoding: 'utf8'
61
+ }));
62
+ if (!Object.keys(entries).length) {
63
+ importLines.push("// Note: Skipped empty '".concat(filename, "' messages file."));
64
+ return; // Skip the language
65
+ }
66
+ } catch (e) {
67
+ importLines.push("// Error: unable to parse '".concat(filename, "' messages file."));
68
+ log("".concat(loggingPrefix, ": NOTICE: Skipping '").concat(directory, "/").concat(filename, "' due to error: ").concat(e, ".\n"));
69
+ return; // Skip the language
70
+ }
71
+
72
+ counter.nonEmptyLanguages += 1;
73
+ importLines.push("import ".concat(messagesCamelCaseVar, " from './").concat(filename, "';"));
74
+ messagesLines.splice(1, 0, " '".concat(reactIntlLanguageCode, "': ").concat(messagesCamelCaseVar, ","));
75
+ });
76
+ if (counter.nonEmptyLanguages) {
77
+ // See the help message above for sample output.
78
+ var messagesFileContent = [filesCodeGeneratorNoticeHeader, importLines.join('\n'), '\nexport default {', messagesLines.join('\n'), '};\n'].join('\n');
79
+ writeFileSync("".concat(messagesDir, "/").concat(directory, "/index.js"), messagesFileContent);
80
+ return {
81
+ directory: directory,
82
+ isWritten: true
83
+ };
84
+ }
85
+ log("".concat(loggingPrefix, ": Skipping '").concat(directory, "' because no languages were found.\n"));
86
+ } catch (e) {
87
+ log("".concat(loggingPrefix, ": NOTICE: Skipping '").concat(directory, "' due to error: ").concat(e, ".\n"));
88
+ }
89
+ return {
90
+ directory: directory,
91
+ isWritten: false
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Create main `src/i18n/index.js` messages import file.
97
+ *
98
+ *
99
+ * @param processedDirectories - List of directories with a boolean flag whether its "index.js" file is written
100
+ * The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]"
101
+ * @param log - Mockable process.stdout.write
102
+ * @param writeFileSync - Mockable fs.writeFileSync
103
+ * @param i18nDir` - Path to `src/i18n` directory
104
+ */
105
+ function generateMainMessagesFile(_ref2) {
106
+ var processedDirectories = _ref2.processedDirectories,
107
+ log = _ref2.log,
108
+ writeFileSync = _ref2.writeFileSync,
109
+ i18nDir = _ref2.i18nDir;
110
+ var importLines = [];
111
+ var exportLines = [];
112
+ processedDirectories.forEach(function (processedDirectory) {
113
+ var directory = processedDirectory.directory,
114
+ isWritten = processedDirectory.isWritten;
115
+ if (isWritten) {
116
+ var moduleCamelCaseVariableName = camelCase("messages_from_".concat(directory));
117
+ importLines.push("import ".concat(moduleCamelCaseVariableName, " from './messages/").concat(directory, "';"));
118
+ exportLines.push(" ".concat(moduleCamelCaseVariableName, ","));
119
+ } else {
120
+ var skipMessage = "Skipped import due to missing '".concat(directory, "/index.js' likely due to empty translations.");
121
+ importLines.push("// ".concat(skipMessage, "."));
122
+ log("".concat(loggingPrefix, ": ").concat(skipMessage, "\n"));
123
+ }
124
+ });
125
+
126
+ // See the help message above for sample output.
127
+ var indexFileContent = [filesCodeGeneratorNoticeHeader, importLines.join('\n'), '\nexport default [', exportLines.join('\n'), '];\n'].join('\n');
128
+ writeFileSync("".concat(i18nDir, "/index.js"), indexFileContent);
129
+ }
130
+
131
+ /*
132
+ * Main function of the file.
133
+ */
134
+ function main(_ref3) {
135
+ var directories = _ref3.directories,
136
+ log = _ref3.log,
137
+ writeFileSync = _ref3.writeFileSync,
138
+ pwd = _ref3.pwd;
139
+ var i18nDir = "".concat(pwd, "/src/i18n"); // The Micro-frontend i18n root directory
140
+
141
+ if (directories.includes('--help') || directories.includes('-h')) {
142
+ log(scriptHelpDocument);
143
+ } else if (!directories.length) {
144
+ log(scriptHelpDocument);
145
+ log("".concat(loggingPrefix, ": Error: A list of directories is required.\n"));
146
+ } else if (!fs.existsSync(i18nDir) || !fs.lstatSync(i18nDir).isDirectory()) {
147
+ log(scriptHelpDocument);
148
+ log("".concat(loggingPrefix, ": Error: src/i18n directory was not found.\n"));
149
+ } else {
150
+ var processedDirectories = directories.map(function (directory) {
151
+ return generateSubdirectoryMessageFile({
152
+ directory: directory,
153
+ log: log,
154
+ writeFileSync: writeFileSync,
155
+ i18nDir: i18nDir
156
+ });
157
+ });
158
+ generateMainMessagesFile({
159
+ processedDirectories: processedDirectories,
160
+ log: log,
161
+ writeFileSync: writeFileSync,
162
+ i18nDir: i18nDir
163
+ });
164
+ }
165
+ }
166
+ if (require.main === module) {
167
+ // Run the main() function if called from the command line.
168
+ main({
169
+ directories: process.argv.slice(2),
170
+ log: function log(text) {
171
+ return process.stdout.write(text);
172
+ },
173
+ writeFileSync: fs.writeFileSync,
174
+ pwd: process.env.PWD
175
+ });
176
+ }
177
+ module.exports.main = main; // Allow tests to use the main function.
178
+ //# sourceMappingURL=intl-imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intl-imports.js","names":["scriptHelpDocument","fs","require","path","camelCase","loggingPrefix","basename","concat","__filename","filesCodeGeneratorNoticeHeader","generateSubdirectoryMessageFile","_ref","directory","log","writeFileSync","i18nDir","importLines","messagesLines","counter","nonEmptyLanguages","messagesDir","files","readdirSync","withFileTypes","sort","jsonFiles","filter","file","isFile","name","endsWith","length","isWritten","forEach","filename","languageCode","replace","reactIntlLanguageCode","toLowerCase","messagesCamelCaseVar","filePath","entries","JSON","parse","readFileSync","encoding","Object","keys","push","e","splice","messagesFileContent","join","generateMainMessagesFile","_ref2","processedDirectories","exportLines","processedDirectory","moduleCamelCaseVariableName","skipMessage","indexFileContent","main","_ref3","directories","pwd","includes","existsSync","lstatSync","isDirectory","map","module","process","argv","slice","text","stdout","write","env","PWD","exports"],"sources":["../../../src/i18n/scripts/intl-imports.js"],"sourcesContent":["#!/usr/bin/env node\n\nconst scriptHelpDocument = `\nNAME\n intl-imports.js — Script to generate the src/i18n/index.js file that exports messages from all the languages for Micro-frontends.\n\nSYNOPSIS\n intl-imports.js [DIRECTORY ...]\n\nDESCRIPTION\n This script is intended to run after 'atlas' has pulled the files.\n \n This expects to run inside a Micro-frontend root directory with the following structure:\n \n frontend-app-learning $ tree src/i18n/\n src/i18n/\n ├── index.js\n └── messages\n ├── frontend-app-example\n │ ├── ar.json\n │ ├── es_419.json\n │ └── zh_CN.json\n ├── frontend-component-footer\n │ ├── ar.json\n │ ├── es_419.json\n │ └── zh_CN.json\n └── frontend-component-header (empty directory)\n \n \n \n With the structure above it's expected to run with the following command in Makefile:\n \n \n $ node_modules/.bin/intl-imports.js frontend-component-footer frontend-component-header frontend-app-example\n \n \n It will generate two type of files:\n \n - Main src/i18n/index.js which overrides the Micro-frontend provided with a sample output of:\n \n \"\"\"\n import messagesFromFrontendComponentFooter from './messages/frontend-component-footer';\n // Skipped import due to missing './messages/frontend-component-footer/index.js' likely due to empty translations.\n import messagesFromFrontendAppExample from './messages/frontend-app-example';\n \n export default [\n messagesFromFrontendComponentFooter,\n messagesFromFrontendAppExample,\n ];\n \"\"\"\n \n - Each sub-directory has src/i18n/messages/frontend-component-header/index.js which is imported by the main file.:\n \n \"\"\"\n import messagesOfArLanguage from './ar.json';\n import messagesOfDeLanguage from './de.json';\n import messagesOfEs419Language from './es_419.json';\n export default {\n 'ar': messagesOfArLanguage,\n 'de': messagesOfDeLanguage,\n 'es-419': messagesOfEs419Language,\n };\n \"\"\"\n`;\n\nconst fs = require('fs');\nconst path = require('path');\nconst camelCase = require('lodash.camelcase');\n\nconst loggingPrefix = path.basename(`${__filename}`); // the name of this JS file\n\n// Header note for generated src/i18n/index.js file\nconst filesCodeGeneratorNoticeHeader = `// This file is generated by the openedx/frontend-platform's \"intl-import.js\" script.\n//\n// Refer to the i18n documents in https://docs.openedx.org/en/latest/developers/references/i18n.html to update\n// the file and use the Micro-frontend i18n pattern in new repositories.\n//\n`;\n\n/**\n * Create frontend-app-example/index.js file with proper imports.\n *\n * @param directory - a directory name containing .json files from Transifex e.g. \"frontend-app-example\".\n * @param log - Mockable process.stdout.write\n * @param writeFileSync - Mockable fs.writeFileSync\n * @param i18nDir - Path to `src/i18n` directory\n *\n * @return object - An object containing directory name and whether its \"index.js\" file was successfully written.\n */\nfunction generateSubdirectoryMessageFile({\n directory,\n log,\n writeFileSync,\n i18nDir,\n}) {\n const importLines = [];\n const messagesLines = [];\n const counter = { nonEmptyLanguages: 0 };\n const messagesDir = `${i18nDir}/messages`; // The directory of Micro-frontend i18n messages\n\n try {\n const files = fs.readdirSync(`${messagesDir}/${directory}`, { withFileTypes: true });\n files.sort(); // Sorting ensures a consistent generated `index.js` order of imports cross-platforms.\n\n const jsonFiles = files.filter(file => file.isFile() && file.name.endsWith('.json'));\n\n if (!jsonFiles.length) {\n log(`${loggingPrefix}: Not creating '${directory}/index.js' because no .json translation files were found.\\n`);\n return {\n directory,\n isWritten: false,\n };\n }\n\n jsonFiles.forEach((file) => {\n const filename = file.name;\n // Gets `fr_CA` from `fr_CA.json`\n const languageCode = filename.replace(/\\.json$/, '');\n // React-friendly language code fr_CA --> fr-ca\n const reactIntlLanguageCode = languageCode.toLowerCase().replace(/_/g, '-');\n // camelCase variable name\n const messagesCamelCaseVar = camelCase(`messages_Of_${languageCode}_Language`);\n const filePath = `${messagesDir}/${directory}/${filename}`;\n\n try {\n const entries = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));\n\n if (!Object.keys(entries).length) {\n importLines.push(`// Note: Skipped empty '${filename}' messages file.`);\n return; // Skip the language\n }\n } catch (e) {\n importLines.push(`// Error: unable to parse '${filename}' messages file.`);\n log(`${loggingPrefix}: NOTICE: Skipping '${directory}/${filename}' due to error: ${e}.\\n`);\n return; // Skip the language\n }\n\n counter.nonEmptyLanguages += 1;\n importLines.push(`import ${messagesCamelCaseVar} from './${filename}';`);\n messagesLines.splice(1, 0, ` '${reactIntlLanguageCode}': ${messagesCamelCaseVar},`);\n });\n\n if (counter.nonEmptyLanguages) {\n // See the help message above for sample output.\n const messagesFileContent = [\n filesCodeGeneratorNoticeHeader,\n importLines.join('\\n'),\n '\\nexport default {',\n messagesLines.join('\\n'),\n '};\\n',\n ].join('\\n');\n\n writeFileSync(`${messagesDir}/${directory}/index.js`, messagesFileContent);\n return {\n directory,\n isWritten: true,\n };\n }\n log(`${loggingPrefix}: Skipping '${directory}' because no languages were found.\\n`);\n } catch (e) {\n log(`${loggingPrefix}: NOTICE: Skipping '${directory}' due to error: ${e}.\\n`);\n }\n\n return {\n directory,\n isWritten: false,\n };\n}\n\n/**\n * Create main `src/i18n/index.js` messages import file.\n *\n *\n * @param processedDirectories - List of directories with a boolean flag whether its \"index.js\" file is written\n * The format is \"[\\{ directory: \"frontend-component-example\", isWritten: false \\}, ...]\"\n * @param log - Mockable process.stdout.write\n * @param writeFileSync - Mockable fs.writeFileSync\n * @param i18nDir` - Path to `src/i18n` directory\n */\nfunction generateMainMessagesFile({\n processedDirectories,\n log,\n writeFileSync,\n i18nDir,\n}) {\n const importLines = [];\n const exportLines = [];\n\n processedDirectories.forEach(processedDirectory => {\n const { directory, isWritten } = processedDirectory;\n if (isWritten) {\n const moduleCamelCaseVariableName = camelCase(`messages_from_${directory}`);\n importLines.push(`import ${moduleCamelCaseVariableName} from './messages/${directory}';`);\n exportLines.push(` ${moduleCamelCaseVariableName},`);\n } else {\n const skipMessage = `Skipped import due to missing '${directory}/index.js' likely due to empty translations.`;\n importLines.push(`// ${skipMessage}.`);\n log(`${loggingPrefix}: ${skipMessage}\\n`);\n }\n });\n\n // See the help message above for sample output.\n const indexFileContent = [\n filesCodeGeneratorNoticeHeader,\n importLines.join('\\n'),\n '\\nexport default [',\n exportLines.join('\\n'),\n '];\\n',\n ].join('\\n');\n\n writeFileSync(`${i18nDir}/index.js`, indexFileContent);\n}\n\n/*\n * Main function of the file.\n */\nfunction main({\n directories,\n log,\n writeFileSync,\n pwd,\n}) {\n const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory\n\n if (directories.includes('--help') || directories.includes('-h')) {\n log(scriptHelpDocument);\n } else if (!directories.length) {\n log(scriptHelpDocument);\n log(`${loggingPrefix}: Error: A list of directories is required.\\n`);\n } else if (!fs.existsSync(i18nDir) || !fs.lstatSync(i18nDir).isDirectory()) {\n log(scriptHelpDocument);\n log(`${loggingPrefix}: Error: src/i18n directory was not found.\\n`);\n } else {\n const processedDirectories = directories.map(directory => generateSubdirectoryMessageFile({\n directory,\n log,\n writeFileSync,\n i18nDir,\n }));\n generateMainMessagesFile({\n processedDirectories,\n log,\n writeFileSync,\n i18nDir,\n });\n }\n}\n\nif (require.main === module) {\n // Run the main() function if called from the command line.\n main({\n directories: process.argv.slice(2),\n log: text => process.stdout.write(text),\n writeFileSync: fs.writeFileSync,\n pwd: process.env.PWD,\n });\n}\n\nmodule.exports.main = main; // Allow tests to use the main function.\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edx/frontend-platform",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "Foundational application framework for Open edX micro-frontend applications.",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -18,6 +18,7 @@
18
18
  "test:watch": "npm run test -- --watch"
19
19
  },
20
20
  "bin": {
21
+ "intl-imports.js": "i18n/scripts/intl-imports.js",
21
22
  "transifex-utils.js": "i18n/scripts/transifex-utils.js"
22
23
  },
23
24
  "repository": {
@@ -34,7 +35,7 @@
34
35
  "@edx/brand": "npm:@edx/brand-openedx@1.2.0",
35
36
  "@edx/browserslist-config": "1.1.1",
36
37
  "@edx/frontend-build": "12.7.0",
37
- "@edx/paragon": "20.28.5",
38
+ "@edx/paragon": "^20.30.1",
38
39
  "@testing-library/react-hooks": "^8.0.1",
39
40
  "axios-mock-adapter": "^1.21.3",
40
41
  "core-js": "3.29.1",
@@ -75,8 +76,8 @@
75
76
  "peerDependencies": {
76
77
  "@edx/paragon": ">= 10.0.0 < 21.0.0",
77
78
  "prop-types": "^15.7.2",
78
- "react": "^16.9.0",
79
- "react-dom": "^16.9.0",
79
+ "react": "^16.9.0 || ^17.0.0",
80
+ "react-dom": "^16.9.0 || ^17.0.0",
80
81
  "react-redux": "^7.1.1",
81
82
  "react-router-dom": "^5.0.1",
82
83
  "redux": "^4.0.4"