UNPKG

3.2 kBJavaScriptView Raw
1const { existsSync } = require('fs-extra')
2const path = require('path')
3const Jimp = require('jimp')
4const { joinUrl, getRouteParams } = require('@nuxtjs/pwa-utils')
5
6module.exports = function nuxtIcon (options) {
7 const hook = () => {
8 return generateIcons.call(this, options)
9 }
10
11 if (this.options.mode === 'spa') {
12 return hook()
13 }
14
15 this.nuxt.hook('build:before', hook)
16}
17
18const defaults = {
19 iconSrc: null,
20 iconFileName: 'icon.png',
21 sizes: [64, 120, 144, 152, 192, 384, 512],
22 targetDir: 'icons'
23}
24
25function generateIcons (moduleOptions) {
26 // Combine sources
27 const options = Object.assign({}, defaults, this.options.icon, moduleOptions)
28
29 const { publicPath } = getRouteParams(this.options)
30
31 // Resolve iconSrc
32 let iconSrc
33
34 const iconSearchPath = [
35 options.iconSrc,
36 path.resolve(this.options.srcDir, this.options.dir.static, options.iconFileName),
37 path.resolve(this.options.srcDir, this.options.dir.assets, options.iconFileName)
38 ]
39
40 for (const p of iconSearchPath) {
41 if (existsSync(p)) {
42 iconSrc = p
43 break
44 }
45 }
46
47 // Ensure icon file exists
48 if (!existsSync(iconSrc)) {
49 return
50 }
51
52 return Jimp.read(iconSrc).then(srcIcon => {
53 // get base64 phash of source image
54 const hash = srcIcon.hash()
55 return Promise.all(options.sizes.map(size => new Promise((resolve, reject) => {
56 srcIcon.clone().contain(size, size).getBuffer(Jimp.MIME_PNG, (err, buff) => {
57 if (err) {
58 return reject(err)
59 }
60 const fileName = `${options.targetDir}/icon_${size}.${hash}.png`
61 resolve({ size, buff, fileName })
62 })
63 }))).then(icons => {
64 // Fill manifest icons
65 if (!this.options.manifest) {
66 this.options.manifest = {}
67 }
68 if (!this.options.manifest.icons) {
69 this.options.manifest.icons = []
70 }
71 const assetIcons = []
72 const exportIcons = {}
73 icons.forEach(icon => {
74 const src = joinUrl(publicPath, icon.fileName)
75 assetIcons.push({
76 src,
77 sizes: `${icon.size}x${icon.size}`,
78 type: `image/png`
79 })
80
81 exportIcons[icon.size] = src
82 })
83
84 assetIcons.forEach(icon => { this.options.manifest.icons.push(icon) })
85
86 // Add plugin to Vue to access icons
87 let moduleOptions = Object.assign({
88 accessibleIcons: true,
89 iconProperty: '$icon',
90 icons: exportIcons
91 }, options)
92
93 if (moduleOptions.accessibleIcons) {
94 this.addPlugin({
95 src: path.resolve(__dirname, './plugin.js'),
96 fileName: 'nuxt-icons.js',
97 options: moduleOptions
98 })
99 }
100
101 // Register webpack plugin to emit icons
102 this.options.build.plugins.push({
103 apply (compiler) {
104 compiler.hooks.emit.tap('nuxt-pwa-icon', compilation => {
105 icons.forEach(icon => {
106 compilation.assets[icon.fileName] = {
107 source: () => icon.buff,
108 size: () => icon.buff.length
109 }
110 })
111 })
112 }
113 })
114 })
115 }).catch(err => {
116 console.error('[icon] unable to read', err)
117 })
118}
119
120module.exports.meta = require('./package.json')