diff --git a/CHANGELOG.md b/CHANGELOG.md index e61939ab26..b7a0002dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ New features: - [#568 Update GOV.UK Frontend to 1.2.0](https://github.com/alphagov/govuk-prototype-kit/pull/568) - [#563 Add Nunjucks macro example to 'passing data' guidance](https://github.com/alphagov/govuk-prototype-kit/pull/563) +- [#553 Add backwards compatibility - support for prototypes made in Version 6 of the Prototype Kit](https://github.com/alphagov/govuk-prototype-kit/pull/553) - [#557 Bump outdated dependencies](https://github.com/alphagov/govuk-prototype-kit/pull/557): - Update standard from 10.0.2 to 11.0.1 and fix violations - Update run-sequence from 1.2.2 to 2.2.1 diff --git a/docs/assets/images/docs/backwards-compatibility-atom.png b/docs/assets/images/docs/backwards-compatibility-atom.png new file mode 100755 index 0000000000..a59bdb3fa0 Binary files /dev/null and b/docs/assets/images/docs/backwards-compatibility-atom.png differ diff --git a/docs/assets/sass/docs.scss b/docs/assets/sass/docs.scss index 8d44a90550..138d7f9ab0 100644 --- a/docs/assets/sass/docs.scss +++ b/docs/assets/sass/docs.scss @@ -1,5 +1,9 @@ @import "node_modules/govuk-frontend/all"; +img{ + max-width: 100%; +} + // adjust code block font-size to 19px .hljs { font-size: 19px; @@ -87,7 +91,7 @@ pre { @extend .app-code; } - + p code { border: 1px solid $govuk-border-colour; background-color: govuk-colour("grey-4"); diff --git a/docs/documentation/backwards-compatibility.md b/docs/documentation/backwards-compatibility.md new file mode 100644 index 0000000000..282b474b6c --- /dev/null +++ b/docs/documentation/backwards-compatibility.md @@ -0,0 +1,61 @@ +# Using backwards compatibility + +Version 7 of the Prototype Kit uses the new GOV.UK Design System. It is not compatible with prototypes built with older versions by default. + +Backwards compatibility lets you import a large old prototype into version 7, without having to rewrite it. You can update old pages one by one as you need to, and add new pages. + +You will end up with 2 'apps' in your prototype: + +**/app** using version 7 + +**/app/v6** using version 6 + +If any pages or routes exist in both apps, the one in version 7 will win. + +## Instructions + +1. Make a note of your Prototype Kit version in **VERSION.txt** in your prototype folder. + +1. Make sure you have a backup of your prototype folder, for example by copying it to another folder or by uploading to GitHub. + +1. Delete everything in your prototype folder except for the **app** and **.git** folders. (.git may be hidden). + +1. Rename your **app** folder to **v6** + +1. Find and replace all instances of **/public/** to **/public/v6/** in your code. +In Atom, press **cmd shift F**. It looks like this: +![Screenshot of Atom find and replace](/public/images/docs/backwards-compatibility-atom.png) + +1. [Download the latest Prototype Kit](/docs/download) and unzip it. + +1. Copy everything from the new Prototype Kit folder into your prototype folder. + +1. Move your **v6** folder into the new **app** folder. + +1. Update **app/config.js** to your settings, in particular the **serviceName**. You can then safely remove **app/v6/config.js**. + +1. On the command line, in your prototype folder, run **npm install**, then **npm start**. + +1. If your previous Prototype Kit version was older than 6.3.0, follow the guidance below about updating from older versions. + +## Updating pages to use version 7 + +You can now create new pages using version 7 by working in the app/views folder. + +You can update old pages by moving them from app/v6/views to app/views. You will then need to update the code on these pages to work with version 7. See the [updating your code guide in the GOV.UK Design System](https://design-system.service.gov.uk/get-started/updating-your-code/). + +## Updating from versions older than 6.3.0 + +The instructions above are for updating from version 6.3.0 of the Prototype Kit. If you had an older version, follow the normal instructions then run the commands below: + +### 6.2.0 + +``` +npm install govuk-elements-sass@3.0.1 govuk_frontend_toolkit@5.1.2 govuk_template_jinja@0.22.1 +``` + +### 6.1.0 or 6.0.0 + +``` +npm install govuk-elements-sass@3.0.1 govuk_frontend_toolkit@5.1.2 govuk_template_jinja@0.19.2 +``` diff --git a/docs/documentation/updating-the-kit.md b/docs/documentation/updating-the-kit.md index f0b127df68..f15fd7cc2f 100644 --- a/docs/documentation/updating-the-kit.md +++ b/docs/documentation/updating-the-kit.md @@ -4,11 +4,11 @@ If you have made any changes outside the `app` folder, this process will destroy those changes. We will try and improve the update process to avoid this, but in the meantime you will need to make a note of your changes outside `app`, and add them back after updating. -## Version 7 +## Updating from version 6 to version 7 -Version 7 of the GOV.UK Prototype Kit is a large change from previous versions. Updating an old prototype will mean re-writing most of the code. +Version 7 of the GOV.UK Prototype Kit is a large change from previous versions. -We are working on ways to make updating easier, so if you have a large prototype it may be worth waiting for that. +If you have a large old prototype, follow this [guide to backward compatibility](/docs/backwards-compatibility) which lets you update the Prototype Kit without having to rewrite all your pages at once. There is a [guide to updating your code](https://design-system.service.gov.uk/get-started/updating-your-code/) on the GOV.UK Design System. diff --git a/gulp/config.json b/gulp/config.json index 6dcfe82b98..31cae7eb02 100644 --- a/gulp/config.json +++ b/gulp/config.json @@ -3,6 +3,7 @@ "public": "public/", "assets" : "app/assets/", "docsAssets" : "docs/assets/", + "v6Assets": "app/v6/assets/", "nodeModules": "node_modules/", "lib": "lib/" } diff --git a/gulp/copy-assets.js b/gulp/copy-assets.js index aae7f58f80..fbe57c6988 100644 --- a/gulp/copy-assets.js +++ b/gulp/copy-assets.js @@ -13,8 +13,14 @@ gulp.task('copy-assets', function () { .pipe(gulp.dest(config.paths.public)) }) -gulp.task('copy-documentation-assets', function () { +gulp.task('copy-assets-documentation', function () { return gulp.src(['!' + config.paths.docsAssets + 'sass{,/**/*}', config.paths.docsAssets + '/**']) .pipe(gulp.dest(config.paths.public)) }) + +gulp.task('copy-assets-v6', function () { + return gulp.src(['!' + config.paths.v6Assets + 'sass{,/**/*}', + config.paths.v6Assets + '/**']) + .pipe(gulp.dest(config.paths.public + '/v6')) +}) diff --git a/gulp/sass.js b/gulp/sass.js index 934d3be3a5..022e9e59fb 100644 --- a/gulp/sass.js +++ b/gulp/sass.js @@ -26,3 +26,20 @@ gulp.task('sass-documentation', function () { .pipe(sourcemaps.write()) .pipe(gulp.dest(config.paths.public + '/stylesheets/')) }) + +// Backward compatibility with Elements + +gulp.task('sass-v6', function () { + return gulp.src(config.paths.v6Assets + '/sass/*.scss') + .pipe(sourcemaps.init()) + .pipe(sass({ + outputStyle: 'expanded', + includePaths: [ + 'node_modules/govuk_frontend_toolkit/stylesheets', + 'node_modules/govuk-elements-sass/public/sass', + 'node_modules/govuk_template_jinja/assets/stylesheets' + ] + }).on('error', sass.logError)) + .pipe(sourcemaps.write()) + .pipe(gulp.dest(config.paths.public + '/v6/stylesheets/')) +}) diff --git a/gulp/tasks.js b/gulp/tasks.js index a912d99062..24980f2694 100644 --- a/gulp/tasks.js +++ b/gulp/tasks.js @@ -17,14 +17,18 @@ gulp.task('default', function (done) { gulp.task('generate-assets', function (done) { runSequence('clean', 'sass', - 'sass-documentation', 'copy-assets', - 'copy-documentation-assets', done) + 'sass-documentation', + 'copy-assets-documentation', + 'sass-v6', + 'copy-assets-v6', done) }) gulp.task('watch', function (done) { runSequence('watch-sass', - 'watch-assets', done) + 'watch-assets', + 'watch-sass-v6', + 'watch-assets-v6', done) }) gulp.task('test', function () { diff --git a/gulp/watch.js b/gulp/watch.js index 1e90dd9788..2c3e15fedb 100644 --- a/gulp/watch.js +++ b/gulp/watch.js @@ -15,3 +15,14 @@ gulp.task('watch-assets', function () { return gulp.watch([config.paths.assets + 'images/**', config.paths.assets + 'javascripts/**'], {cwd: './'}, ['copy-assets']) }) + +// Backward compatibility with Elements + +gulp.task('watch-sass-v6', function () { + return gulp.watch(config.paths.v6Assets + 'sass/**', {cwd: './'}, ['sass-v6']) +}) + +gulp.task('watch-assets-v6', function () { + return gulp.watch([config.paths.v6Assets + 'images/**', + config.paths.v6Assets + 'javascripts/**'], {cwd: './'}, ['copy-assets-v6']) +}) diff --git a/lib/v6/govuk_template_unbranded.html b/lib/v6/govuk_template_unbranded.html new file mode 100644 index 0000000000..905f241048 --- /dev/null +++ b/lib/v6/govuk_template_unbranded.html @@ -0,0 +1,74 @@ +{% block top_of_page %}{% endblock %} + + + + + + {% block page_title %}{% endblock %} + + + + + + + + + + + + + + + + + + + + + + + {% block head %}{% endblock %} + + + + + + {% block body_start %}{% endblock %} + + + + + + + + + + + + {% block after_header %}{% endblock %} + + {% block content %}{% endblock %} + + + + + + + + + + {% block body_end %}{% endblock %} + + + + diff --git a/package.json b/package.json index 3c7f13b344..0ce29f9766 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,10 @@ "express": "4.16.3", "express-session": "^1.13.0", "express-writer": "0.0.4", + "govuk-elements-sass": "^3.1.3", "govuk-frontend": "^1.2.0", + "govuk_frontend_toolkit": "^7.5.0", + "govuk_template_jinja": "^0.24.1", "gulp": "^3.9.1", "gulp-clean": "^0.4.0", "gulp-mocha": "^6.0.0", diff --git a/server.js b/server.js index 62cdfe2642..f00a2884d9 100644 --- a/server.js +++ b/server.js @@ -18,8 +18,27 @@ const packageJson = require('./package.json') const routes = require('./app/routes.js') const utils = require('./lib/utils.js') +// Variables for v6 backwards compatibility +// Set false by default, then turn on if we find /app/v6/routes.js +var useV6 = false +var v6App +var v6Routes + +try { + v6Routes = require('./app/v6/routes.js') + useV6 = true +} catch (e) { + // No routes.js in app/v6 so we can continue with useV6 false +} + const app = express() const documentationApp = express() + +if (useV6) { + console.log('/app/v6/routes.js detected - using v6 compatibility mode') + v6App = express() +} + dotenv.config() // Set cookies for use in cookie banner. @@ -123,6 +142,32 @@ app.use(bodyParser.urlencoded({ extended: true })) +// Set up v6 app for backwards compatibility +if (useV6) { + var v6Views = [ + path.join(__dirname, '/node_modules/govuk_template_jinja/views/layouts'), + path.join(__dirname, '/app/v6/views/'), + path.join(__dirname, '/lib/v6') // for old unbranded template + ] + + var nunjucksV6Env = nunjucks.configure(v6Views, { + autoescape: true, + express: v6App, + noCache: true, + watch: true + }) + // Nunjucks filters + utils.addNunjucksFilters(nunjucksV6Env) + + // Set views engine + v6App.set('view engine', 'html') + + // Backward compatibility with GOV.UK Elements + app.use('/public/v6/', express.static(path.join(__dirname, '/node_modules/govuk_template_jinja/assets'))) + app.use('/public/v6/', express.static(path.join(__dirname, '/node_modules/govuk_frontend_toolkit'))) + app.use('/public/v6/javascripts/govuk/', express.static(path.join(__dirname, '/node_modules/govuk_frontend_toolkit/javascripts/govuk/'))) +} + // Add global variable to determine if DoNotTrack is enabled. // This indicates a user has explicitly opted-out of tracking. // Therefore we can avoid injecting third-party scripts that do not respect this decision. @@ -158,7 +203,12 @@ app.use(session({ if (useAutoStoreData === 'true') { app.use(utils.autoStoreData) utils.addCheckedFunction(nunjucksAppEnv) - utils.addCheckedFunction(nunjucksDocumentationEnv) + if (useDocumentation) { + utils.addCheckedFunction(nunjucksDocumentationEnv) + } + if (useV6) { + utils.addCheckedFunction(nunjucksV6Env) + } } // Clear all data in session if you open /prototype-admin/clear-data @@ -219,6 +269,18 @@ if (useDocumentation) { documentationApp.use('/', documentationRoutes) } +if (useV6) { + // Clone app locals to v6 app locals + v6App.locals = Object.assign({}, app.locals) + v6App.locals.asset_path = '/public/v6/' + + // Create separate router for v6 + app.use('/', v6App) + + // Docs under the /docs namespace + v6App.use('/', v6Routes) +} + // Strip .html and .htm if provided app.get(/\.html?$/i, function (req, res) { var path = req.path @@ -244,6 +306,13 @@ if (useDocumentation) { }) } +if (useV6) { + // App folder routes get priority + v6App.get(/^([^.]+)$/, function (req, res, next) { + utils.matchRoutes(req, res, next) + }) +} + // Redirect all POSTs to GETs - this allows users to use POST for autoStoreData app.post(/^\/([^.]+)$/, function (req, res) { res.redirect('/' + req.params[0])