Skip to content

Commit 9248174

Browse files
hans00pi0
andauthored
feat(icon): add support for icon purpose (#246)
Co-authored-by: Pooya Parsa <pyapar@gmail.com>
1 parent 7a48d2a commit 9248174

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

docs/modules/icon.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,16 @@ Will return an empty string when no icon in the given size is available (eg. whe
4848
- Default: '$icon'
4949

5050
Name of property for accessible icons.
51+
52+
**purpose**
53+
- Default: null
54+
55+
Array or string of icon purpose.
56+
Example:
57+
```js
58+
purpose: [ 'badge', 'maskable' ]
59+
// or
60+
purpose: 'maskable'
61+
```
62+
63+
More detail of "purpose": https://w3c.github.io/manifest/#purpose-member

lib/icon/module.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ async function run (pwa, _emitAssets) {
2424
iconProperty: '$icon',
2525
publicPath,
2626
iconSrc: null,
27+
purpose: null,
2728

2829
_iconHash: null,
2930
_cacheDir: null,
@@ -45,6 +46,18 @@ async function run (pwa, _emitAssets) {
4546
return
4647
}
4748

49+
// Verify purpose
50+
if (options.purpose) {
51+
const purpose = Array.isArray(options.purpose) ? options.purpose : [options.purpose]
52+
const len = purpose.length
53+
const validPurpose = ['badge', 'maskable', 'any']
54+
options.purpose = purpose.filter(item => validPurpose.includes(item))
55+
if (len !== options.purpose.len) {
56+
// eslint-disable-next-line no-console
57+
console.warn('[pwa] [icon] Some invalid items removed from `options.purpose`. Valid values: ' + validPurpose)
58+
}
59+
}
60+
4861
// Generate icons
4962
await generateIcons.call(this, options)
5063

@@ -109,11 +122,15 @@ async function generateIcons (options) {
109122
options._icons[size] = `${options.targetDir}/icon_${size}.${options.iconHash}.png`
110123
}
111124

125+
// Generate _purpose
126+
const purpose = options.purpose ? options.purpose.join(' ') : undefined
127+
112128
// Generate _assetIcons
113129
options._assetIcons = options.sizes.map(size => ({
114130
src: joinUrl(options.publicPath, options._icons[size]),
115131
sizes: `${size}x${size}`,
116-
type: 'image/png'
132+
type: 'image/png',
133+
purpose
117134
}))
118135
}
119136

test/fixture/nuxt.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ module.exports = {
66
{ handler: require('../../') }
77
],
88

9+
icon: {
10+
purpose: 'maskable'
11+
},
12+
913
manifest: {
1014
name: 'Test Project Name',
1115
description: 'Test Project Description'

test/pwa.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ describe('pwa', () => {
3434
expect(html).toContain('/_nuxt/icons/icon_512.b8f3a1.png')
3535
})
3636

37+
test('icons purpose', () => {
38+
const assetDir = path.join(nuxt.options.generate.dir, '_nuxt')
39+
const manifestFileName = fs.readdirSync(assetDir).find(item => item.match(/^manifest.+\.json$/i))
40+
const manifestContent = JSON.parse(fs.readFileSync(path.join(assetDir, manifestFileName)))
41+
expect(manifestContent.icons).toEqual(
42+
expect.arrayContaining([
43+
expect.objectContaining({
44+
purpose: expect.stringMatching(/( ?(any|maskable|badge))+/)
45+
})
46+
])
47+
)
48+
})
49+
3750
test('sw.js', async () => {
3851
const swContents = await fs.readFile(path.resolve(nuxt.options.generate.dir, 'sw.js'), 'utf-8')
3952

0 commit comments

Comments
 (0)