@openedx/frontend-base 1.0.0-alpha.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.
Files changed (356) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +112 -0
  3. package/config/babel/babel.config.js +28 -0
  4. package/config/config-helpers/createConfig.js +13 -0
  5. package/config/config-helpers/createLintConfig.js +16 -0
  6. package/config/config-helpers/getBaseConfig.js +12 -0
  7. package/config/defaultConfigPaths.js +35 -0
  8. package/config/eslint/base.eslint.config.js +113 -0
  9. package/config/index.js +12 -0
  10. package/config/jest/jest.config.js +30 -0
  11. package/config/tsconfig.json +32 -0
  12. package/config/types.js +25 -0
  13. package/config/webpack/common-config/all/getCodeRules.js +52 -0
  14. package/config/webpack/common-config/all/getFileLoaderRules.js +26 -0
  15. package/config/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  16. package/config/webpack/common-config/all/getImageMinimizer.js +25 -0
  17. package/config/webpack/common-config/all/getStylesheetRule.js +112 -0
  18. package/config/webpack/common-config/dev/getDevServer.js +38 -0
  19. package/config/webpack/common-config/index.js +18 -0
  20. package/config/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  21. package/config/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  22. package/config/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  23. package/config/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  24. package/config/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  25. package/config/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  26. package/config/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  27. package/config/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  28. package/config/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  29. package/config/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  30. package/config/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  31. package/config/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  32. package/config/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  33. package/config/webpack/types.js +2 -0
  34. package/config/webpack/utils/getLocalAliases.js +65 -0
  35. package/config/webpack/utils/getPublicPath.js +6 -0
  36. package/config/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  37. package/config/webpack/utils/paragonUtils.js +138 -0
  38. package/config/webpack/webpack.config.build.js +80 -0
  39. package/config/webpack/webpack.config.dev.js +76 -0
  40. package/config/webpack/webpack.config.dev.shell.js +110 -0
  41. package/eslint.config.js +18 -0
  42. package/frontend-base.d.ts +8 -0
  43. package/index.ts +7 -0
  44. package/jest.config.js +7 -0
  45. package/openedx-frontend-base.tgz +0 -0
  46. package/package.json +149 -0
  47. package/runtime/analytics/MockAnalyticsService.js +71 -0
  48. package/runtime/analytics/SegmentAnalyticsService.js +243 -0
  49. package/runtime/analytics/index.ts +12 -0
  50. package/runtime/analytics/interface.js +145 -0
  51. package/runtime/auth/AxiosCsrfTokenService.js +60 -0
  52. package/runtime/auth/AxiosJwtAuthService.js +363 -0
  53. package/runtime/auth/AxiosJwtTokenService.js +134 -0
  54. package/runtime/auth/LocalForageCache.js +76 -0
  55. package/runtime/auth/MockAuthService.js +278 -0
  56. package/runtime/auth/index.ts +19 -0
  57. package/runtime/auth/interceptors/createCsrfTokenProviderInterceptor.js +36 -0
  58. package/runtime/auth/interceptors/createJwtTokenProviderInterceptor.js +37 -0
  59. package/runtime/auth/interceptors/createProcessAxiosRequestErrorInterceptor.js +20 -0
  60. package/runtime/auth/interceptors/createRetryInterceptor.js +74 -0
  61. package/runtime/auth/interface.js +309 -0
  62. package/runtime/auth/utils.js +105 -0
  63. package/runtime/babel.config.js +3 -0
  64. package/runtime/config/index.ts +295 -0
  65. package/runtime/constants.ts +68 -0
  66. package/runtime/i18n/index.js +118 -0
  67. package/runtime/i18n/injectIntlWithShim.jsx +48 -0
  68. package/runtime/i18n/lib.ts +272 -0
  69. package/runtime/index.ts +134 -0
  70. package/runtime/initialize.js +352 -0
  71. package/runtime/jest.config.js +32 -0
  72. package/runtime/logging/MockLoggingService.js +31 -0
  73. package/runtime/logging/NewRelicLoggingService.js +184 -0
  74. package/runtime/logging/index.ts +9 -0
  75. package/runtime/logging/interface.js +109 -0
  76. package/runtime/logging/types.ts +4 -0
  77. package/runtime/react/AuthenticatedPageRoute.jsx +43 -0
  78. package/runtime/react/CombinedAppProvider.tsx +46 -0
  79. package/runtime/react/CurrentAppContext.tsx +25 -0
  80. package/runtime/react/CurrentAppProvider.tsx +46 -0
  81. package/runtime/react/Divider.tsx +5 -0
  82. package/runtime/react/ErrorBoundary.jsx +47 -0
  83. package/runtime/react/ErrorPage.jsx +72 -0
  84. package/runtime/react/LoginRedirect.jsx +16 -0
  85. package/runtime/react/PageWrap.jsx +24 -0
  86. package/runtime/react/SiteContext.tsx +32 -0
  87. package/runtime/react/SiteProvider.tsx +78 -0
  88. package/runtime/react/hooks.ts +106 -0
  89. package/runtime/react/index.ts +19 -0
  90. package/runtime/routing/index.ts +1 -0
  91. package/runtime/routing/utils.ts +34 -0
  92. package/runtime/scripts/GoogleAnalyticsLoader.ts +59 -0
  93. package/runtime/scripts/index.ts +1 -0
  94. package/runtime/setupTest.js +49 -0
  95. package/runtime/slots/Slot.tsx +32 -0
  96. package/runtime/slots/SlotContext.tsx +8 -0
  97. package/runtime/slots/hooks.ts +35 -0
  98. package/runtime/slots/index.ts +7 -0
  99. package/runtime/slots/layout/DefaultSlotLayout.tsx +9 -0
  100. package/runtime/slots/layout/hooks.ts +65 -0
  101. package/runtime/slots/layout/index.ts +5 -0
  102. package/runtime/slots/layout/types.ts +45 -0
  103. package/runtime/slots/layout/utils.ts +14 -0
  104. package/runtime/slots/types.ts +23 -0
  105. package/runtime/slots/utils.ts +59 -0
  106. package/runtime/slots/widget/WidgetContext.tsx +9 -0
  107. package/runtime/slots/widget/WidgetProvider.tsx +30 -0
  108. package/runtime/slots/widget/hooks.ts +105 -0
  109. package/runtime/slots/widget/iframe/IFrameContentWrapper.messages.tsx +16 -0
  110. package/runtime/slots/widget/iframe/IFrameContentWrapper.tsx +84 -0
  111. package/runtime/slots/widget/iframe/IFrameWidget.tsx +59 -0
  112. package/runtime/slots/widget/iframe/constants.ts +19 -0
  113. package/runtime/slots/widget/iframe/hooks.ts +179 -0
  114. package/runtime/slots/widget/iframe/index.ts +6 -0
  115. package/runtime/slots/widget/iframe/types.ts +7 -0
  116. package/runtime/slots/widget/index.ts +6 -0
  117. package/runtime/slots/widget/types.ts +134 -0
  118. package/runtime/slots/widget/utils.tsx +201 -0
  119. package/runtime/subscriptions.ts +60 -0
  120. package/runtime/testing/index.ts +9 -0
  121. package/runtime/testing/initializeMockApp.ts +81 -0
  122. package/runtime/testing/mockMessages.ts +23 -0
  123. package/runtime/utils.js +178 -0
  124. package/shell/DefaultLayout.tsx +18 -0
  125. package/shell/DefaultMain.tsx +7 -0
  126. package/shell/Logo.tsx +28 -0
  127. package/shell/Shell.messages.ts +61 -0
  128. package/shell/Shell.tsx +18 -0
  129. package/shell/app.scss +149 -0
  130. package/shell/app.ts +24 -0
  131. package/shell/babel.config.js +3 -0
  132. package/shell/dev/devFooter/app.tsx +43 -0
  133. package/shell/dev/devFooter/index.ts +1 -0
  134. package/shell/dev/devHeader/BarContext.tsx +13 -0
  135. package/shell/dev/devHeader/BarLink.tsx +16 -0
  136. package/shell/dev/devHeader/BarProvider.tsx +25 -0
  137. package/shell/dev/devHeader/CoursesLink.tsx +16 -0
  138. package/shell/dev/devHeader/FooContext.tsx +13 -0
  139. package/shell/dev/devHeader/FooLink.tsx +16 -0
  140. package/shell/dev/devHeader/FooProvider.tsx +25 -0
  141. package/shell/dev/devHeader/app.tsx +53 -0
  142. package/shell/dev/devHeader/index.ts +1 -0
  143. package/shell/dev/devHeader/providers.tsx +11 -0
  144. package/shell/dev/devHome/HomePage.tsx +28 -0
  145. package/shell/dev/devHome/app.ts +18 -0
  146. package/shell/dev/devHome/i18n/index.ts +27 -0
  147. package/shell/dev/devHome/index.ts +1 -0
  148. package/shell/dev/devHome/messages.ts +11 -0
  149. package/shell/dev/devUser/app.tsx +24 -0
  150. package/shell/dev/devUser/index.ts +1 -0
  151. package/shell/dev/index.ts +5 -0
  152. package/shell/dev/slotShowcase/HorizontalSlotLayout.tsx +11 -0
  153. package/shell/dev/slotShowcase/LayoutWithOptions.tsx +17 -0
  154. package/shell/dev/slotShowcase/SlotShowcasePage.tsx +66 -0
  155. package/shell/dev/slotShowcase/WidgetWithOptions.tsx +11 -0
  156. package/shell/dev/slotShowcase/app.tsx +373 -0
  157. package/shell/dev/slotShowcase/index.ts +1 -0
  158. package/shell/footer/CenterLinks.tsx +11 -0
  159. package/shell/footer/CopyrightNotice.tsx +36 -0
  160. package/shell/footer/Footer.tsx +34 -0
  161. package/shell/footer/LabeledLinkColumn.tsx +19 -0
  162. package/shell/footer/LanguageMenu.tsx +35 -0
  163. package/shell/footer/LanguageMenuItem.tsx +23 -0
  164. package/shell/footer/LeftLinks.tsx +11 -0
  165. package/shell/footer/LegalNotices.tsx +17 -0
  166. package/shell/footer/PoweredBy.tsx +17 -0
  167. package/shell/footer/RevealLinks.tsx +43 -0
  168. package/shell/footer/RightLinks.tsx +11 -0
  169. package/shell/footer/app.tsx +73 -0
  170. package/shell/footer/data/api.ts +48 -0
  171. package/shell/footer/index.ts +2 -0
  172. package/shell/header/AuthenticatedMenu.tsx +32 -0
  173. package/shell/header/Header.tsx +17 -0
  174. package/shell/header/anonymous-menu/AnonymousMenu.tsx +14 -0
  175. package/shell/header/anonymous-menu/LoginButton.tsx +14 -0
  176. package/shell/header/anonymous-menu/RegisterButton.tsx +15 -0
  177. package/shell/header/app.tsx +142 -0
  178. package/shell/header/desktop/DesktopLayout.tsx +22 -0
  179. package/shell/header/desktop/PrimaryNavLinks.tsx +10 -0
  180. package/shell/header/desktop/SecondaryNavLinks.tsx +10 -0
  181. package/shell/header/index.ts +2 -0
  182. package/shell/header/mobile/MobileLayout.tsx +47 -0
  183. package/shell/header/mobile/MobileNavLinks.tsx +10 -0
  184. package/shell/i18n/index.ts +25 -0
  185. package/shell/index.ts +7 -0
  186. package/shell/jest.config.js +30 -0
  187. package/shell/menus/LinkMenuItem.tsx +64 -0
  188. package/shell/menus/NavDropdownMenuSlot.tsx +29 -0
  189. package/shell/menus/ProfileLinkMenuItem.tsx +33 -0
  190. package/shell/menus/data/utils.ts +19 -0
  191. package/shell/public/index.html +10 -0
  192. package/shell/router/createRouter.ts +17 -0
  193. package/shell/router/getAppRoutes.ts +21 -0
  194. package/shell/setupTest.js +48 -0
  195. package/shell/site.config.dev.tsx +49 -0
  196. package/shell/site.tsx +41 -0
  197. package/test-site/app.d.ts +15 -0
  198. package/test-site/dist/176.436443549ebb858db483.js +2 -0
  199. package/test-site/dist/176.436443549ebb858db483.js.map +1 -0
  200. package/test-site/dist/362.536eff787d2380fe246c.js +2 -0
  201. package/test-site/dist/362.536eff787d2380fe246c.js.map +1 -0
  202. package/test-site/dist/653.486966b108d224551296.js +2 -0
  203. package/test-site/dist/653.486966b108d224551296.js.map +1 -0
  204. package/test-site/dist/74e025d3fe9a7b7f8503054e2563b353.jpg +0 -0
  205. package/test-site/dist/806.323cf6496ad0a7fe73a7.js +3 -0
  206. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.LICENSE.txt +106 -0
  207. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.map +1 -0
  208. package/test-site/dist/95ec738c0b7faac5b5c9126794446bbd.svg +4 -0
  209. package/test-site/dist/app.612058b36c74787759ac.css +61 -0
  210. package/test-site/dist/app.612058b36c74787759ac.css.map +1 -0
  211. package/test-site/dist/app.612058b36c74787759ac.js +2 -0
  212. package/test-site/dist/app.612058b36c74787759ac.js.map +1 -0
  213. package/test-site/dist/cb28cdb1468c915e27e5cec9af64f22f.svg +1 -0
  214. package/test-site/dist/index.html +1 -0
  215. package/test-site/dist/report.html +39 -0
  216. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js +2 -0
  217. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js.map +1 -0
  218. package/test-site/eslint.config.js +12 -0
  219. package/test-site/package-lock.json +19226 -0
  220. package/test-site/package.json +29 -0
  221. package/test-site/public/index.html +10 -0
  222. package/test-site/site.config.build.tsx +27 -0
  223. package/test-site/site.config.dev.tsx +27 -0
  224. package/test-site/src/authenticated-page/AuthenticatedPage.tsx +18 -0
  225. package/test-site/src/authenticated-page/i18n/index.ts +27 -0
  226. package/test-site/src/authenticated-page/index.tsx +28 -0
  227. package/test-site/src/example-page/ExamplePage.tsx +79 -0
  228. package/test-site/src/example-page/Image.tsx +11 -0
  229. package/test-site/src/example-page/ParagonPreview.jsx +66 -0
  230. package/test-site/src/example-page/apple.jpg +0 -0
  231. package/test-site/src/example-page/apple.svg +1 -0
  232. package/test-site/src/example-page/index.ts +16 -0
  233. package/test-site/src/i18n/README.md +3 -0
  234. package/test-site/src/i18n/messages/frontend-app-sample/ar.json +4 -0
  235. package/test-site/src/i18n/messages/frontend-app-sample/eo.json +1 -0
  236. package/test-site/src/i18n/messages/frontend-app-sample/es_419.json +4 -0
  237. package/test-site/src/i18n/messages/frontend-component-emptylangs/ar.json +1 -0
  238. package/test-site/src/i18n/messages/frontend-component-singlelang/ar.json +3 -0
  239. package/test-site/src/iframe-widget/IframeWidget.tsx +14 -0
  240. package/test-site/src/iframe-widget/index.ts +16 -0
  241. package/test-site/src/index.tsx +3 -0
  242. package/test-site/src/messages.js +11 -0
  243. package/test-site/src/site.scss +11 -0
  244. package/test-site/tsconfig.json +14 -0
  245. package/tools/babel/babel.config.js +27 -0
  246. package/tools/babel.config.js +3 -0
  247. package/tools/cli/README.md +29 -0
  248. package/tools/cli/commands/pack.ts +9 -0
  249. package/tools/cli/commands/release.ts +27 -0
  250. package/tools/cli/commands/serve.ts +43 -0
  251. package/tools/cli/intl-imports.ts +274 -0
  252. package/tools/cli/openedx.ts +101 -0
  253. package/tools/cli/transifex-utils.ts +75 -0
  254. package/tools/cli/utils/ensureConfigFilenameOption.ts +40 -0
  255. package/tools/cli/utils/formatter.ts +10 -0
  256. package/tools/cli/utils/getResolvedConfigPath.ts +23 -0
  257. package/tools/cli/utils/prettyPrintTitle.ts +15 -0
  258. package/tools/cli/utils/printUsage.ts +53 -0
  259. package/tools/config-helpers/createConfig.ts +8 -0
  260. package/tools/config-helpers/createLintConfig.ts +14 -0
  261. package/tools/config-helpers/getBaseConfig.ts +11 -0
  262. package/tools/defaultConfigPaths.ts +30 -0
  263. package/tools/dist/babel/babel.config.js +28 -0
  264. package/tools/dist/cli/commands/pack.js +14 -0
  265. package/tools/dist/cli/commands/release.js +28 -0
  266. package/tools/dist/cli/commands/serve.js +44 -0
  267. package/tools/dist/cli/intl-imports.js +233 -0
  268. package/tools/dist/cli/openedx.js +100 -0
  269. package/tools/dist/cli/transifex-utils.js +68 -0
  270. package/tools/dist/cli/utils/ensureConfigFilenameOption.js +42 -0
  271. package/tools/dist/cli/utils/formatter.js +10 -0
  272. package/tools/dist/cli/utils/getResolvedConfigPath.js +28 -0
  273. package/tools/dist/cli/utils/prettyPrintTitle.js +17 -0
  274. package/tools/dist/cli/utils/printUsage.js +48 -0
  275. package/tools/dist/config-helpers/createConfig.js +13 -0
  276. package/tools/dist/config-helpers/createLintConfig.js +16 -0
  277. package/tools/dist/config-helpers/getBaseConfig.js +12 -0
  278. package/tools/dist/defaultConfigPaths.js +35 -0
  279. package/tools/dist/eslint/base.eslint.config.js +113 -0
  280. package/tools/dist/eslint.config.js +11 -0
  281. package/tools/dist/index.js +12 -0
  282. package/tools/dist/jest/jest.config.js +30 -0
  283. package/tools/dist/jest.config.js +20 -0
  284. package/tools/dist/types.js +25 -0
  285. package/tools/dist/typescript/tsconfig.json +32 -0
  286. package/tools/dist/webpack/common-config/all/getCodeRules.js +52 -0
  287. package/tools/dist/webpack/common-config/all/getFileLoaderRules.js +26 -0
  288. package/tools/dist/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  289. package/tools/dist/webpack/common-config/all/getImageMinimizer.js +25 -0
  290. package/tools/dist/webpack/common-config/all/getStylesheetRule.js +112 -0
  291. package/tools/dist/webpack/common-config/dev/getDevServer.js +38 -0
  292. package/tools/dist/webpack/common-config/index.js +18 -0
  293. package/tools/dist/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  294. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  295. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  296. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  297. package/tools/dist/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  298. package/tools/dist/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  299. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  300. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  301. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  302. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  303. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  304. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  305. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  306. package/tools/dist/webpack/types.js +2 -0
  307. package/tools/dist/webpack/utils/getLocalAliases.js +65 -0
  308. package/tools/dist/webpack/utils/getPublicPath.js +6 -0
  309. package/tools/dist/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  310. package/tools/dist/webpack/utils/paragonUtils.js +138 -0
  311. package/tools/dist/webpack/webpack.config.build.js +80 -0
  312. package/tools/dist/webpack/webpack.config.dev.js +76 -0
  313. package/tools/dist/webpack/webpack.config.dev.shell.js +110 -0
  314. package/tools/eslint/base.eslint.config.js +124 -0
  315. package/tools/eslint/modules.d.ts +5 -0
  316. package/tools/eslint.config.js +15 -0
  317. package/tools/index.ts +3 -0
  318. package/tools/jest/jest.config.js +30 -0
  319. package/tools/jest.config.js +19 -0
  320. package/tools/tsconfig.json +24 -0
  321. package/tools/types.ts +21 -0
  322. package/tools/typescript/tsconfig.json +32 -0
  323. package/tools/webpack/common-config/README.md +15 -0
  324. package/tools/webpack/common-config/all/getCodeRules.ts +51 -0
  325. package/tools/webpack/common-config/all/getFileLoaderRules.ts +23 -0
  326. package/tools/webpack/common-config/all/getIgnoreWarnings.ts +13 -0
  327. package/tools/webpack/common-config/all/getImageMinimizer.ts +26 -0
  328. package/tools/webpack/common-config/all/getStylesheetRule.ts +111 -0
  329. package/tools/webpack/common-config/dev/getDevServer.ts +35 -0
  330. package/tools/webpack/common-config/index.ts +6 -0
  331. package/tools/webpack/common-config/site/getHtmlWebpackPlugin.ts +11 -0
  332. package/tools/webpack/modules.d.ts +6 -0
  333. package/tools/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.ts +102 -0
  334. package/tools/webpack/plugins/html-webpack-new-relic-plugin/LICENSE +21 -0
  335. package/tools/webpack/plugins/html-webpack-new-relic-plugin/README.md +7 -0
  336. package/tools/webpack/plugins/html-webpack-new-relic-plugin/index.js +3 -0
  337. package/tools/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +1 -0
  338. package/tools/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.ts +134 -0
  339. package/tools/webpack/plugins/paragon-webpack-plugin/index.ts +3 -0
  340. package/tools/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.ts +71 -0
  341. package/tools/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.ts +72 -0
  342. package/tools/webpack/plugins/paragon-webpack-plugin/utils/index.ts +6 -0
  343. package/tools/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.ts +131 -0
  344. package/tools/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.ts +144 -0
  345. package/tools/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.ts +106 -0
  346. package/tools/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.ts +54 -0
  347. package/tools/webpack/types.ts +69 -0
  348. package/tools/webpack/utils/getLocalAliases.ts +65 -0
  349. package/tools/webpack/utils/getPublicPath.ts +3 -0
  350. package/tools/webpack/utils/getResolvedSiteConfigPath.ts +28 -0
  351. package/tools/webpack/utils/paragonUtils.ts +152 -0
  352. package/tools/webpack/webpack.config.build.ts +93 -0
  353. package/tools/webpack/webpack.config.dev.shell.ts +122 -0
  354. package/tools/webpack/webpack.config.dev.ts +90 -0
  355. package/tsconfig.json +23 -0
  356. package/types.ts +99 -0
