@madgex/fert 1.3.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 (120) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +15 -0
  3. package/.github/workflows/commits.yml +14 -0
  4. package/.github/workflows/release.yml +29 -0
  5. package/.husky/commit-msg +4 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.prettierignore +2 -0
  8. package/.prettierrc.js +8 -0
  9. package/README.md +232 -0
  10. package/bin/cli.js +68 -0
  11. package/bin/commands/build-tasks/build-external-assets.js +16 -0
  12. package/bin/commands/build-tasks/build-tokens.js +119 -0
  13. package/bin/commands/build-tasks/bundle-ds-css.js +74 -0
  14. package/bin/commands/build-tasks/bundle-entry.js +43 -0
  15. package/bin/commands/build.js +42 -0
  16. package/bin/commands/dev-server.js +50 -0
  17. package/bin/commands/init.js +207 -0
  18. package/bin/commands/publish-tasks/asset-store-uploader.js +94 -0
  19. package/bin/commands/publish-tasks/get-aws-parameter.js +41 -0
  20. package/bin/commands/publish.js +51 -0
  21. package/bin/utils/cpid-lookup.js +47 -0
  22. package/bin/utils/index.js +121 -0
  23. package/bin/utils/resolve-external-assets.js +77 -0
  24. package/commitlint.config.cjs +1 -0
  25. package/constants.js +36 -0
  26. package/delivery/git.cer +22 -0
  27. package/delivery/jenkinsfile +93 -0
  28. package/package.json +84 -0
  29. package/repo-templates/globals/fert.config.js +4 -0
  30. package/repo-templates/globals/jenkinsfile +4 -0
  31. package/repo-templates/template-basic/_gitignore +5 -0
  32. package/repo-templates/template-basic/brand.json +21 -0
  33. package/repo-templates/template-basic/package.json +13 -0
  34. package/repo-templates/template-basic/public/favicon.ico +0 -0
  35. package/repo-templates/template-basic/public/fonts/mdgx-icons.eot +0 -0
  36. package/repo-templates/template-basic/public/fonts/mdgx-icons.svg +71 -0
  37. package/repo-templates/template-basic/public/fonts/mdgx-icons.ttf +0 -0
  38. package/repo-templates/template-basic/public/fonts/mdgx-icons.woff +0 -0
  39. package/repo-templates/template-basic/public/fonts/my-font.woff +1 -0
  40. package/repo-templates/template-basic/public/images/logo.png +0 -0
  41. package/repo-templates/template-basic/src/css/styles.scss +12 -0
  42. package/repo-templates/template-basic/src/index.js +3 -0
  43. package/repo-templates/template-basic/templates/footer.njk +14 -0
  44. package/repo-templates/template-basic/templates/header.njk +14 -0
  45. package/repo-templates/template-bigworkbag/_gitignore +5 -0
  46. package/repo-templates/template-bigworkbag/brand.json +21 -0
  47. package/repo-templates/template-bigworkbag/package.json +13 -0
  48. package/repo-templates/template-bigworkbag/public/favicon.ico +0 -0
  49. package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.eot +0 -0
  50. package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.svg +71 -0
  51. package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.ttf +0 -0
  52. package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.woff +0 -0
  53. package/repo-templates/template-bigworkbag/public/fonts/my-font.woff +1 -0
  54. package/repo-templates/template-bigworkbag/public/images/logo.png +0 -0
  55. package/repo-templates/template-bigworkbag/public/images/user-menu-pointer.svg +4 -0
  56. package/repo-templates/template-bigworkbag/src/css/breakpoints.scss +17 -0
  57. package/repo-templates/template-bigworkbag/src/css/clicky-menu.scss +52 -0
  58. package/repo-templates/template-bigworkbag/src/css/desktop-main-nav.scss +25 -0
  59. package/repo-templates/template-bigworkbag/src/css/desktop-user-nav.scss +127 -0
  60. package/repo-templates/template-bigworkbag/src/css/footer.scss +77 -0
  61. package/repo-templates/template-bigworkbag/src/css/header-top.scss +29 -0
  62. package/repo-templates/template-bigworkbag/src/css/leaderboard-ad.scss +22 -0
  63. package/repo-templates/template-bigworkbag/src/css/mobile-main-nav.scss +68 -0
  64. package/repo-templates/template-bigworkbag/src/css/mobile-user-nav.scss +49 -0
  65. package/repo-templates/template-bigworkbag/src/css/reset.scss +91 -0
  66. package/repo-templates/template-bigworkbag/src/css/styles.scss +19 -0
  67. package/repo-templates/template-bigworkbag/src/css/top-bar.scss +13 -0
  68. package/repo-templates/template-bigworkbag/src/css/typography.scss +20 -0
  69. package/repo-templates/template-bigworkbag/src/css/util.scss +28 -0
  70. package/repo-templates/template-bigworkbag/src/css/variables.scss +9 -0
  71. package/repo-templates/template-bigworkbag/src/index.js +3 -0
  72. package/repo-templates/template-bigworkbag/src/js/clicky-menus.js +178 -0
  73. package/repo-templates/template-bigworkbag/src/js/no-js.js +10 -0
  74. package/repo-templates/template-bigworkbag/templates/context/footer-nav.njk +27 -0
  75. package/repo-templates/template-bigworkbag/templates/context/main-nav.njk +32 -0
  76. package/repo-templates/template-bigworkbag/templates/context/user-nav.njk +17 -0
  77. package/repo-templates/template-bigworkbag/templates/footer.njk +68 -0
  78. package/repo-templates/template-bigworkbag/templates/header.njk +54 -0
  79. package/repo-templates/template-bigworkbag/templates/includes/desktop-main-nav-items.njk +18 -0
  80. package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/loggedin-items.njk +28 -0
  81. package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/loggedout-items.njk +9 -0
  82. package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/submenu-items.njk +18 -0
  83. package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/user-nav.njk +24 -0
  84. package/repo-templates/template-bigworkbag/templates/includes/dev-console-context.njk +7 -0
  85. package/repo-templates/template-bigworkbag/templates/includes/mobile-main-nav-items.njk +25 -0
  86. package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/loggedin-items.njk +33 -0
  87. package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/loggedout-items.njk +16 -0
  88. package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/user-nav.njk +24 -0
  89. package/repo-templates/template-bigworkbag/templates/svgs/arrow-down.svg +3 -0
  90. package/repo-templates/template-bigworkbag/templates/svgs/arrow-left.svg +3 -0
  91. package/repo-templates/template-bigworkbag/templates/svgs/arrow-right.svg +3 -0
  92. package/repo-templates/template-bigworkbag/templates/svgs/arrow-up.svg +3 -0
  93. package/repo-templates/template-bigworkbag/templates/svgs/cart.svg +3 -0
  94. package/repo-templates/template-bigworkbag/templates/svgs/facebook.svg +3 -0
  95. package/repo-templates/template-bigworkbag/templates/svgs/linkedin.svg +3 -0
  96. package/repo-templates/template-bigworkbag/templates/svgs/profile.svg +5 -0
  97. package/repo-templates/template-bigworkbag/templates/svgs/star-filled.svg +3 -0
  98. package/repo-templates/template-bigworkbag/templates/svgs/star-outline.svg +3 -0
  99. package/repo-templates/template-bigworkbag/templates/svgs/twitter.svg +3 -0
  100. package/repo-templates/template-bigworkbag/templates/svgs/youtube.svg +3 -0
  101. package/repo-templates/template-bigworkbag/templates/translations/da.njk +26 -0
  102. package/repo-templates/template-bigworkbag/templates/translations/de.njk +26 -0
  103. package/repo-templates/template-bigworkbag/templates/translations/en.njk +26 -0
  104. package/repo-templates/template-bigworkbag/templates/translations/es.njk +26 -0
  105. package/repo-templates/template-bigworkbag/templates/translations/fr.njk +26 -0
  106. package/repo-templates/template-bigworkbag/templates/translations/nb.njk +26 -0
  107. package/repo-templates/template-bigworkbag/templates/translations/nl.njk +26 -0
  108. package/repo-templates/template-bigworkbag/templates/translations/sv.njk +26 -0
  109. package/repo-templates/template-bigworkbag/templates/translations/zh-cn.njk +26 -0
  110. package/server/extensions/error-logging.js +25 -0
  111. package/server/index.js +98 -0
  112. package/server/plugins/hapi-vite.js +61 -0
  113. package/server/routes/public.js +29 -0
  114. package/server/routes/views.js +46 -0
  115. package/server/templates/furniture.njk +67 -0
  116. package/server/templates/page1.njk +37 -0
  117. package/server/view-manager.js +59 -0
  118. package/shared/Dockerfile.brandingRepoPublish +28 -0
  119. package/shared/README.md +4 -0
  120. package/vite.config.js +14 -0
