diff --git a/cypress/e2e/smoke/0-smoke-tests/index-page.cypress.js b/cypress/e2e/smoke/0-smoke-tests/index-page.cypress.js index 5de33e60cd..93d987f925 100644 --- a/cypress/e2e/smoke/0-smoke-tests/index-page.cypress.js +++ b/cypress/e2e/smoke/0-smoke-tests/index-page.cypress.js @@ -11,7 +11,7 @@ describe('smoke test', () => { it('GOV.UK Frontend fonts loaded', () => { waitForApplication('/') - const fontUrl = '/plugin-assets/govuk-frontend/govuk/assets/fonts/bold-b542beb274-v2.woff2' + const fontUrl = `/plugin-assets/govuk-frontend${Cypress.env('frontendAssetsFolder')}/fonts/bold-b542beb274-v2.woff2` cy.task('log', 'Requesting govuk-frontend font') cy.request(`/${fontUrl}`, { retryOnStatusCodeFailure: true }) diff --git a/cypress/events/index.js b/cypress/events/index.js index 5c7bb6379c..9f0e73f866 100644 --- a/cypress/events/index.js +++ b/cypress/events/index.js @@ -74,6 +74,11 @@ module.exports = function setupNodeEvents (on, config) { config.env.packageFolder = path.join(config.env.projectFolder, 'node_modules', 'govuk-prototype-kit') } + if ('govuk-frontend' in dependencies) { + const frontEndConfigFile = path.join(config.env.projectFolder, 'node_modules', 'govuk-frontend', 'govuk-prototype-kit.config.json') + config.env.frontendAssetsFolder = fse.readJsonSync(frontEndConfigFile).assets.find(asset => !asset.split(path.sep).pop().includes('.')) + } + const waitUntilAppRestarts = (timeout = 20000) => waitOn({ delay: 3000, resources: [config.baseUrl], diff --git a/lib/manage-prototype-handlers.js b/lib/manage-prototype-handlers.js index b6defcc838..dd8c9f7ee5 100644 --- a/lib/manage-prototype-handlers.js +++ b/lib/manage-prototype-handlers.js @@ -10,7 +10,7 @@ const { doubleCsrf } = require('csrf-csrf') const config = require('./config') const plugins = require('./plugins/plugins') const { exec } = require('./exec') -const { prototypeAppScripts } = require('./utils') +const { prototypeAppScripts, getScriptsAndAssetsConfig, getInternalGovukFrontendDir } = require('./utils') const { projectDir, packageDir, appViewsDir } = require('./utils/paths') const nunjucksConfiguration = require('./nunjucks/nunjucksConfiguration') const syncChanges = require('./sync-changes') @@ -103,7 +103,7 @@ function postPasswordHandler (req, res) { const password = config.getConfig().password const submittedPassword = req.body.password const providedUrl = req.body.returnURL - const processedRedirectUrl = (!providedUrl || providedUrl.startsWith('/manage-prototype/password')) ? '/' : providedUrl + const processedRedirectUrl = (!providedUrl || providedUrl.startsWith(`${contextPath}/password`)) ? '/' : providedUrl if (submittedPassword === password) { // see lib/middleware/authentication.js for explanation @@ -115,10 +115,26 @@ function postPasswordHandler (req, res) { }) res.redirect(processedRedirectUrl) } else { - res.redirect('/manage-prototype/password?error=wrong-password&returnURL=' + encodeURIComponent(processedRedirectUrl)) + res.redirect(`${contextPath}/password?error=wrong-password&returnURL=` + encodeURIComponent(processedRedirectUrl)) } } +function managePluginsMiddleware (req, res, next) { + const { scripts: frontEndScripts } = getScriptsAndAssetsConfig(getInternalGovukFrontendDir()) + const { scripts: kitScripts } = getScriptsAndAssetsConfig(packageDir) + res.locals.managePlugins = { + scripts: [ + ...frontEndScripts.map((script) => { + return { src: `${contextPath}/dependencies/govuk-frontend${script.src || script}`, type: script.type } + }), + ...kitScripts.map((script) => { + return { src: `${contextPath}/dependencies/govuk-prototype-kit${script.src || script}`, type: script.type } + }) + ] + } + next() +} + // Middleware to ensure the routes specified below will render the manage-prototype-not-available // view when the prototype is not running in development function developmentOnlyMiddleware (req, res, next) { @@ -728,6 +744,7 @@ async function postPluginsModeHandler (req, res) { module.exports = { contextPath, + managePluginsMiddleware, setKitRestarted, csrfProtection: [doubleCsrfProtection, csrfErrorHandler], getPageLoadedHandler, diff --git a/lib/manage-prototype-routes.js b/lib/manage-prototype-routes.js index 5ad9460d12..c77a18d2c3 100644 --- a/lib/manage-prototype-routes.js +++ b/lib/manage-prototype-routes.js @@ -1,8 +1,12 @@ +// core dependencies +const path = require('path') + // npm dependencies const express = require('express') const { contextPath, + managePluginsMiddleware, setKitRestarted, csrfProtection, getPageLoadedHandler, @@ -26,11 +30,31 @@ const { pluginCacheMiddleware, postPluginsHandler } = require('./manage-prototype-handlers') -const path = require('path') -const { getInternalGovukFrontendDir } = require('./utils') + +const { getInternalGovukFrontendDir, getScriptsAndAssetsConfig } = require('./utils') +const { packageDir } = require('./utils/paths') const router = require('../index').requests.setupRouter(contextPath) +router.use(managePluginsMiddleware) + +function getAssetUrls (pluginDir) { + const { scripts, assets } = getScriptsAndAssetsConfig(pluginDir) + + return [ + ...assets, + ...scripts.map(script => script.src || script) + ] +} + +getAssetUrls(getInternalGovukFrontendDir()).forEach(url => { + router.use(`/dependencies/govuk-frontend${url}`, express.static(path.join(getInternalGovukFrontendDir(), url))) +}) + +getAssetUrls(packageDir).forEach(url => { + router.use(`/dependencies/govuk-prototype-kit${url}`, express.static(path.join(packageDir, url))) +}) + router.get('/csrf-token', getCsrfTokenHandler) // Indicates page has loaded @@ -79,15 +103,6 @@ router.post('/plugins/:mode', postPluginsModeMiddleware) router.post('/plugins/:mode', csrfProtection, postPluginsModeHandler) -const partialGovukFrontendUrls = [ - 'govuk/assets', - 'govuk/all.js', - 'govuk-prototype-kit/init.js' -] -partialGovukFrontendUrls.forEach(url => { - router.use(`/dependencies/govuk-frontend/${url}`, express.static(path.join(getInternalGovukFrontendDir(), url))) -}) - setKitRestarted(true) module.exports = router diff --git a/lib/nunjucks/views/manage-prototype/scripts.njk b/lib/nunjucks/views/manage-prototype/scripts.njk index 92673dbc78..9fc2b3a1c7 100644 --- a/lib/nunjucks/views/manage-prototype/scripts.njk +++ b/lib/nunjucks/views/manage-prototype/scripts.njk @@ -1,3 +1,8 @@ - - - +{% for scriptConfig in managePlugins.scripts %} + {% if scriptConfig.type|length %} + + {% else %} + + {% endif %} +{% endfor %} + diff --git a/lib/utils/index.js b/lib/utils/index.js index 594172d3ec..71cfa4c05d 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -264,6 +264,23 @@ function getInternalGovukFrontendDir () { return internalGovukFrontendDir } +function getScriptsAndAssetsConfig (pluginDir) { + let { + assets = [], + scripts = [] + } = fse.readJsonSync(path.join(pluginDir, 'govuk-prototype-kit.config.json')) + + if (!Array.isArray(assets)) { + assets = [assets] + } + + if (!Array.isArray(scripts)) { + scripts = [scripts] + } + + return { assets, scripts } +} + function sortByObjectKey (key) { return function (a, b) { if (a[key] > b[key]) { @@ -291,5 +308,6 @@ module.exports = { searchAndReplaceFiles, recursiveDirectoryContentsSync, getInternalGovukFrontendDir, + getScriptsAndAssetsConfig, sortByObjectKey }