Skip to content

Commit

Permalink
Merge pull request #2088 from alphagov/implement-script-type-equals-m…
Browse files Browse the repository at this point in the history
…odule

Plugin authors can now use scripts with type module
  • Loading branch information
BenSurgisonGDS committed Apr 6, 2023
2 parents beedf23 + d2f8fda commit e8dfa4e
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,10 @@ describe('Single Plugin Test', async () => {
cy.get('.plugin-foo').should('have.css', 'background-color', BLUE)
cy.get('.plugin-foo').should('have.css', 'border-color', WHITE)
})

it('Loads plugin-foo module correctly', () => {
waitForApplication()
cy.visit('/plugin-foo')
cy.get('#foo-module').contains('The foo result is: 3')
})
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"assets": [
"/scripts"
],
"nunjucksFilters": [
"/filters.js"
],
Expand All @@ -10,7 +13,11 @@
"/macros"
],
"scripts": [
"/scripts/foo.js"
"/scripts/foo.js",
{
"path": "/scripts/foo-module.js",
"type": "module"
}
],
"sass": [
"/sass/foo.scss"
Expand Down
10 changes: 10 additions & 0 deletions cypress/fixtures/plugins/plugin-foo/scripts/foo-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import fooSubmodule from './foo-submodule.js'

const fooParagraph = document.getElementById('foo-module')

if (fooParagraph) {
fooParagraph.hidden = false
setTimeout(() => {
fooParagraph.innerHTML = 'The foo result is: ' + fooSubmodule(1, 2)
}, 500)
}
3 changes: 3 additions & 0 deletions cypress/fixtures/plugins/plugin-foo/scripts/foo-submodule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function fooSubmodule (x, y) {
return x + y
}
1 change: 1 addition & 0 deletions cypress/fixtures/plugins/plugin-foo/views/foo.njk
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
<h1 class="test-foo">Plugin Foo</h1>
<p hidden id='foo-module'>calculating</p>
8 changes: 6 additions & 2 deletions lib/nunjucks/govuk-prototype-kit/includes/scripts.njk
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{% for scriptUrl in pluginConfig.scripts %}
<script src="{{scriptUrl}}"></script>
{% for scriptConfig in pluginConfig.scripts %}
{% if scriptConfig.type|length %}
<script type="{{scriptConfig.type}}" src="{{scriptConfig.src}}"></script>
{% else %}
<script src="{{scriptConfig.src}}"></script>
{% endif %}
{% endfor %}
39 changes: 26 additions & 13 deletions lib/plugins/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,21 @@ const getPublicUrl = config => {
.join('/')
}

function getFileSystemPath (config) {
throwIfBadFilepath(config)
function getFileSystemPath ({ packageName, item }) {
// item will either be the plugin path or will be an object containing the plugin path within the src property
item = item.path || item
throwIfBadFilepath({ packageName, item })
return getPathFromProjectRoot('node_modules',
config.packageName,
config.item.split('/').filter(filterOutParentAndEmpty).join(path.sep))
packageName,
item.split('/').filter(filterOutParentAndEmpty).join(path.sep))
}

function getPublicUrlAndFileSystemPath (config) {
function getPublicUrlAndFileSystemPath ({ packageName, item }) {
// item will either be the plugin path or will be an object containing the plugin path within the src property
item = item.path || item
return {
fileSystemPath: getFileSystemPath(config),
publicUrl: getPublicUrl(config)
fileSystemPath: getFileSystemPath({ packageName, item }),
publicUrl: getPublicUrl({ packageName, item })
}
}

Expand Down Expand Up @@ -308,17 +312,26 @@ const getByType = type => getList(type)

/**
* Gets public urls for all plugins of type
* @param {string} type - (scripts, stylesheets, nunjucks etc)
* @param {string} listType - (scripts, stylesheets, nunjucks etc)
* @return {string[]} A list of urls
*/
const getPublicUrls = type => getList(type).map(getPublicUrl)
const getPublicUrls = listType => getList(listType).map(({ packageName, item }) => {
// item will either be the plugin path or will be an object containing the plugin path within the src property
if (listType === 'scripts' && typeof item === 'object') {
const { path, type } = item
const publicUrl = getPublicUrl({ packageName, item: path })
return { src: publicUrl, type }
} else {
return getPublicUrl({ packageName, item })
}
})

/**
* Gets filesystem paths for all plugins of type
* @param {string} type - (scripts, stylesheets, nunjucks etc)
* @param {string} listType - (scripts, stylesheets, nunjucks etc)
* @return {string[]} An array of filesystem paths
*/
const getFileSystemPaths = type => getList(type).map(getFileSystemPath)
const getFileSystemPaths = listType => getList(listType).map(getFileSystemPath)

/**
* Gets public urls and filesystem paths for all plugins of type
Expand All @@ -330,12 +343,12 @@ const getPublicUrlAndFileSystemPaths = type => getList(type).map(getPublicUrlAnd
/**
* This is used in the views to output links and scripts for each file
* @param {{scripts: string[], stylesheets: string[]}} additionalConfig
* @return {{scripts: string[], stylesheets: string[]}} Returns an object containing two keys(scripts & stylesheets),
* @return {{scripts: {src: string, type: string}[], stylesheets: string[]}} Returns an object containing two keys(scripts & stylesheets),
* each item contains an array of full paths to specific files.
*/
function getAppConfig (additionalConfig) {
return {
scripts: self.getPublicUrls('scripts').concat((additionalConfig || {}).scripts || []),
scripts: self.getPublicUrls('scripts').concat((additionalConfig || {}).scripts || []).map((item) => typeof item === 'string' ? { src: item } : item),
stylesheets: self.getPublicUrls('stylesheets').concat((additionalConfig || {}).stylesheets || [])
}
}
Expand Down
28 changes: 18 additions & 10 deletions lib/plugins/plugins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ describe('plugins', () => {
})
it('should not include scripts for jQuery if it is not installed', () => {
expect(plugins.getAppConfig().scripts).toEqual([
'/plugin-assets/jquery/dist/jquery.js'
{ src: '/plugin-assets/jquery/dist/jquery.js' }
])
})
})
Expand All @@ -385,7 +385,7 @@ describe('plugins', () => {

it('should return a list of public urls for the scripts', () => {
expect(plugins.getAppConfig().scripts).toEqual([
'/plugin-assets/govuk-frontend/govuk/all.js'
{ src: '/plugin-assets/govuk-frontend/govuk/all.js' }
])
})

Expand All @@ -396,16 +396,24 @@ describe('plugins', () => {
it('should include installed plugins where scripts config is a string array', () => {
mockPluginConfig('my-plugin', { scripts: ['/abc/def/ghi.js'] })
expect(plugins.getAppConfig().scripts).toEqual([
'/plugin-assets/govuk-frontend/govuk/all.js',
'/plugin-assets/my-plugin/abc/def/ghi.js'
{ src: '/plugin-assets/govuk-frontend/govuk/all.js' },
{ src: '/plugin-assets/my-plugin/abc/def/ghi.js' }
])
})

it('should include installed plugins where scripts config is a string', () => {
mockPluginConfig('my-plugin', { scripts: '/ab/cd/ef/ghi.js' })
expect(plugins.getAppConfig().scripts).toEqual([
'/plugin-assets/govuk-frontend/govuk/all.js',
'/plugin-assets/my-plugin/ab/cd/ef/ghi.js'
{ src: '/plugin-assets/govuk-frontend/govuk/all.js' },
{ src: '/plugin-assets/my-plugin/ab/cd/ef/ghi.js' }
])
})

it('should include installed plugins where scripts config is an object including type', () => {
mockPluginConfig('my-plugin', { scripts: { path: '/ab/cd/ef/ghi.js', type: 'module' } })
expect(plugins.getAppConfig().scripts).toEqual([
{ src: '/plugin-assets/govuk-frontend/govuk/all.js' },
{ src: '/plugin-assets/my-plugin/ab/cd/ef/ghi.js', type: 'module' }
])
})

Expand All @@ -429,10 +437,10 @@ describe('plugins', () => {
'/b.css'
],
scripts: [
'/plugin-assets/govuk-frontend/govuk/all.js',
'/plugin-assets/my-plugin/jkl/mno/pqr.js',
'/d.js',
'e.js'
{ src: '/plugin-assets/govuk-frontend/govuk/all.js' },
{ src: '/plugin-assets/my-plugin/jkl/mno/pqr.js' },
{ src: '/d.js' },
{ src: 'e.js' }
]
})
})
Expand Down

0 comments on commit e8dfa4e

Please sign in to comment.