package/.eslintignore ADDED
@@ -0,0 +1,8 @@
1
+ dist
2
+ temp
3
+ **/dist
4
+ *.json
5
+ **/*.json
6
+ !.eslintrc.js
7
+ node_modules
8
+ repo-templates
package/.eslintrc.js ADDED
@@ -0,0 +1,15 @@
1
+ module.exports = {
2
+ env: {
3
+ node: true,
4
+ es6: true,
5
+ },
6
+ plugins: ['prettier'],
7
+ extends: ['eslint:recommended', 'plugin:prettier/recommended'],
8
+ parserOptions: {
9
+ requireConfigFile: false,
10
+ ecmaVersion: 'latest',
11
+ },
12
+ rules: {
13
+ 'prettier/prettier': 'error',
14
+ },
15
+ };
@@ -0,0 +1,14 @@
1
+ name: Conventional Commit Checker
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [master]
6
+ types: [opened, edited, synchronize]
7
+
8
+ jobs:
9
+ check-for-cc:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: check-for-cc
13
+ id: check-for-cc
14
+ uses: agenthunt/conventional-commit-checker-action@v1.0.0
@@ -0,0 +1,29 @@
1
+ name: Release
2
+ on:
3
+ workflow_run:
4
+ workflows: ['tests']
5
+ branches: [master]
6
+ types:
7
+ - completed
8
+ push:
9
+ branches:
10
+ - master
11
+ jobs:
12
+ release:
13
+ name: Release
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v1
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v2
20
+ with:
21
+ cache: npm
22
+ node-version: 14
23
+ - name: Install dependencies
24
+ run: npm ci
25
+ - name: Release
26
+ env:
27
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
29
+ run: npx semantic-release
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ npx --no -- commitlint --edit "${1}"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname -- "$0")/_/husky.sh"
3
+
4
+ npm run lint-staged
@@ -0,0 +1,2 @@
1
+ node_modules
2
+ .vscode
package/.prettierrc.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ semi: true,
3
+ tabWidth: 2,
4
+ singleQuote: true,
5
+ printWidth: 80,
6
+ trailingComma: 'es5',
7
+ endOfLine: 'auto'
8
+ };
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # FERT - proposed approach/readme
2
+
3
+ Madgex brand tooling for anyone.
4
+
5
+ > **F**ront-**e**nd **R**ollout **T**ool – Tooling to help scaffold, develop and deploy Madgex client branding
6
+
7
+ # Why FERT
8
+
9
+ The Madgex job board brands all have a custom headers, footers and their associated JavaScript & CSS. In the past we've struggled with finding an easy local development & roll-out setup. Fert is an attempt to address that.
10
+
11
+ ## Requirements
12
+
13
+ * To be a one-stop shop for:
14
+
15
+ * Scaffolding a new project
16
+
17
+ * A dev server to allow easy brand development
18
+
19
+ * Builds distributable assets
20
+
21
+ * Must be able to install via [NPM](https://www.npmjs.com/) or internal registry
22
+
23
+ * Must work cross-platform (Windows and *nix)
24
+
25
+ ## A human-first design
26
+
27
+ To empower & serve its users, we should design this CLI with the users in mind. Ensuring it feels as familiar as possible, following established patterns and is has the following:
28
+
29
+ * Easy to learn commands from a inbuilt help screen
30
+
31
+ * Easy to read/understand error messages
32
+
33
+ * Empathy in the error messages – can some helpful context be provided with the error to assist the user remedy the issue?
34
+
35
+ # Under the hood
36
+
37
+ * [Hapi](https://hapi.dev/) is used for the local dev server
38
+
39
+ * [Vite](https://vitejs.dev/) for HMR, serves the JS entry & bundles assets for production
40
+
41
+ * [Style Dictionary](https://amzn.github.io/style-dictionary/#/README) is used to transform Design Tokens into various outputs, inc. JSON, CSS Custom Properties and SCSS variables. The output is built into `public/tokens/`
42
+
43
+ * Chokidar is used to watch for changes in the `templates` and `public/tokens` directories and either refresh the browser page or build a new set of tokens respectively.
44
+
45
+
46
+
47
+ # Configuration
48
+
49
+ There are **three required files** in the root of the branding repo:
50
+
51
+ `brand.json` [required] – a JSON file that supplies the base branding tokens. These values will be merged with the Design System tokens & a full set of branding tokens will be created.
52
+
53
+ e.g.
54
+
55
+ ```json
56
+ {
57
+ "color": {
58
+ "brand": {
59
+ "1": {
60
+ "base": { "value": "#005689" }
61
+ }
62
+ }
63
+ },
64
+ // more branding tokens applied here...
65
+ }
66
+ ```
67
+
68
+ `fert.config.js` [required] – a configuration file in the root of the branding repo specifying the following config to both the Fert dev server and the production asset build:
69
+
70
+ | Option | |
71
+ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
72
+ | `clientPropertyId` <String> | The `clientPropertyId` associated with the branding repo (required) |
73
+ | `entry` <String> | The JavaScript entry file. Any assets (CSS/SCSS/SVGs) included will be processed and be part of the output. Defaults to `['src/index.js']` |
74
+
75
+ The `entry` will be used by Vite to create production bundles.
76
+
77
+ e.g.
78
+
79
+ ```js
80
+ module.exports = {
81
+ clientPropertyId: "ff6102ff-0f4b-43d1-a2c7-83b835b8dee5",
82
+ entry: "./src/index.js",
83
+ };
84
+ ```
85
+
86
+ `jenkinsfile` - A jenkins file containing the pipeline which will build and send the assets to S3. Every push to the repo will trigger a jenkins build automatically. Changes on **master** will trigger a build and send assets to the **production** bucket. Any other branches will send the assets to the jb.dev bucket.
87
+
88
+ # CLI commands
89
+
90
+ The CLI will support 3 main commands: dev server (default command), scaffolding a new project and building production assets.
91
+
92
+ * [Dev server](#dev-server)
93
+
94
+ * [Scaffold](#scaffold)
95
+
96
+ * [Build](#build)
97
+
98
+ * [Publish](#publish)
99
+
100
+ ## Dev server
101
+
102
+ `fert`
103
+
104
+ Start the Fert dev server in the current directory.
105
+
106
+ **Usage**
107
+
108
+ `fert [root]`
109
+
110
+ **Outline of implementation**
111
+
112
+ A fast, minimal development server that allows the developer to see the header/footer templates and branding (Design System tokens) specified in the local repo applied to a Design System-based HTML page.
113
+
114
+ The server will be a hapi server, importing the header/footer micro front-end server(s) as dependencies, running all together to render the page.
115
+
116
+ Changes to the local tokens will cause the DS tokens to be rebuilt.
117
+
118
+ Changes to the local `fert.config.js` will be reflected in the dev servers environment.
119
+
120
+ Changes to any local file will be reflected in the developers browser without having to manually refresh.
121
+
122
+ ## Scaffold
123
+
124
+ `fert init`
125
+
126
+ When faced with an empty branding repo, this will help the user get started with the boilerplate branding project template
127
+
128
+ **Usage**
129
+
130
+ `fert init [root]`
131
+
132
+ **Options**
133
+
134
+ | Option | |
135
+ | --------- | --------------------------------------------------------------------- |
136
+ | `--template <template>` | Specify the template you wish to use when scaffolding |
137
+ | `--cpid <cpid>` | Specify the clientPropertyId to use in the new project |
138
+
139
+ **Outline of implementation**
140
+
141
+ The init command will clone a well-maintained boilerplate repo into the target directory. It may be good to use a tool like [`degit`](https://www.npmjs.com/package/degit) for faster cloning & not confusing git with nested, hidden `.git` directories.
142
+
143
+ The `--force` option would destructively reset the branding repo to a common baseline, resetting the content.
144
+
145
+ The source boilerplate repo: https://github.com/wiley/madgex-00000000-0000-0000-0000-000000000000
146
+ The `init` command is intended for an automation tool which will create a new branding repo, run this command and commit the new files.
147
+
148
+ ## Build
149
+
150
+ `fert build`
151
+
152
+ Process CSS/JS assets specified in `fert.config.js` and copy static assets, including templates for distribution.
153
+
154
+ **Usage**
155
+
156
+ `fert build [root] --only [tokens | assets]`
157
+
158
+ | Option | |
159
+ | ----------------- | ---------------------------------------------------------------------------------------------------------- |
160
+ | `--only [task]` | Specify a single part of the build process to run (`string` \| `tokens` \| `assets`) |
161
+ | `--config <path>` | Override the internal default Vite config & provide a custom `vite.config.js` file to use to build assets. |
162
+
163
+ **Outline of implementation**
164
+
165
+ Using Vite, the `entry` in the `fert.config.js` file is processed and bundled to the `dist` directory.
166
+
167
+ Templates are copied to `dist`.
168
+
169
+ Public assets are copied to `dist`.
170
+
171
+ The resulting `dist` directory is uploaded wholesale to the `assets-store-api` for use in production.
172
+
173
+ Templates & CSS may be processed using the [CSS Modules](https://github.com/css-modules/css-modules) system to encapsulate header/footer styles & prevent bleed into the rest of the page.
174
+
175
+ ## Publish
176
+
177
+ `fert publish`
178
+
179
+ **Usage**
180
+
181
+ `fert publish [root] --target [target]`
182
+
183
+ | Option | |
184
+ | ---------- | ---------------------------------------------------------------------------- |
185
+ | `--target` | Where to publish the `dist` directory assets.<br/>`dev` \| `prod` (`string`) |
186
+
187
+ Send all files and directories created in the `dist` directory to either development or production versions of the Asset Store API. Files uploaded to the Asset Store API are available via a CloudFront-based CDN.
188
+
189
+ **Outline of implementation**
190
+
191
+ Index all the files and their paths in the `dist` directory, and using a recursive function upload each item (destructively) to the Asset Store API.
192
+
193
+ The Asset Store API uses a multi-part form upload to PUT files in the client directory. Upload paths are respected, directories are created on the fly.
194
+
195
+
196
+
197
+ # CI/CD
198
+
199
+ It's intended that the branding repos have their own build/deploy pipeline. Each change that's merged to `master` will trigger a build (`npm run build` as a common entry point) and the resulting output directory (`dist`) is pushed up to the `asset-store-api` for use in production.
200
+
201
+ ## `npm scripts`
202
+
203
+ Here are the default npm scripts in a Fert-scaffolded project.
204
+
205
+ ```json
206
+ {
207
+ "scripts": {
208
+ "dev": "fert", // start dev server
209
+ "build": "fert build" // build assets for production
210
+ }
211
+ }
212
+ ```
213
+
214
+ Its expected that a Jenkins pipeline will run `fert publish` to send all built assets to the Asset Store API.
215
+
216
+
217
+
218
+ # @madgex/boilerplate-utils
219
+
220
+ A collection of utilities for use in branding projects, e.g.
221
+
222
+ * Hamburger nav HTML/CSS/JS
223
+
224
+ * common SCSS
225
+
226
+ * SVGs
227
+
228
+ * templates/macros
229
+
230
+ If needed, this package can be `npm install`ed in the branding project & consumed from the JS/SCSS.
231
+
232
+ Templates/macros will have to be copied into the branding repo as they won't be visible/available to the server rendering the template.
package/bin/cli.js ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('node:fs');
4
+ const chalk = require('chalk');
5
+ const cli = require('cac')('fert');
6
+ const { VERSION } = require('../constants');
7
+ const { printBanner } = require('./utils/index.js');
8
+
9
+ const run = () => {
10
+ printBanner();
11
+
12
+ cli
13
+ .command(
14
+ '[root]',
15
+ 'Start layout server. Can supply a branding directory if running FERT standalone'
16
+ )
17
+ .alias('dev')
18
+ .option('--open', 'Automatically open the dev server in your browser')
19
+ .option('--host [host]', '[string] specify hostname')
20
+ .option('--port <port>', '[number] specify port')
21
+ .action((...args) => require('./commands/dev-server')(...args));
22
+
23
+ cli
24
+ .command(
25
+ 'build [root]',
26
+ 'Build project. Can supply a branding directory if running FERT standalone'
27
+ )
28
+ .option('--only <task>', `Only run part of the build [ 'assets', 'tokens']`)
29
+ .option('--config [dir]', 'Use custom rollup config file')
30
+ .action((...args) => require('./commands/build.js')(...args));
31
+
32
+ cli
33
+ .command('publish [root]', 'Publish project to S3')
34
+ .option('--target <env>', 'Environment to publish to, "dev" or "prod"')
35
+ .action((...args) => require('./commands/publish')(...args));
36
+
37
+ cli
38
+ .command('init [root]', 'Create a new branding project')
39
+ .option('--template <template>', 'Template to use when scaffolding project')
40
+ .option(
41
+ '--cpid <cpid>',
42
+ 'Specify the clientPropertyId to use in the new project'
43
+ )
44
+ .action((...args) => require('./commands/init')(...args));
45
+
46
+ cli.help();
47
+ cli.version(VERSION);
48
+ cli.parse();
49
+
50
+ // checks for available update
51
+ const pkg = JSON.parse(fs.readFileSync(__dirname + '/../package.json'));
52
+
53
+ if (pkg.version.indexOf('0.0.0') !== 0) {
54
+ require('simple-update-notifier')({ pkg });
55
+ }
56
+ };
57
+
58
+ try {
59
+ run();
60
+ } catch (error) {
61
+ if (error.name === 'CACError') {
62
+ console.error(chalk`\n{red ${error.message}}`);
63
+ } else {
64
+ console.error(error);
65
+ }
66
+
67
+ process.exit(1);
68
+ }
@@ -0,0 +1,16 @@
1
+ const Path = require('path');
2
+ const fs = require('fs/promises');
3
+ const { log } = require('../../utils');
4
+
5
+ module.exports = async function buildExternalAssets(fertConfig) {
6
+ const { externalAssets, workingDir } = fertConfig;
7
+ const destination = Path.join(workingDir, `/dist/external-assets.json`);
8
+
9
+ try {
10
+ await fs.writeFile(destination, JSON.stringify(externalAssets, null, 2));
11
+ log.success('External assets file created');
12
+ } catch (err) {
13
+ log.error(err);
14
+ throw err;
15
+ }
16
+ };
@@ -0,0 +1,119 @@
1
+ const StyleDictionaryPackage = require('style-dictionary');
2
+ const Path = require('path');
3
+ const fs = require('fs/promises');
4
+ const {
5
+ registerTransforms,
6
+ } = require('@madgex/design-system/tasks/registerTransforms');
7
+ const colorTransforms = require('@madgex/design-system/tasks/colorTransforms');
8
+ const { ensureTrailingSlash, log, exists } = require('../../utils');
9
+ const { TMP_DIR } = require('../../../constants');
10
+
11
+ const dsTokensPath = Path.dirname(
12
+ require.resolve('@madgex/design-system/src/tokens/_config.js')
13
+ );
14
+
15
+ // eslint-disable-next-line no-unused-vars
16
+ const createTempBrandFile = async (dir = './') => {
17
+ // Generate unique name to bust style dict cache
18
+ const timestamp = Date.now();
19
+ const tmpBrandFile = Path.join(TMP_DIR, `/fert/brand-${timestamp}.json`);
20
+ const dirPath = Path.dirname(tmpBrandFile);
21
+
22
+ if (!(await exists(dirPath))) {
23
+ await fs.mkdir(dirPath, { recursive: true });
24
+ }
25
+
26
+ return tmpBrandFile;
27
+ };
28
+
29
+ // Style Dictionary is noisy and annoying, this suppresses its output
30
+ async function runSilently(fn) {
31
+ const originalLog = console.log;
32
+ console.log = () => {};
33
+ await fn();
34
+ console.log = originalLog;
35
+ }
36
+
37
+ module.exports = async function buildCssFromTokens(srcTokensPath, buildPath) {
38
+ srcTokensPath = ensureTrailingSlash(Path.resolve(srcTokensPath));
39
+ buildPath = ensureTrailingSlash(Path.resolve(buildPath));
40
+
41
+ const brandFile = Path.join(srcTokensPath, 'brand.json');
42
+
43
+ if (!(await exists(buildPath))) {
44
+ await fs.mkdir(buildPath, { recursive: true });
45
+ }
46
+
47
+ // Fetch the file so we can transform the colours in style dictionary
48
+ const brandObj = JSON.parse(
49
+ await fs.readFile(brandFile, { encoding: 'utf8' })
50
+ );
51
+ const tmpBrandFile = await createTempBrandFile(srcTokensPath);
52
+
53
+ await fs.writeFile(
54
+ Path.join(tmpBrandFile),
55
+ JSON.stringify(colorTransforms(brandObj))
56
+ );
57
+
58
+ // TODO - Investigate whether we can retrieve from DS instead of redefining
59
+ // e.g. const { registerTransforms } = require('@madgex/design-system/tasks/registerTransforms');
60
+ const transforms = [
61
+ 'attribute/cti',
62
+ 'name/cti/kebab',
63
+ 'color/css',
64
+ 'css/rawData',
65
+ ];
66
+ const prefix = 'mds';
67
+
68
+ // TODO - Investigate whether we can retrieve from DS instead of redefining
69
+ const styleDictionaryConfig = {
70
+ include: [Path.join(dsTokensPath, '*.json')],
71
+ source: [tmpBrandFile],
72
+ platforms: {
73
+ 'scss-variables': {
74
+ transforms,
75
+ prefix,
76
+ buildPath: Path.join(buildPath, 'scss/'),
77
+ files: [
78
+ {
79
+ destination: 'index.scss',
80
+ format: 'scss/map-deep',
81
+ },
82
+ ],
83
+ },
84
+ 'css-variables': {
85
+ transforms,
86
+ prefix,
87
+ buildPath: Path.join(buildPath, 'css-vars/'),
88
+ files: [
89
+ {
90
+ destination: `variables.css`,
91
+ format: 'css/variables',
92
+ },
93
+ ],
94
+ },
95
+ 'json-variables': {
96
+ transforms,
97
+ prefix,
98
+ buildPath: Path.join(buildPath, 'json/'),
99
+ files: [
100
+ {
101
+ destination: `variables.json`,
102
+ format: 'json/nested',
103
+ },
104
+ ],
105
+ },
106
+ },
107
+ };
108
+
109
+ // Use StyleDictionary to build a tokens SCSS file
110
+ const StyleDictionary = StyleDictionaryPackage.extend(styleDictionaryConfig);
111
+
112
+ await registerTransforms(StyleDictionary);
113
+ await runSilently(StyleDictionary.buildAllPlatforms.bind(StyleDictionary));
114
+
115
+ // clean-up temp SD file
116
+ await fs.unlink(tmpBrandFile);
117
+
118
+ log.success('Token build complete.');
119
+ };
@@ -0,0 +1,74 @@
1
+ const path = require('node:path');
2
+ const fsp = require('node:fs/promises');
3
+ const _ = require('lodash');
4
+ const vite = require('vite');
5
+ const chalk = require('chalk');
6
+
7
+ // TODO: delete me when DS is driven by CSS Custom Ppoperties
8
+
9
+ module.exports = async (viteConfig) => {
10
+ const dsBundledViteConfig = { ...viteConfig };
11
+
12
+ // create ds-bundled vite build in-memory
13
+ _.merge(dsBundledViteConfig, {
14
+ logLevel: 'silent',
15
+ build: {
16
+ write: false,
17
+ rollupOptions: {
18
+ output: {
19
+ assetFileNames: 'assets/[name]-ds-[hash].[ext]',
20
+ },
21
+ },
22
+ },
23
+ css: {
24
+ preprocessorOptions: {
25
+ scss: {
26
+ additionalData: `
27
+ @import "../../public/tokens/scss/index.scss";
28
+ @import "@madgex/design-system/src/scss/import.scss";
29
+ `, // all scss processed files gets this injected at the top
30
+ },
31
+ },
32
+ },
33
+ });
34
+
35
+ const dsBuild = await vite.build(dsBundledViteConfig);
36
+ const { output: files } = Array.isArray(dsBuild) ? dsBuild[0] : dsBuild;
37
+
38
+ // write just the CSS file to disk
39
+ for (const file of files) {
40
+ if (file.name !== 'style.css') {
41
+ continue;
42
+ }
43
+ const cssFileContent = file.source;
44
+ await fsp.writeFile(
45
+ path.resolve('dist', file.fileName),
46
+ cssFileContent,
47
+ 'utf8'
48
+ );
49
+
50
+ // read the manifest.json
51
+ const manifestPath = path.resolve('dist', 'manifest.json');
52
+ const manifestStr = await fsp.readFile(manifestPath);
53
+ const manifest = JSON.parse(manifestStr);
54
+
55
+ // add entry to manifest.json
56
+ const dsEntryName = file.name
57
+ .split('.')
58
+ .map((part, i) => (i === 0 ? `${part}-ds` : part))
59
+ .join('.');
60
+ manifest[dsEntryName] = { ...manifest[file.name] };
61
+ manifest[dsEntryName].file = file.fileName;
62
+
63
+ // write new manifest
64
+ await fsp.writeFile(
65
+ manifestPath,
66
+ JSON.stringify(manifest, null, 2),
67
+ 'utf8'
68
+ );
69
+
70
+ console.log(
71
+ `\nUpdated build & manifest with DS-bundled CSS file: ${chalk.magenta(file.fileName)}\n` // prettier-ignore
72
+ );
73
+ }
74
+ };
@@ -0,0 +1,43 @@
1
+ const path = require('path');
2
+ const _ = require('lodash');
3
+ const vite = require('vite');
4
+ const updateBuildWithBundledDsCSS = require('./bundle-ds-css');
5
+ const buildExternalAssets = require('./build-external-assets');
6
+ const { log } = require('../../utils');
7
+
8
+ module.exports = async (fertConfig, options = {}) => {
9
+ let dynamicOptions = {};
10
+ let viteConfig = {};
11
+
12
+ if (options.config) {
13
+ viteConfig = require(path.resolve(fertConfig.workingDir, options.config));
14
+ } else {
15
+ viteConfig = require(path.resolve(__dirname, '../../../vite.config.js'));
16
+ }
17
+
18
+ dynamicOptions = {
19
+ root: path.resolve(fertConfig.workingDir),
20
+ base: '/_/jobseekers-frontend/',
21
+ build: {
22
+ cssCodeSplit: false, // important: to get a single, style.css file output
23
+ outDir: path.resolve(fertConfig.workingDir, 'dist'),
24
+ rollupOptions: {
25
+ input: path.resolve(
26
+ fertConfig.workingDir,
27
+ fertConfig.entry || './src/index.js'
28
+ ),
29
+ },
30
+ },
31
+ };
32
+
33
+ _.merge(viteConfig, dynamicOptions);
34
+
35
+ await vite.build(viteConfig);
36
+
37
+ // second build - this time with the DS included in the CSS bundle
38
+ await updateBuildWithBundledDsCSS(viteConfig);
39
+
40
+ await buildExternalAssets(fertConfig);
41
+
42
+ log.success('Assets built.');
43
+ };