@@ -0,0 +1,68 @@
1
+ /** @constant */
2
+ export const SITE_TOPIC = 'APP';
3
+
4
+ export const SITE_PUBSUB_INITIALIZED = `${SITE_TOPIC}.PUBSUB_INITIALIZED`;
5
+
6
+ /**
7
+ * Event published when the application initialization sequence has finished loading any dynamic
8
+ * configuration setup in a custom config handler.
9
+ *
10
+ * @event
11
+ */
12
+ export const SITE_CONFIG_INITIALIZED = `${SITE_TOPIC}.CONFIG_INITIALIZED`;
13
+
14
+ /**
15
+ * Event published when the application initialization sequence has finished determining the user's
16
+ * authentication state, creating an authenticated API client, and executing auth handlers.
17
+ *
18
+ * @event
19
+ */
20
+ export const SITE_AUTH_INITIALIZED = `${SITE_TOPIC}.AUTH_INITIALIZED`;
21
+
22
+ /**
23
+ * Event published when the application initialization sequence has finished initializing
24
+ * internationalization and executing any i18n handlers.
25
+ *
26
+ * @event
27
+ */
28
+ export const SITE_I18N_INITIALIZED = `${SITE_TOPIC}.I18N_INITIALIZED`;
29
+
30
+ /**
31
+ * Event published when the application initialization sequence has finished initializing the
32
+ * logging service and executing any logging handlers.
33
+ *
34
+ * @event
35
+ */
36
+ export const SITE_LOGGING_INITIALIZED = `${SITE_TOPIC}.LOGGING_INITIALIZED`;
37
+
38
+ /**
39
+ * Event published when the application initialization sequence has finished initializing the
40
+ * analytics service and executing any analytics handlers.
41
+ *
42
+ * @event
43
+ */
44
+ export const SITE_ANALYTICS_INITIALIZED = `${SITE_TOPIC}.ANALYTICS_INITIALIZED`;
45
+
46
+ /**
47
+ * Event published when the application initialization sequence has finished. Applications should
48
+ * subscribe to this event and start rendering the UI when it has fired.
49
+ *
50
+ * @event
51
+ */
52
+ export const SITE_READY = `${SITE_TOPIC}.READY`;
53
+
54
+ /**
55
+ * Event published when the application initialization sequence has aborted. This is frequently
56
+ * used to show an error page when an initialization error has occurred.
57
+ *
58
+ * @see {@link module:React~ErrorPage}
59
+ * @event
60
+ */
61
+ export const SITE_INIT_ERROR = `${SITE_TOPIC}.INIT_ERROR`;
62
+
63
+ /** @constant */
64
+ export const CONFIG_TOPIC = 'CONFIG';
65
+
66
+ export const CONFIG_CHANGED = `${CONFIG_TOPIC}.CHANGED`;
67
+
68
+ export const ACTIVE_ROLES_CHANGED = 'ACTIVE_ROLES_CHANGED';
@@ -0,0 +1,118 @@
1
+ /**
2
+ * #### Import members from **@openedx/frontend-base**
3
+ * The i18n module relies on react-intl and re-exports all of that package's exports.
4
+ *
5
+ * For each locale we want to support, react-intl needs 1) the locale-data, which includes
6
+ * information about how to format numbers, handle plurals, etc., and 2) the translations, as an
7
+ * object holding message id / translated string pairs. A locale string and the messages object are
8
+ * passed into the IntlProvider element that wraps your element hierarchy.
9
+ *
10
+ * Note that react-intl has no way of checking if the translations you give it actually have
11
+ * anything to do with the locale you pass it; it will happily use whatever messages object you pass
12
+ * in. However, if the locale data for the locale you passed into the IntlProvider was not
13
+ * correctly installed with addLocaleData, all of your translations will fall back to the default
14
+ * (in our case English), *even if you gave IntlProvider the correct messages object for that
15
+ * locale*.
16
+ *
17
+ * Messages are provided to this module via the configureI18n() function below.
18
+ *
19
+ *
20
+ * @module Internationalization
21
+ * @see {@link https://github.com/openedx/frontend-base/blob/master/docs/how_tos/i18n.rst}
22
+ * @see {@link https://formatjs.io/docs/react-intl/components/ Intl} for components exported from this module.
23
+ *
24
+ */
25
+
26
+ /**
27
+ * @name createIntl
28
+ * @kind function
29
+ * @see {@link https://formatjs.io/docs/react-intl/api#createIntl Intl}
30
+ */
31
+
32
+ /**
33
+ * @name FormattedDate
34
+ * @kind class
35
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formatteddate Intl}
36
+ */
37
+
38
+ /**
39
+ * @name FormattedTime
40
+ * @kind class
41
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formattedtime Intl}
42
+ */
43
+
44
+ /**
45
+ * @name FormattedRelativeTime
46
+ * @kind class
47
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formattedrelativetime Intl}
48
+ */
49
+
50
+ /**
51
+ * @name FormattedNumber
52
+ * @kind class
53
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formattednumber Intl}
54
+ */
55
+
56
+ /**
57
+ * @name FormattedPlural
58
+ * @kind class
59
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formattedplural Intl}
60
+ */
61
+
62
+ /**
63
+ * @name FormattedMessage
64
+ * @kind class
65
+ * @see {@link https://formatjs.io/docs/react-intl/components/#formattedmessage Intl}
66
+ */
67
+
68
+ /**
69
+ * @name IntlProvider
70
+ * @kind class
71
+ * @see {@link https://formatjs.io/docs/react-intl/components/#intlprovider Intl}
72
+ */
73
+
74
+ /**
75
+ * @name defineMessages
76
+ * @kind function
77
+ * @see {@link https://formatjs.io/docs/react-intl/api#definemessagesdefinemessage Intl}
78
+ */
79
+
80
+ /**
81
+ * @name useIntl
82
+ * @kind function
83
+ * @see {@link https://formatjs.io/docs/react-intl/api#useIntl Intl}
84
+ */
85
+
86
+ export {
87
+ createIntl,
88
+ defineMessages,
89
+ FormattedDate,
90
+ FormattedMessage,
91
+ FormattedNumber,
92
+ FormattedPlural,
93
+ FormattedRelativeTime,
94
+ FormattedTime,
95
+ IntlProvider,
96
+ useIntl
97
+ } from 'react-intl';
98
+
99
+ export {
100
+ addAppMessages,
101
+ configureI18n,
102
+ getLocale,
103
+ getLocalizedLanguageName,
104
+ getMessages,
105
+ getPrimaryLanguageSubtag,
106
+ getSupportedLanguageList,
107
+ handleRtl,
108
+ intlShape,
109
+ isRtl,
110
+ LOCALE_CHANGED,
111
+ LOCALE_TOPIC,
112
+ mergeMessages,
113
+ updateLocale
114
+ } from './lib';
115
+
116
+ export {
117
+ default as injectIntl
118
+ } from './injectIntlWithShim';
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { injectIntl } from 'react-intl';
3
+ import { EnvironmentTypes } from '../../types';
4
+ import { getSiteConfig } from '../config';
5
+ import { getLoggingService } from '../logging';
6
+ import { intlShape } from './lib';
7
+
8
+ /**
9
+ * This function wraps react-intl's injectIntl function in order to add error logging to the intl
10
+ * property's formatMessage function.
11
+ *
12
+ * @memberof I18n
13
+ */
14
+ const injectIntlWithShim = (WrappedComponent) => {
15
+ class ShimmedIntlComponent extends React.Component {
16
+ constructor(props) {
17
+ super(props);
18
+ this.shimmedIntl = Object.create(this.props.intl, {
19
+ formatMessage: {
20
+ value: (definition, ...args) => {
21
+ if (definition === undefined || definition.id === undefined) {
22
+ const error = new Error('i18n error: An undefined message was supplied to intl.formatMessage.');
23
+ if (getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT) {
24
+ console.error(error); // eslint-disable-line no-console
25
+ return '!!! Missing message supplied to intl.formatMessage !!!';
26
+ }
27
+ getLoggingService().logError(error);
28
+ return ''; // Fail silently in production
29
+ }
30
+ return this.props.intl.formatMessage(definition, ...args);
31
+ },
32
+ },
33
+ });
34
+ }
35
+
36
+ render() {
37
+ return <WrappedComponent {...this.props} intl={this.shimmedIntl} />;
38
+ }
39
+ }
40
+
41
+ ShimmedIntlComponent.propTypes = {
42
+ intl: intlShape.isRequired,
43
+ };
44
+
45
+ return injectIntl(ShimmedIntlComponent);
46
+ };
47
+
48
+ export default injectIntlWithShim;
@@ -0,0 +1,272 @@
1
+ import merge from 'lodash.merge';
2
+ import PropTypes from 'prop-types';
3
+ import { MessageFormatElement } from 'react-intl';
4
+ import Cookies from 'universal-cookie';
5
+
6
+ import { LocalizedMessages } from '../../types';
7
+ import { getSiteConfig } from '../config';
8
+ import { publish } from '../subscriptions';
9
+
10
+ const cookies = new Cookies();
11
+
12
+ // This list is based on https://help.smartling.com/hc/en-us/articles/1260802028830-Right-to-left-RTL-Languages
13
+ // There are very few resources available online outlining the locale codes for RTL languages;
14
+ // If this list is inaccurate, we should change it.
15
+ const rtlLocales = [
16
+ 'ar', // Arabic (International)
17
+ 'ar-ae', // Arabic (United Arab Emirates)
18
+ 'ar-bh', // Arabic (Bahrain)
19
+ 'ar-dj', // Arabic (Djibouti)
20
+ 'ar-dz', // Arabic (Algeria)
21
+ 'ar-eg', // Arabic (Egypt)
22
+ 'ar-iq', // Arabic (Iraq)
23
+ 'ar-jo', // Arabic (Jordan)
24
+ 'ar-kw', // Arabic (Kuwait)
25
+ 'ar-lb', // Arabic (Lebanon)
26
+ 'ar-ly', // Arabic (Libya)
27
+ 'ar-ma', // Arabic (Morocco)
28
+ 'ar-om', // Arabic (Oman)
29
+ 'ar-qa', // Arabic (Qatar)
30
+ 'ar-sa', // Arabic (Saudi Arabia)
31
+ 'ar-sd', // Arabic (Sudan)
32
+ 'ar-sy', // Arabic (Syria)
33
+ 'ar-tn', // Arabic (Tunisia)
34
+ 'ar-ye', // Arabic (Yemen)
35
+ 'fa', // Persian
36
+ 'fa-af', // Dari/Persian (Afghanistan)
37
+ 'fa-ir', // Persian (Iran)
38
+ 'he', // Hebrew (he)
39
+ 'he-il', // Hebrew
40
+ 'iw', // Hebrew (iw)
41
+ 'kd', // Kurdish (Sorani) RTL
42
+ 'pk-pk', // Panjabi-Shahmuki (Pakistan)
43
+ 'ps', // Pushto; Pashto
44
+ 'ug', // Uighur; Uyghur
45
+ 'ur', // Urdu
46
+ 'ur-in', // Urdu (India)
47
+ 'ur-pk', // Urdu (Pakistan)
48
+ 'yi', // Yiddish
49
+ 'yi-us', // Yiddish (United States)
50
+ ];
51
+
52
+ let messages: Record<string, Record<string, string> | Record<string, MessageFormatElement[]> | undefined>;
53
+
54
+ /**
55
+ * @memberof module:Internationalization
56
+ *
57
+ * Prior versions of react-intl (our primary implementation of the i18n service) included a
58
+ * PropTypes-based 'shape' for its `intl` object. This has since been removed. For legacy
59
+ * compatibility, we include an `intlShape` export that is set to PropTypes.object. Usage of this
60
+ * export is deprecated.
61
+ *
62
+ * @deprecated
63
+ */
64
+ export const intlShape = PropTypes.object;
65
+
66
+ /**
67
+ * @memberof module:Internationalization
68
+ */
69
+ export const LOCALE_TOPIC = 'LOCALE';
70
+
71
+ /**
72
+ * @memberof module:Internationalization
73
+ */
74
+ export const LOCALE_CHANGED = `${LOCALE_TOPIC}.CHANGED`;
75
+
76
+ /**
77
+ *
78
+ * @memberof module:Internationalization
79
+ * @returns {Cookies}
80
+ */
81
+ export function getCookies() {
82
+ return cookies;
83
+ }
84
+
85
+ /**
86
+ * Some of our dependencies function on primary language subtags, rather than full locales.
87
+ * This function strips a locale down to that first subtag. Depending on the code, this
88
+ * may be 2 or more characters.
89
+ *
90
+ * @param {string} code
91
+ * @memberof module:Internationalization
92
+ */
93
+ export function getPrimaryLanguageSubtag(code) {
94
+ return code.split('-')[0];
95
+ }
96
+
97
+ /**
98
+ * Finds the closest supported locale to the one provided. This is done in three steps:
99
+ *
100
+ * 1. Returning the locale itself if its exact language code is supported.
101
+ * 2. Returning the primary language subtag of the language code if it is supported (ar for ar-eg,
102
+ * for instance).
103
+ * 3. Returning 'en' if neither of the above produce a supported locale.
104
+ *
105
+ * @param {string} locale
106
+ * @returns {string}
107
+ * @memberof module:Internationalization
108
+ */
109
+ export function findSupportedLocale(locale) {
110
+ if (messages === undefined) {
111
+ throw new Error('findSupportedLocale called before configuring i18n. Call configureI18n with messages first.');
112
+ }
113
+
114
+ if (messages[locale] !== undefined) {
115
+ return locale;
116
+ }
117
+
118
+ if (messages[getPrimaryLanguageSubtag(locale)] !== undefined) {
119
+ return getPrimaryLanguageSubtag(locale);
120
+ }
121
+
122
+ return 'en';
123
+ }
124
+
125
+ /**
126
+ * Get the locale from the cookie or, failing that, the browser setting.
127
+ * Gracefully fall back to a more general primary language subtag or to English (en)
128
+ * if we don't support that language.
129
+ *
130
+ * @param {string|undefined} locale If a locale is provided, returns the closest supported locale. Optional.
131
+ * @throws An error if i18n has not yet been configured.
132
+ * @returns {string}
133
+ * @memberof module:Internationalization
134
+ */
135
+ export function getLocale(locale?: string) {
136
+ if (messages === null) {
137
+ throw new Error('getLocale called before configuring i18n. Call configureI18n with messages first.');
138
+ }
139
+
140
+ // 1. Explicit application request
141
+ if (locale !== undefined) {
142
+ return findSupportedLocale(locale);
143
+ }
144
+ // 2. User setting in cookie
145
+
146
+ const { languagePreferenceCookieName } = getSiteConfig();
147
+ if (languagePreferenceCookieName) {
148
+ const languagePreference = cookies.get(languagePreferenceCookieName);
149
+ if (languagePreference) {
150
+ return findSupportedLocale(languagePreference.toLowerCase());
151
+ }
152
+ }
153
+
154
+ // 3. Browser language (default)
155
+ // Note that some browers prefer upper case for the region part of the locale, while others don't.
156
+ // Thus the toLowerCase, for consistency.
157
+ // https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language
158
+ return findSupportedLocale(globalThis.navigator.language.toLowerCase());
159
+ }
160
+
161
+ export function getLocalizedLanguageName(locale) {
162
+ const localizedName = (new Intl.DisplayNames([locale], { type: 'language' })).of(locale);
163
+
164
+ if (localizedName === undefined) {
165
+ throw new Error(`Unsupported locale: ${locale}`);
166
+ }
167
+
168
+ return `${localizedName.charAt(0).toLocaleUpperCase(locale)}${localizedName.slice(1)}`;
169
+ }
170
+
171
+ export function getSupportedLanguageList() {
172
+ const locales = Object.keys(messages);
173
+ locales.push('en'); // 'en' is not in the messages object because it's the default.
174
+ locales.sort();
175
+
176
+ return locales.map((locale) => ({
177
+ code: locale,
178
+ name: getLocalizedLanguageName(locale),
179
+ }));
180
+ }
181
+
182
+ export function updateLocale() {
183
+ handleRtl();
184
+ publish(LOCALE_CHANGED);
185
+ }
186
+
187
+ /**
188
+ * Returns messages for the provided locale, or the user's preferred locale if no argument is
189
+ * provided.
190
+ *
191
+ * @param {string} [locale=getLocale()]
192
+ * @memberof module:Internationalization
193
+ */
194
+ export function getMessages(locale = getLocale()) {
195
+ if (messages === undefined) {
196
+ throw new Error('getMessages called before configuring i18n. Call configureI18n with messages first.');
197
+ }
198
+
199
+ return messages[locale];
200
+ }
201
+
202
+ /**
203
+ * Determines if the provided locale is a right-to-left language.
204
+ *
205
+ * @param {string} locale
206
+ * @memberof module:Internationalization
207
+ */
208
+ export function isRtl(locale) {
209
+ return rtlLocales.includes(locale);
210
+ }
211
+
212
+ /**
213
+ * Handles applying the RTL stylesheet and "dir=rtl" attribute to the html tag if the current locale
214
+ * is a RTL language.
215
+ *
216
+ * @memberof module:Internationalization
217
+ */
218
+ export function handleRtl() {
219
+ if (isRtl(getLocale())) {
220
+ globalThis.document.getElementsByTagName('html')[0].setAttribute('dir', 'rtl');
221
+ } else {
222
+ globalThis.document.getElementsByTagName('html')[0].setAttribute('dir', 'ltr');
223
+ }
224
+ }
225
+
226
+ /**
227
+ *
228
+ *
229
+ * @param {Object} newMessages
230
+ * @returns {Object}
231
+ * @memberof module:Internationalization
232
+ */
233
+ export function mergeMessages(newMessages = {}) {
234
+ const msgs = Array.isArray(newMessages) ? merge({}, ...newMessages) : newMessages;
235
+ messages = merge(messages, msgs);
236
+
237
+ return messages;
238
+ }
239
+
240
+ /**
241
+ * Adds all the messages found in the loaded apps.
242
+ *
243
+ * @memberof module:Internationalization
244
+ */
245
+ export function addAppMessages() {
246
+ const { apps } = getSiteConfig();
247
+ if (apps) {
248
+ apps.forEach((app) => {
249
+ mergeMessages(app.messages);
250
+ });
251
+ }
252
+ }
253
+
254
+ interface ConfigureI18nOptions {
255
+ messages: LocalizedMessages[] | LocalizedMessages,
256
+ }
257
+
258
+ /**
259
+ * Configures the i18n library with messages for your application.
260
+ *
261
+ * Logs a warning if it detects a locale it doesn't expect (as defined by the supportedLocales list
262
+ * above), or if an expected locale is not provided.
263
+ *
264
+ * @param {Object} options
265
+ * @param {Object} options.messages
266
+ * @memberof module:Internationalization
267
+ */
268
+ export function configureI18n(options: ConfigureI18nOptions) {
269
+ messages = Array.isArray(options.messages) ? merge({}, ...options.messages) : options.messages;
270
+
271
+ handleRtl();
272
+ }
@@ -0,0 +1,134 @@
1
+ export {
2
+ configureAnalytics,
3
+ getAnalyticsService,
4
+ identifyAnonymousUser,
5
+ identifyAuthenticatedUser,
6
+ MockAnalyticsService,
7
+ resetAnalyticsService,
8
+ SegmentAnalyticsService,
9
+ sendPageEvent,
10
+ sendTrackEvent,
11
+ sendTrackingLogEvent
12
+ } from './analytics';
13
+
14
+ export {
15
+ AUTHENTICATED_USER_CHANGED,
16
+ AUTHENTICATED_USER_TOPIC,
17
+ AxiosJwtAuthService,
18
+ configureAuth,
19
+ ensureAuthenticatedUser,
20
+ fetchAuthenticatedUser,
21
+ getAuthenticatedHttpClient,
22
+ getAuthenticatedUser,
23
+ getAuthService,
24
+ getHttpClient,
25
+ getLoginRedirectUrl,
26
+ getLogoutRedirectUrl,
27
+ hydrateAuthenticatedUser,
28
+ MockAuthService,
29
+ redirectToLogin,
30
+ redirectToLogout,
31
+ setAuthenticatedUser
32
+ } from './auth';
33
+
34
+ export {
35
+ getSiteConfig,
36
+ setSiteConfig,
37
+ mergeSiteConfig,
38
+ addAppConfigs,
39
+ getAppConfig,
40
+ mergeAppConfig,
41
+ setActiveRouteRoles,
42
+ getActiveRouteRoles,
43
+ addActiveWidgetRole,
44
+ removeActiveWidgetRole,
45
+ getActiveWidgetRoles,
46
+ getActiveRoles,
47
+ getExternalLinkUrl
48
+ } from './config';
49
+
50
+ export * from './constants';
51
+
52
+ export {
53
+ configureI18n,
54
+ createIntl,
55
+ defineMessages,
56
+ FormattedDate,
57
+ FormattedMessage,
58
+ FormattedNumber,
59
+ FormattedPlural,
60
+ FormattedRelativeTime,
61
+ FormattedTime,
62
+ getLocale,
63
+ getLocalizedLanguageName,
64
+ getMessages,
65
+ getPrimaryLanguageSubtag,
66
+ getSupportedLanguageList,
67
+ handleRtl,
68
+ injectIntl,
69
+ IntlProvider,
70
+ intlShape,
71
+ isRtl,
72
+ LOCALE_CHANGED,
73
+ LOCALE_TOPIC,
74
+ mergeMessages,
75
+ updateLocale,
76
+ useIntl
77
+ } from './i18n';
78
+
79
+ export {
80
+ auth,
81
+ getBasename,
82
+ initError,
83
+ initialize
84
+ } from './initialize';
85
+
86
+ export {
87
+ configureLogging,
88
+ getLoggingService,
89
+ logError,
90
+ logInfo,
91
+ MockLoggingService,
92
+ NewRelicLoggingService,
93
+ resetLoggingService
94
+ } from './logging';
95
+
96
+ export {
97
+ CurrentAppContext,
98
+ CurrentAppProvider,
99
+ SiteContext,
100
+ SiteProvider,
101
+ AuthenticatedPageRoute,
102
+ Divider,
103
+ ErrorBoundary,
104
+ ErrorPage,
105
+ LoginRedirect,
106
+ PageWrap,
107
+ useSiteEvent,
108
+ useAuthenticatedUser,
109
+ useSiteConfig,
110
+ useAppConfig
111
+ } from './react';
112
+
113
+ export {
114
+ clearAllSubscriptions,
115
+ publish,
116
+ subscribe,
117
+ unsubscribe
118
+ } from './subscriptions';
119
+
120
+ export {
121
+ initializeMockApp,
122
+ mockMessages
123
+ } from './testing';
124
+
125
+ export {
126
+ camelCaseObject,
127
+ convertKeyNames,
128
+ getQueryParameters,
129
+ isValidVariableName,
130
+ modifyObjectKeys,
131
+ snakeCaseObject
132
+ } from './utils';
133
+
134
+ export * from './slots';