From 89da66000ce2a98d90e7a06e0391bd7ba510833c Mon Sep 17 00:00:00 2001 From: Oliver Byford Date: Wed, 30 May 2018 09:27:44 +0100 Subject: [PATCH 1/3] Allow custom image and font URL helpers --- src/settings/_all.scss | 2 +- src/settings/_assets.scss | 69 ++++++++++++++++++++++++++++++++++ src/settings/_paths.scss | 12 ------ src/tools/_font-url.scss | 20 +++++++++- src/tools/_image-url.scss | 20 +++++++++- src/tools/font-url.test.js | 74 +++++++++++++++++++++++++++++++++++++ src/tools/image-url.test.js | 71 +++++++++++++++++++++++++++++++++++ 7 files changed, 251 insertions(+), 17 deletions(-) create mode 100644 src/settings/_assets.scss delete mode 100644 src/settings/_paths.scss create mode 100644 src/tools/font-url.test.js create mode 100644 src/tools/image-url.test.js diff --git a/src/settings/_all.scss b/src/settings/_all.scss index 755695d116..71170754d9 100644 --- a/src/settings/_all.scss +++ b/src/settings/_all.scss @@ -1,7 +1,7 @@ // The order we import settings in is important, as some settings files rely on // others -@import "paths"; +@import "assets"; @import "compatibility"; @import "global-styles"; diff --git a/src/settings/_assets.scss b/src/settings/_assets.scss new file mode 100644 index 0000000000..b1e1da2e94 --- /dev/null +++ b/src/settings/_assets.scss @@ -0,0 +1,69 @@ +/// Path to the assets directory, with trailing slash. +/// +/// This is the directory where the images and fonts subdirectories live. You +/// will need to make this directory available via your application – see the +/// README for details. +/// +/// @type String + +$govuk-assets-path: "/assets/" !default; + +/// Path to the images folder, with trailing slash. +/// +/// @type String + +$govuk-images-path: "#{$govuk-assets-path}images/" !default; + +/// Path to the fonts folder, with trailing slash. +/// +/// @type String + +$govuk-fonts-path: "#{$govuk-assets-path}fonts/" !default; + +/// Custom image URL function +/// +/// If the built-in image URL helper does not meet your needs, you can specify +/// the name of a custom handler – either built in or by writing your own +/// function. +/// +/// If you are writing your own handler, ensure that it returns a string wrapped +/// with `url()` +/// +/// @type String +/// +/// @example scss - Ruby asset handling +/// $govuk-image-url-function: 'asset-url'; +/// +/// @example scss - Custom asset handling +/// +/// @function my-url-handler($filename) { +/// @return ''; // Some custom URL handling +/// } +/// +/// $govuk-image-url-function: 'my-url-handler'; + +$govuk-image-url-function: false !default; + +/// Custom font URL function +/// +/// If the built-in font URL helper does not meet your needs, you can specify +/// the name of a custom handler – either built in or by writing your own +/// function. +/// +/// If you are writing your own handler, ensure that it returns a string wrapped +/// with `url()` +/// +/// @type String +/// +/// @example scss - Ruby asset handling +/// $govuk-font-url-function: 'asset-url'; +/// +/// @example scss - Custom asset handling +/// +/// @function my-url-handler($filename) { +/// @return ''; // Some custom URL handling +/// } +/// +/// $govuk-font-url-function: 'my-url-handler'; + +$govuk-font-url-function: false !default; diff --git a/src/settings/_paths.scss b/src/settings/_paths.scss deleted file mode 100644 index e528111867..0000000000 --- a/src/settings/_paths.scss +++ /dev/null @@ -1,12 +0,0 @@ -/// Path to the assets directory, with trailing slash. -/// -/// This is the directory where the images and fonts subdirectories live. You -/// will need to make this directory available via your application – see the -/// README for details. -$govuk-assets-path: "/assets/" !default; - -// Path to the images folder, with trailing slash. -$govuk-images-path: "#{$govuk-assets-path}images/" !default; - -// Path to the fonts folder, with trailing slash. -$govuk-fonts-path: "#{$govuk-assets-path}fonts/" !default; diff --git a/src/tools/_font-url.scss b/src/tools/_font-url.scss index a85b9e73d5..7a4a09fe2d 100644 --- a/src/tools/_font-url.scss +++ b/src/tools/_font-url.scss @@ -1,7 +1,23 @@ +// Disable indentation linting in this file only +// sass-lint:disable indentation + /// Font URL /// -/// Returns a URL for the given font filename +/// If a custom font-url handler is defined ($govuk-font-url-function) then +/// it will be called, otherwise a url will be returned with the filename +/// appended to the font path. +/// +/// @param {String} Font filename +/// @return {String} URL for the filename, wrapped in `url()` @function govuk-font-url($filename) { - @return url($govuk-fonts-path + $filename); + $use-custom-function: variable-exists("govuk-font-url-function") + and $govuk-font-url-function + and function-exists($govuk-font-url-function); + + @if ($use-custom-function) { + @return call($govuk-font-url-function, $filename); + } @else { + @return url($govuk-fonts-path + $filename); + } } diff --git a/src/tools/_image-url.scss b/src/tools/_image-url.scss index f625a77c2e..62a74ef650 100644 --- a/src/tools/_image-url.scss +++ b/src/tools/_image-url.scss @@ -1,7 +1,23 @@ +// Disable indentation linting in this file only +// sass-lint:disable indentation + /// Image URL /// -/// Returns a URL for the given image filename +/// If a custom image-url handler is defined ($govuk-image-url-function) then +/// it will be called, otherwise a url will be returned with the filename +/// appended to the image path. +/// +/// @param {String} Filename for the image to load +/// @return {String} URL for the filename, wrapped in `url()` @function govuk-image-url($filename) { - @return url($govuk-images-path + $filename); + $use-custom-function: variable-exists("govuk-image-url-function") + and $govuk-image-url-function + and function-exists($govuk-image-url-function); + + @if ($use-custom-function) { + @return call($govuk-image-url-function, $filename); + } @else { + @return url($govuk-images-path + $filename); + } } diff --git a/src/tools/font-url.test.js b/src/tools/font-url.test.js new file mode 100644 index 0000000000..f328aa1f87 --- /dev/null +++ b/src/tools/font-url.test.js @@ -0,0 +1,74 @@ +/* eslint-env jest */ + +const util = require('util') + +const configPaths = require('../../config/paths.json') + +const sass = require('node-sass') +const sassRender = util.promisify(sass.render) + +const sassConfig = { + includePaths: [ configPaths.src ], + outputStyle: 'compressed' +} + +describe('@function font-url', () => { + it('by default concatenates the font path and the filename', async () => { + const sass = ` + @import "tools/font-url"; + + $govuk-fonts-path: '/path/to/fonts/'; + + @font-face { + font-family: "whatever"; + src: govuk-font-url("whatever.woff2"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '@font-face{font-family:"whatever";src:url("/path/to/fonts/whatever.woff2")}' + ) + }) + + it('can be overridden to use a defined Sass function', async () => { + const sass = ` + @import "tools/font-url"; + + $govuk-font-url-function: 'to_upper_case'; + + @font-face { + font-family: "whatever"; + src: govuk-font-url("whatever.woff2"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '@font-face{font-family:"whatever";src:"WHATEVER.WOFF2"}' + ) + }) + + it('can be overridden to use a custom function', async () => { + const sass = ` + @import "tools/font-url"; + + @function custom-url-handler($filename) { + @return url("/custom/#{$filename}"); + } + + $govuk-fonts-path: '/assets/fonts/'; + $govuk-font-url-function: 'custom-url-handler'; + + @font-face { + font-family: "whatever"; + src: govuk-font-url("whatever.woff2"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '@font-face{font-family:"whatever";src:url("/custom/whatever.woff2")}' + ) + }) +}) diff --git a/src/tools/image-url.test.js b/src/tools/image-url.test.js new file mode 100644 index 0000000000..8fc6ac4de3 --- /dev/null +++ b/src/tools/image-url.test.js @@ -0,0 +1,71 @@ +/* eslint-env jest */ + +const util = require('util') + +const configPaths = require('../../config/paths.json') + +const sass = require('node-sass') +const sassRender = util.promisify(sass.render) + +const sassConfig = { + includePaths: [ configPaths.src ], + outputStyle: 'compressed' +} + +describe('@function image-url', () => { + it('by default concatenates the image path and the filename', async () => { + const sass = ` + @import "tools/image-url"; + + $govuk-images-path: '/path/to/images/'; + + .foo { + background-image: govuk-image-url("baz.png"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '.foo{background-image:url("/path/to/images/baz.png")}' + ) + }) + + it('can be overridden to use a defined Sass function', async () => { + const sass = ` + @import "tools/image-url"; + + $govuk-image-url-function: 'to_upper_case'; + + .foo { + background-image: govuk-image-url("baz.png"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '.foo{background-image:"BAZ.PNG"}' + ) + }) + + it('can be overridden to use a custom function', async () => { + const sass = ` + @import "tools/image-url"; + + @function custom-url-handler($filename) { + @return url("/custom/#{$filename}"); + } + + $govuk-images-path: '/assets/fonts/'; + $govuk-image-url-function: 'custom-url-handler'; + + .foo { + background-image: govuk-image-url("baz.png"); + }` + + const results = await sassRender({ data: sass, ...sassConfig }) + + expect(results.css.toString().trim()).toEqual( + '.foo{background-image:url("/custom/baz.png")}' + ) + }) +}) From 5720a1c4bf5df9374213ec09af9c80436805c495 Mon Sep 17 00:00:00 2001 From: Oliver Byford Date: Wed, 30 May 2018 09:51:55 +0100 Subject: [PATCH 2/3] Use correct Rails functions in examples --- src/settings/_assets.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/settings/_assets.scss b/src/settings/_assets.scss index b1e1da2e94..c937f7a36b 100644 --- a/src/settings/_assets.scss +++ b/src/settings/_assets.scss @@ -31,8 +31,8 @@ $govuk-fonts-path: "#{$govuk-assets-path}fonts/" !default; /// /// @type String /// -/// @example scss - Ruby asset handling -/// $govuk-image-url-function: 'asset-url'; +/// @example scss - Rails asset handling +/// $govuk-image-url-function: 'image-url'; /// /// @example scss - Custom asset handling /// @@ -55,8 +55,8 @@ $govuk-image-url-function: false !default; /// /// @type String /// -/// @example scss - Ruby asset handling -/// $govuk-font-url-function: 'asset-url'; +/// @example scss - Rails asset handling +/// $govuk-font-url-function: 'font-url'; /// /// @example scss - Custom asset handling /// From 17616e0e222780dfd31db5fcc99b9224f07aaff9 Mon Sep 17 00:00:00 2001 From: Oliver Byford Date: Wed, 30 May 2018 10:26:52 +0100 Subject: [PATCH 3/3] Document custom asset url helpers in CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d988ba78e6..5ee0a86883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,12 @@ Note: We're not following semantic versioning yet, we are going to talk about th browser will then swap to NTA as long as it loads within the short swap period. ([PR #726](https://github.com/alphagov/govuk-frontend/pull/726)) +- You can now override the helpers used to generate image and font urls, for + example if you are using sass-rails' asset-pipeline functionality. + You can do this by setting `$govuk-image-url-function` and + `$govuk-font-url-function` to the name of the function(s) you wish to use. + See `src/settings/_assets.scss` for more information and examples. + ([PR #733](https://github.com/alphagov/govuk-frontend/pull/733)) 🏠 Internal: