diff --git a/.gitignore b/.gitignore
index fc033ad110..512dea94fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,9 +8,12 @@ package-lock.json
# npm package folders
/components/
/page-templates/
+/templates/
/css/
/favicons/
/fonts/
/img/
/scripts/
/scss/
+
+secrets.yml
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 0000000000..f286e2e13f
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,15 @@
+#### Login to Concourse
+
+```
+fly -t main login -c CONCOURSE_URL
+```
+
+#### Add design system Pipeline
+
+```
+fly -t main set-pipeline -p design-system -c concourse.yml --load-vars-from secrets.yml
+```
+
+```
+fly -t main unpause-pipeline --pipeline design-system
+```
diff --git a/ci/common.js b/ci/common.js
new file mode 100644
index 0000000000..87835e9c65
--- /dev/null
+++ b/ci/common.js
@@ -0,0 +1,55 @@
+import * as fs from 'fs';
+import { createFolder, copyFile } from './helpers';
+
+export async function copyComponents(componentsPath, newComponentsPath) {
+ await createFolder(newComponentsPath);
+
+ try {
+ const items = await fs.readdirSync(componentsPath).filter(path => !path.includes('.njk'));
+
+ items.forEach(item => copyComponent(item, componentsPath, newComponentsPath));
+ } catch (error) {
+ throw new Error(error);
+ }
+}
+
+async function copyComponent(componentName, componentsPath, newComponentsPath) {
+ try {
+ const componentPath = `${componentsPath}/${componentName}`;
+ const newComponentPath = `${newComponentsPath}/${componentName}`;
+
+ const items = await fs
+ .readdirSync(componentPath)
+ .filter(path => path.includes('.njk') && path.includes('_') && !path.includes('_test-'));
+
+ if (items.length) {
+ await createFolder(newComponentPath);
+ }
+
+ items.forEach(async path => {
+ await copyFile(`${componentPath}/${path}`, `${newComponentPath}/${path}`);
+ });
+ } catch (error) {
+ throw new Error(error);
+ }
+}
+
+export async function copyTemplates(templatesPath, newTemplatesPath) {
+ await createFolder(newTemplatesPath);
+
+ try {
+ const items = await fs.readdirSync(templatesPath).filter(path => path.includes('.njk') && path.includes('_'));
+
+ items.forEach(item => copyTemplate(item, templatesPath, newTemplatesPath));
+ } catch (error) {
+ throw new Error(error);
+ }
+}
+
+async function copyTemplate(templateFileName, templatesPath, newTemplatesPath) {
+ try {
+ await copyFile(`${templatesPath}/${templateFileName}`, `${newTemplatesPath}/${templateFileName}`);
+ } catch (error) {
+ throw new Error(error);
+ }
+}
diff --git a/ci/concourse.yml b/ci/concourse.yml
new file mode 100644
index 0000000000..73b5f8f0ae
--- /dev/null
+++ b/ci/concourse.yml
@@ -0,0 +1,118 @@
+resource_types:
+- name: slack-notification
+ type: docker-image
+ source:
+ repository: cfcommunity/slack-notification-resource
+ tag: latest
+
+resources:
+- name: ons-design-system-release
+ type: github-release
+ source:
+ owner: ONSdigital
+ repository: design-system
+ access_token: ((github_access_token))
+ release: true
+ pre_release: true
+
+- name: slack-alert
+ type: slack-notification
+ source:
+ url: ((slack_webhook_url))
+
+jobs:
+- name: Release
+ plan:
+ - get: ons-design-system-release
+ params:
+ include_source_tarball: true
+ trigger: true
+
+ - task: CDN Build
+ config:
+ platform: linux
+
+ image_resource:
+ type: docker-image
+ source:
+ repository: node
+ tag: 10.14.2
+
+ inputs:
+ - name: ons-design-system-release
+
+ outputs:
+ - name: dist
+ - name: templates
+
+ run:
+ path: sh
+ args:
+ - -exc
+ - |
+ apt-get update && apt-get install -y --allow-unauthenticated zip
+
+ cd ons-design-system-release
+
+ mkdir design-system
+ tar -xzf source.tar.gz -C design-system --strip-components=1
+
+ cd design-system
+
+ design_system_release=$(cat ../../ons-design-system-release/version)
+
+ yarn
+ RELEASE_VERSION=$design_system_release yarn cdn-bundle
+
+ mkdir ../../dist/$design_system_release
+ cp -R build/* ../../dist/$design_system_release
+ zip -r ../../templates/templates.zip templates/*
+ on_failure:
+ put: slack-alert
+ params:
+ channel: '#pat-lib-notifications'
+ attachments:
+ - pretext: Design System Build Failed
+ color: danger
+ title: Concourse Build $BUILD_ID
+ title_link: http://concourse.dev.eq.ons.digital/builds/$BUILD_ID
+
+ - task: Release to S3
+ params:
+ AWS_ACCESS_KEY_ID: ((aws_access_key))
+ AWS_SECRET_ACCESS_KEY: ((aws_secret_key))
+ AWS_DEFAULT_REGION: eu-west-1
+ config:
+ platform: linux
+
+ image_resource:
+ type: docker-image
+ source:
+ repository: mesosphere/aws-cli
+
+ inputs:
+ - name: dist
+
+ run:
+ path: sh
+ args:
+ - -exc
+ - |
+ aws s3 sync --acl public-read dist s3://((s3_bucket_name))/design-system/
+
+ on_failure:
+ put: slack-alert
+ params:
+ channel: '#pat-lib-notifications'
+ attachments:
+ - pretext: Design System CDN Release Failed
+ color: danger
+ title: Concourse Build $BUILD_ID
+ title_link: http://concourse.dev.eq.ons.digital/builds/$BUILD_ID
+
+ - put: ons-design-system-release
+ params:
+ name: ons-design-system-release/version
+ tag: ons-design-system-release/version
+ globs:
+ - templates/*.zip
diff --git a/ci/generate-npm-package.js b/ci/generate-npm-package.js
new file mode 100644
index 0000000000..3352de86e2
--- /dev/null
+++ b/ci/generate-npm-package.js
@@ -0,0 +1,65 @@
+import * as fs from 'fs';
+
+import { removeFolder, copyDir, createFolder, copyFile, asyncForEach } from './helpers';
+import { copyComponents, copyTemplates } from './common';
+
+const cwd = process.cwd();
+const sourcePath = `${cwd}/src`;
+const componentsPath = `${sourcePath}/components`;
+const newComponentsPath = `${cwd}/components`;
+const templatesPath = `${sourcePath}/styles/page-template`;
+const newTemplatesPath = `${cwd}/page-templates`;
+const assetFolders = ['css', 'favicons', 'fonts', 'img', 'scripts'];
+const builtAssetsFolders = assetFolders.map(folder => `${cwd}/build/${folder}`);
+const newSassPath = `${cwd}/scss`;
+
+async function removeExistingFolders() {
+ const folders = [newComponentsPath, newTemplatesPath, ...assetFolders];
+
+ await asyncForEach(folders, removeFolder);
+}
+
+async function copyAssets() {
+ await asyncForEach(assetFolders, async (folder, index) => {
+ await createFolder(folder);
+
+ try {
+ const builtPath = builtAssetsFolders[index];
+ const files = await fs.readdirSync(builtPath).filter(path => !path.includes('patternlib'));
+
+ asyncForEach(files, async file => {
+ if (file.match(/(\.\w+)$/)) {
+ await copyFile(`${builtPath}/${file}`, `${folder}/${file}`);
+ } else {
+ const newFolderPath = `${folder}/${file}`;
+ const nestedBuiltPath = `${builtPath}/${file}`;
+ await createFolder(newFolderPath);
+
+ const nestedFiles = await fs.readdirSync(nestedBuiltPath).filter(path => !path.includes('patternlib'));
+
+ asyncForEach(nestedFiles, async nestedFile => {
+ await copyFile(`${nestedBuiltPath}/${nestedFile}`, `${newFolderPath}/${nestedFile}`);
+ });
+ }
+ });
+ } catch (error) {
+ throw new Error(error);
+ }
+ });
+}
+
+async function copyBaseSass() {
+ await createFolder(newSassPath);
+ await copyDir(`${sourcePath}/scss/helpers`, `${newSassPath}/helpers`);
+ await copyDir(`${sourcePath}/scss/vars`, `${newSassPath}/vars`);
+}
+
+async function run() {
+ await removeExistingFolders();
+ await copyComponents(componentsPath, newComponentsPath);
+ await copyTemplates(templatesPath, newTemplatesPath);
+ await copyAssets();
+ await copyBaseSass();
+}
+
+run();
diff --git a/ci/helpers.js b/ci/helpers.js
new file mode 100644
index 0000000000..185073b496
--- /dev/null
+++ b/ci/helpers.js
@@ -0,0 +1,48 @@
+import * as fs from 'fs';
+import ncp from 'ncp';
+import rimraf from 'rimraf';
+
+export async function copyDir(from, to) {
+ return new Promise((resolve, reject) => {
+ ncp(from, to, error => {
+ if (error) {
+ throw new Error(error);
+ reject(error);
+ } else {
+ resolve();
+ }
+ });
+ });
+}
+
+export async function createFolder(folderPath) {
+ try {
+ await fs.mkdirSync(folderPath);
+ } catch (error) {
+ throw new Error(error);
+ }
+}
+
+export async function copyFile(filePath, newComponentPath) {
+ try {
+ await fs.copyFileSync(filePath, newComponentPath);
+ } catch (error) {
+ throw new Error(error);
+ }
+}
+
+export async function asyncForEach(array, callback) {
+ for (let index = 0, arrayLength = array.length; index < arrayLength; index++) {
+ await callback(array[index], index, array);
+ }
+}
+
+export async function removeFolder(folderPath) {
+ try {
+ if (await fs.existsSync(folderPath)) {
+ await rimraf.sync(folderPath);
+ }
+ } catch (error) {
+ throw new Error(error);
+ }
+}
diff --git a/ci/prepare-templates-for-zip.js b/ci/prepare-templates-for-zip.js
new file mode 100644
index 0000000000..31059e36c1
--- /dev/null
+++ b/ci/prepare-templates-for-zip.js
@@ -0,0 +1,40 @@
+import prependFile from 'prepend-file';
+import { removeFolder, createFolder, asyncForEach } from './helpers';
+import { copyComponents, copyTemplates } from './common';
+
+const cwd = process.cwd();
+const sourcePath = `${cwd}/src`;
+const destPath = `${cwd}/templates`;
+const componentsPath = `${sourcePath}/components`;
+const newComponentsPath = `${destPath}/components`;
+const templatesPath = `${sourcePath}/styles/page-template`;
+const newTemplatesPath = `${destPath}/layout`;
+const copiedPageTemplatePath = `${newTemplatesPath}/_template.njk`;
+
+async function removeExistingFolders() {
+ const folders = [newComponentsPath, newTemplatesPath];
+
+ await asyncForEach(folders, removeFolder);
+}
+
+async function addCDNVersionToPageTemplate() {
+ const version = process.env.RELEASE_VERSION;
+
+ if (version) {
+ const insert = `{% set release_version = '${version}' %}\n`;
+
+ prependFile.sync(copiedPageTemplatePath, insert);
+ } else {
+ throw new Error('RELEASE_VERSION not specified');
+ }
+}
+
+async function run() {
+ await removeExistingFolders();
+ await createFolder(destPath);
+ await copyComponents(componentsPath, newComponentsPath);
+ await copyTemplates(templatesPath, newTemplatesPath);
+ await addCDNVersionToPageTemplate();
+}
+
+run();
diff --git a/ci/secrets.yml.example b/ci/secrets.yml.example
new file mode 100644
index 0000000000..0fc81f9440
--- /dev/null
+++ b/ci/secrets.yml.example
@@ -0,0 +1,5 @@
+aws_access_key:
+aws_secret_key:
+s3_bucket_name:
+slack_webhook_url:
+github_access_token:
diff --git a/lib/generate-npm-package.js b/lib/generate-npm-package.js
deleted file mode 100644
index e8c53d7ffb..0000000000
--- a/lib/generate-npm-package.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import * as fs from 'fs';
-
-import rimraf from 'rimraf';
-import ncp from 'ncp';
-
-const cwd = process.cwd();
-const sourcePath = `${cwd}/src`;
-const componentsPath = `${sourcePath}/components`;
-const newComponentsPath = `${cwd}/components`;
-const templatesPath = `${sourcePath}/styles/page-template`;
-const newTemplatesPath = `${cwd}/page-templates`;
-const assetFolders = ['css', 'favicons', 'fonts', 'img', 'scripts'];
-const builtAssetsFolders = assetFolders.map(folder => `${cwd}/build/${folder}`);
-const newSassPath = `${cwd}/scss`;
-
-async function removeExistingFolders() {
- const folders = [newComponentsPath, newTemplatesPath, ...assetFolders];
-
- await asyncForEach(folders, removeFolder);
-}
-
-async function removeFolder(folderPath) {
- try {
- if (await fs.existsSync(folderPath)) {
- await rimraf.sync(folderPath);
- }
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyComponents() {
- await createFolder(newComponentsPath);
-
- try {
- const items = await fs.readdirSync(componentsPath).filter(path => !path.includes('.njk'));
-
- items.forEach(await copyComponent);
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyComponent(componentName) {
- try {
- const componentPath = `${componentsPath}/${componentName}`;
- const newComponentPath = `${newComponentsPath}/${componentName}`;
-
- const items = await fs
- .readdirSync(componentPath)
- .filter(path => path.includes('.njk') && path.includes('_') && !path.includes('_test-'));
-
- if (items.length) {
- await createFolder(newComponentPath);
- }
-
- items.forEach(async path => {
- await copyFile(`${componentPath}/${path}`, `${newComponentPath}/${path}`);
- });
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyTemplates() {
- await createFolder(newTemplatesPath);
-
- try {
- const items = await fs.readdirSync(templatesPath).filter(path => path.includes('.njk'));
-
- items.forEach(await copyTemplate);
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyTemplate(templateFileName) {
- try {
- await copyFile(`${templatesPath}/${templateFileName}`, `${newTemplatesPath}/${templateFileName}`);
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyAssets() {
- await asyncForEach(assetFolders, async (folder, index) => {
- await createFolder(folder);
-
- try {
- const builtPath = builtAssetsFolders[index];
- const files = await fs.readdirSync(builtPath).filter(path => !path.includes('patternlib'));
-
- asyncForEach(files, async file => {
- if (file.match(/(\.\w+)$/)) {
- await copyFile(`${builtPath}/${file}`, `${folder}/${file}`);
- } else {
- const newFolderPath = `${folder}/${file}`;
- const nestedBuiltPath = `${builtPath}/${file}`;
- await createFolder(newFolderPath);
-
- const nestedFiles = await fs.readdirSync(nestedBuiltPath).filter(path => !path.includes('patternlib'));
-
- asyncForEach(nestedFiles, async nestedFile => {
- await copyFile(`${nestedBuiltPath}/${nestedFile}`, `${newFolderPath}/${nestedFile}`);
- });
- }
- });
- } catch (error) {
- throw new Error(error);
- }
- });
-}
-
-async function copyBaseSass() {
- await createFolder(newSassPath);
- await copyDir(`${sourcePath}/scss/helpers`, `${newSassPath}/helpers`);
- await copyDir(`${sourcePath}/scss/vars`, `${newSassPath}/vars`);
-}
-
-async function copyDir(from, to) {
- return new Promise((resolve, reject) => {
- ncp(from, to, error => {
- if (error) {
- throw new Error(error);
- reject(error);
- } else {
- resolve();
- }
- });
- });
-}
-
-async function createFolder(folderPath) {
- try {
- await fs.mkdirSync(folderPath);
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function copyFile(filePath, newComponentPath) {
- try {
- await fs.copyFileSync(filePath, newComponentPath);
- } catch (error) {
- throw new Error(error);
- }
-}
-
-async function asyncForEach(array, callback) {
- for (let index = 0, arrayLength = array.length; index < arrayLength; index++) {
- await callback(array[index], index, array);
- }
-}
-
-async function run() {
- await removeExistingFolders();
- await copyComponents();
- await copyTemplates();
- await copyAssets();
- await copyBaseSass();
-}
-
-run();
diff --git a/package.json b/package.json
index e5fbf38c96..49701419e3 100644
--- a/package.json
+++ b/package.json
@@ -10,16 +10,17 @@
"url": "https://github.com/bameyrick"
},
"scripts": {
- "build": "yarn tidy-clean && yarn webpack --config webpack.prod.babel.js",
- "check-unused": "npx npm-check-unused",
- "dedupe-deps": "npx yarn-deduplicate yarn.lock",
- "lint-staged": "lint-staged",
- "npm-bundle": "NODE_ENV=production yarn build && babel-node lib/generate-npm-package.js",
"start": "yarn tidy-clean && yarn webpack-dev-server --host 0.0.0.0 --watch --config webpack.dev.babel.js",
+ "build": "yarn tidy-clean && yarn webpack --config webpack.prod.babel.js",
+ "npm-bundle": "NODE_ENV=production yarn tidy-clean && yarn webpack --config webpack.npm.babel.js && babel-node ci/generate-npm-package.js",
+ "cdn-bundle": "NODE_ENV=production yarn tidy-clean && yarn webpack --config webpack.cdn.babel.js && babel-node ci/prepare-templates-for-zip.js",
+ "test:local": "KARMA_SINGLE_RUN=false karma start ./src/tests/config/karma.conf.js",
"test": "karma start ./src/tests/config/karma.conf.js && karma start ./src/tests/config/karma.conf.nomodule.js && codecov",
"test:browserstack": "TEST_ON_BROWSERSTACK=true karma start ./src/tests/config/karma.conf.js && TEST_ON_BROWSERSTACK=true karma start ./src/tests/config/karma.conf.nomodule.js",
- "test:local": "KARMA_SINGLE_RUN=false karma start ./src/tests/config/karma.conf.js",
- "tidy-clean": "rm -rf build css favicons fonts img templates scripts coverage scss"
+ "tidy-clean": "rm -rf build css favicons fonts img components page-templates templates scripts coverage scss",
+ "check-unused": "npx npm-check-unused",
+ "dedupe-deps": "npx yarn-deduplicate yarn.lock",
+ "lint-staged": "lint-staged"
},
"husky": {
"hooks": {
@@ -109,6 +110,7 @@
"postcss-loader": "^3.0.0",
"postcss-mq-optimize": "^0.0.0",
"postcss-url": "^8.0.0",
+ "prepend-file": "^1.3.1",
"prettier": "^1.15.2",
"pretty": "^2.0.0",
"print-error": "^0.1.17",
diff --git a/src/get-started/index.njk b/src/get-started/index.njk
index 11da7b52b5..d19d097d33 100644
--- a/src/get-started/index.njk
+++ b/src/get-started/index.njk
@@ -4,22 +4,22 @@ sortOrder: 1
---
You can start using the latest version of the ONS Design System in your service right now. All of the styles, assets and components are production ready.
-## Include the compiled css and js
-All of the global styles and individual component code is compiled and made available via a `cdn`.
+## Include the compiled CSS and JS
+All of the global styles and individual component code is compiled and made available via a `CDN`.
Each release of the Design System is tagged with a version e.g. ![](https://img.shields.io/github/release/onsdigital/design-system.svg?style=flat-square) which forms part of the `url` of the compiled files for a specific release.
-The following files are deployed to the `cdn` which can be referenced in a service or project:
+The following files are deployed to the `CDN` which can be referenced in a service or project:
-- `main.css` - Responsive css file of all components.
-- `bundle.min.js` - Bundled javascript modules.
+- `main.css` - Responsive CSS file of all components.
+- `main.js` - Bundled JavaScript modules.
To reference the files in your service you would use the following `url` structures (the `[VERSION]` should be replaced with the required release version e.g. ![](https://img.shields.io/github/release/onsdigital/design-system.svg?style=flat-square)):
-- `https://cdn.ons.gov.uk/sdc/[VERSION]/css/main.css`
-- `https://cdn.ons.gov.uk/sdc/[VERSION]/js/bundle.min.js`
+- `https://cdn.ons.gov.uk/design-system/[VERSION]/css/main.css`
+- `https://cdn.ons.gov.uk/design-system/[VERSION]/js/main.js`
-Each release deployed to the `cdn` is always available. This allows services to plan upgrades to new versions.
+Each release deployed to the `CDN` is always available. This allows services to plan upgrades to new versions.
## Favicons
@@ -27,7 +27,7 @@ Favicons have been created for Safari, Chrome and Edge/Internet Explorer for des
- <meta name="msapplication-config" content="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/browserconfig.json">
+ <meta name="msapplication-config" content="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/browserconfig.json">
@@ -35,23 +35,23 @@ Favicons have been created for Safari, Chrome and Edge/Internet Explorer for des
- <link rel="icon" type="image/png" href="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/favicon-32x32.png" sizes="32x32">
+ <link rel="icon" type="image/png" href="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/favicon-32x32.png" sizes="32x32">
- <link rel="icon" type="image/png" href="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/favicon-16x16.png" sizes="16x16">
+ <link rel="icon" type="image/png" href="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/favicon-16x16.png" sizes="16x16">
- <link rel="mask-icon" color="#5bbad5" href="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/safari-pinned-tab.svg">
+ <link rel="mask-icon" color="#5bbad5" href="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/safari-pinned-tab.svg">
- <link rel="apple-touch-icon" type="image/png" href="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/apple-touch-icon.png" sizes="180x180">
+ <link rel="apple-touch-icon" type="image/png" href="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/apple-touch-icon.png" sizes="180x180">
- <link rel="manifest" href="https://cdn.ons.gov.uk/sdc/[VERSION]/favicons/manifest.json">
+ <link rel="manifest" href="https://cdn.ons.gov.uk/design-system/[VERSION]/favicons/manifest.json">
diff --git a/src/img/check-green.png b/src/img/check-green.png
deleted file mode 100644
index f1edf9e950..0000000000
Binary files a/src/img/check-green.png and /dev/null differ
diff --git a/src/img/favicon_chrome_tab.png b/src/img/favicon_chrome_tab.png
deleted file mode 100644
index a400ffe888..0000000000
Binary files a/src/img/favicon_chrome_tab.png and /dev/null differ
diff --git a/src/img/favicon_safari_homepage.png b/src/img/favicon_safari_homepage.png
deleted file mode 100644
index 958a1521a7..0000000000
Binary files a/src/img/favicon_safari_homepage.png and /dev/null differ
diff --git a/src/img/favicon_series_winphone_nokialumia930.png b/src/img/favicon_series_winphone_nokialumia930.png
deleted file mode 100644
index 7cc75da96b..0000000000
Binary files a/src/img/favicon_series_winphone_nokialumia930.png and /dev/null differ
diff --git a/src/img/favicons_winphone_nokialumia930.png b/src/img/favicons_winphone_nokialumia930.png
deleted file mode 100644
index b4cb024f25..0000000000
Binary files a/src/img/favicons_winphone_nokialumia930.png and /dev/null differ
diff --git a/src/styles/page-template/_template.njk b/src/styles/page-template/_template.njk
index 398de63346..734e574c21 100644
--- a/src/styles/page-template/_template.njk
+++ b/src/styles/page-template/_template.njk
@@ -9,9 +9,9 @@
{% set currentLanguageISOCode = currentLanguage.ISOCode %}
{% endif %}
-{% if page.cdn %}
+{% if page.cdn or release_version %}
{# Production #}
- {% set assetsURL = "https://cdn.ons.gov.uk/sdc/" + page.cdn %}
+ {% set assetsURL = "https://cdn.ons.gov.uk/design-system/" + (page.cdn or release_version) %}
{% elif data and data.version %}
{# Prototype kits #}
{% set assetsURL = "/" + data.version %}
@@ -129,9 +129,9 @@
{% endif %}
{% if isPatternLib %}
- {% set scripts = assetsURL + "/scripts/bundle.js," + assetsURL + "/scripts/patternlib.js" %}
+ {% set scripts = assetsURL + "/scripts/main.js," + assetsURL + "/scripts/patternlib.js" %}
{% else %}
- {% set scripts = assetsURL + "/scripts/bundle.js" %}
+ {% set scripts = assetsURL + "/scripts/main.js" %}
{% endif %}
{% include './_bundle-loader.njk' %}
diff --git a/src/views/layouts/_master.njk b/src/views/layouts/_master.njk
index 0e985c9b9d..3067b5d5c6 100644
--- a/src/views/layouts/_master.njk
+++ b/src/views/layouts/_master.njk
@@ -13,7 +13,7 @@
{% block master_body %}
{% endblock %}
- {% set scripts = "/scripts/bundle.js,/scripts/patternlib.js" %}
+ {% set scripts = "/scripts/main.js,/scripts/patternlib.js" %}
{% include 'styles/page-template/_bundle-loader.njk' %}
{% if devMode %}
diff --git a/src/views/layouts/_prototype.njk b/src/views/layouts/_prototype.njk
index 14a54ac0a4..b165972326 100644
--- a/src/views/layouts/_prototype.njk
+++ b/src/views/layouts/_prototype.njk
@@ -13,7 +13,7 @@
{% block prototype_body %}
{% endblock %}
- {% set scripts = "/scripts/bundle.js,/scripts/patternlib.js" %}
+ {% set scripts = "/scripts/main.js,/scripts/patternlib.js" %}
{% include 'styles/page-template/_bundle-loader.njk' %}
{% if devMode %}
diff --git a/webpack.cdn.babel.js b/webpack.cdn.babel.js
new file mode 100644
index 0000000000..f25c1ea748
--- /dev/null
+++ b/webpack.cdn.babel.js
@@ -0,0 +1,6 @@
+import merge from 'webpack-merge';
+import commonConfig from './webpack.common';
+
+const common = commonConfig('production');
+
+export default [merge(common.assets, {}), merge(common.es2015plus, {}), merge(common.es5, {})];
diff --git a/webpack.common.js b/webpack.common.js
index 5df558d3fc..df245713f3 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -51,12 +51,50 @@ const core = {
]
};
-const jsCore = merge(core, {
- entry: {
- 'scripts/bundle': ['./js/public-path-override.js', './js/polyfills/index.js', './js/index.js'],
- 'scripts/patternlib': ['./js/patternlib/index.js']
+const cssCore = merge(core, {
+ module: {
+ rules: [
+ // Styles
+ {
+ include: [path.join(process.cwd(), 'src/scss')],
+ test: /\.scss$/,
+ use: [
+ {
+ loader: 'file-loader',
+ options: {
+ name: 'css/[name].css'
+ }
+ },
+ {
+ loader: 'postcss-loader',
+ options: {
+ indent: 'postcss',
+ plugins: postcssPlugins
+ }
+ },
+ {
+ loader: 'sass-loader',
+ options: {
+ sourceMap: false,
+ precision: 8,
+ includePaths: [path.join(process.cwd(), 'src/scss')],
+ importer: globImporter()
+ }
+ }
+ ]
+ }
+ ]
},
+ plugins: [
+ new FixStyleOnlyEntriesPlugin({
+ extensions: ['scss', 'njk', 'html'],
+ silent: true
+ })
+ ]
+});
+
+const jsCore = merge(core, {
output: {
chunkFilename: 'scripts/[name].js',
publicPath: '/'
@@ -92,84 +130,100 @@ const jsCore = merge(core, {
// }
});
+const es2015plusCore = merge(jsCore, {
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /(node_modules)/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ babelrc: false,
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ modules: false,
+ targets: {
+ browsers: ['Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15']
+ }
+ }
+ ]
+ ],
+ plugins: [
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-proposal-class-properties',
+ '@babel/plugin-transform-runtime',
+ 'rewiremock/babel'
+ ]
+ }
+ }
+ }
+ ]
+ }
+});
+
+const es5Core = merge(jsCore, {
+ output: {
+ filename: '[name].es5.js',
+ chunkFilename: 'scripts/[name].es5.js'
+ },
+
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /(node_modules)/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ babelrc: false,
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ modules: false,
+ targets: {
+ browsers: ['last 3 versions']
+ }
+ }
+ ]
+ ],
+ plugins: [
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-proposal-class-properties',
+ '@babel/plugin-transform-runtime',
+ 'rewiremock/babel'
+ ]
+ }
+ }
+ }
+ ]
+ }
+});
+
+const scriptsEntry = {
+ 'scripts/main': ['./js/public-path-override.js', './js/polyfills/index.js', './js/index.js']
+};
+
+const patternLibScriptsEntry = {
+ 'scripts/patternlib': ['./js/patternlib/index.js']
+};
+
export default function(mode) {
const devMode = mode === 'development';
return {
- nonJs: merge(core, {
+ assets: merge(cssCore, {
mode,
entry: {
'css/main': ['./scss/main.scss'],
- 'css/census': ['./scss/census.scss'],
- 'css/patternlib': ['./scss/patternlib.scss'],
- error: ['./scss/error.scss'],
- html: glob.sync('./**/*.{njk,html}', { cwd: 'src', ignore: './**/_*.{njk,html}' })
- },
-
- module: {
- rules: [
- // Styles
- {
- include: [path.join(process.cwd(), 'src/scss')],
- test: /\.scss$/,
- use: [
- {
- loader: 'file-loader',
- options: {
- name: 'css/[name].css'
- }
- },
- {
- loader: 'postcss-loader',
- options: {
- indent: 'postcss',
- plugins: postcssPlugins
- }
- },
- {
- loader: 'sass-loader',
- options: {
- sourceMap: false,
- precision: 8,
- includePaths: [path.join(process.cwd(), 'src/scss')],
- importer: globImporter()
- }
- }
- ]
- },
- // Templates
- {
- test: /\.(njk|html)$/,
- loaders: [
- {
- loader: 'file-loader',
- options: {
- name: '[path][name].html'
- }
- },
- {
- loader: path.resolve('./lib/nunjucks-html-loader.js'),
- options: {
- searchPaths: `${__dirname}/src`,
- layoutPath: 'views/layouts',
- context: {
- devMode,
- isPatternLib: true
- }
- }
- }
- ]
- }
- ]
+ 'css/census': ['./scss/census.scss']
},
plugins: [
- new FixStyleOnlyEntriesPlugin({
- extensions: ['scss', 'njk', 'html'],
- silent: true
- }),
-
new CopyWebpackPlugin(
[
{
@@ -184,12 +238,6 @@ export default function(mode) {
dot: true
}
},
- {
- from: {
- glob: 'patternlib-img/**/*',
- dot: true
- }
- },
{
from: {
glob: 'favicons/**/*',
@@ -212,81 +260,103 @@ export default function(mode) {
]
}),
- es2015plus: merge(jsCore, {
+ patternLibAssets: merge(cssCore, {
mode,
- module: {
- rules: [
- {
- test: /\.js$/,
- exclude: /(node_modules)/,
- use: {
- loader: 'babel-loader',
- options: {
- babelrc: false,
- presets: [
- [
- '@babel/preset-env',
- {
- modules: false,
- targets: {
- browsers: ['Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15']
- }
- }
- ]
- ],
- plugins: [
- '@babel/plugin-syntax-dynamic-import',
- '@babel/plugin-proposal-class-properties',
- '@babel/plugin-transform-runtime',
- 'rewiremock/babel'
- ]
+ entry: {
+ 'css/patternlib': ['./scss/patternlib.scss'],
+ error: ['./scss/error.scss']
+ },
+
+ plugins: [
+ new CopyWebpackPlugin(
+ [
+ {
+ from: {
+ glob: 'patternlib-img/**/*',
+ dot: true
}
}
+ ],
+ {
+ ignore: ['.gitkeep'],
+ debug: 'warning'
}
- ]
- }
+ ),
+
+ new ImageminPlugin({
+ test: /\.(svg)$/i,
+ svgo: {
+ plugins: svgoConfig
+ }
+ })
+ ]
}),
- es5: merge(jsCore, {
+ templates: merge(core, {
mode,
- output: {
- filename: '[name].es5.js',
- chunkFilename: 'scripts/[name].es5.js'
+ entry: {
+ html: glob.sync('./**/*.{njk,html}', { cwd: 'src', ignore: './**/_*.{njk,html}' })
},
module: {
rules: [
{
- test: /\.js$/,
- exclude: /(node_modules)/,
- use: {
- loader: 'babel-loader',
- options: {
- babelrc: false,
- presets: [
- [
- '@babel/preset-env',
- {
- modules: false,
- targets: {
- browsers: ['last 3 versions']
- }
- }
- ]
- ],
- plugins: [
- '@babel/plugin-syntax-dynamic-import',
- '@babel/plugin-proposal-class-properties',
- '@babel/plugin-transform-runtime',
- 'rewiremock/babel'
- ]
+ test: /\.(njk|html)$/,
+ loaders: [
+ {
+ loader: 'file-loader',
+ options: {
+ name: '[path][name].html'
+ }
+ },
+ {
+ loader: path.resolve('./lib/nunjucks-html-loader.js'),
+ options: {
+ searchPaths: `${__dirname}/src`,
+ layoutPath: 'views/layouts',
+ context: {
+ devMode,
+ isPatternLib: true
+ }
+ }
}
- }
+ ]
}
]
- }
+ },
+
+ plugins: [
+ new FixStyleOnlyEntriesPlugin({
+ extensions: ['scss', 'njk', 'html'],
+ silent: true
+ })
+ ]
+ }),
+
+ es2015plus: merge(es2015plusCore, {
+ mode,
+
+ entry: scriptsEntry
+ }),
+
+ es2015plusPatternLib: merge(es2015plusCore, {
+ mode,
+
+ entry: patternLibScriptsEntry
+ }),
+
+ es5: merge(es5Core, {
+ mode,
+
+ entry: scriptsEntry
+ }),
+
+ es5PatternLib: merge(es5Core, {
+ mode,
+
+ entry: patternLibScriptsEntry
})
};
}
diff --git a/webpack.dev.babel.js b/webpack.dev.babel.js
index 3600621c35..eeb0dd401c 100644
--- a/webpack.dev.babel.js
+++ b/webpack.dev.babel.js
@@ -47,4 +47,12 @@ const serverSettings = {
plugins: [new LiveReloadPlugin()]
};
-export default [merge(common.nonJs, serverSettings), merge(common.es2015plus, serverSettings), merge(common.es5, serverSettings)];
+export default [
+ merge(common.assets, serverSettings),
+ merge(common.patternLibAssets, serverSettings),
+ merge(common.templates, serverSettings),
+ merge(common.es2015plus, serverSettings),
+ merge(common.es5, serverSettings),
+ merge(common.es2015plusPatternLib, serverSettings),
+ merge(common.es5PatternLib, serverSettings)
+];
diff --git a/webpack.npm.babel.js b/webpack.npm.babel.js
new file mode 100644
index 0000000000..f25c1ea748
--- /dev/null
+++ b/webpack.npm.babel.js
@@ -0,0 +1,6 @@
+import merge from 'webpack-merge';
+import commonConfig from './webpack.common';
+
+const common = commonConfig('production');
+
+export default [merge(common.assets, {}), merge(common.es2015plus, {}), merge(common.es5, {})];
diff --git a/webpack.prod.babel.js b/webpack.prod.babel.js
index 707ad1d071..8e232c04af 100644
--- a/webpack.prod.babel.js
+++ b/webpack.prod.babel.js
@@ -6,7 +6,9 @@ import commonConfig from './webpack.common';
const common = commonConfig('production');
export default [
- merge(common.nonJs, {}),
+ merge(common.assets, {}),
+ merge(common.patternLibAssets, {}),
+ merge(common.templates, {}),
merge(common.es2015plus, {
plugins: [
new BundleAnalyzerPlugin({
@@ -32,5 +34,7 @@ export default [
excludeAssets: /patternlib.es5.js/
})
]
- })
+ }),
+ merge(common.es2015plusPatternLib, {}),
+ merge(common.es5PatternLib, {})
];
diff --git a/yarn.lock b/yarn.lock
index d17c1adcdb..e93024d1b2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7435,7 +7435,7 @@ os-locale@^3.0.0:
lcid "^2.0.0"
mem "^4.0.0"
-os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
@@ -8202,6 +8202,13 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+prepend-file@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/prepend-file/-/prepend-file-1.3.1.tgz#83b16e0b4ac1901fce88dbd945a22f4cc81df579"
+ integrity sha1-g7FuC0rBkB/OiNvZRaIvTMgd9Xk=
+ dependencies:
+ tmp "0.0.31"
+
prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
@@ -10171,6 +10178,13 @@ title-case@^2.1.0:
no-case "^2.2.0"
upper-case "^1.0.3"
+tmp@0.0.31:
+ version "0.0.31"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
+ integrity sha1-jzirlDjhcxXl29izZX6L+yd65Kc=
+ dependencies:
+ os-tmpdir "~1.0.1"
+
tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"