1 | const { existsSync } = require('fs-extra')
|
2 | const path = require('path')
|
3 | const Jimp = require('jimp')
|
4 | const { joinUrl, getRouteParams } = require('@nuxtjs/pwa-utils')
|
5 |
|
6 | module.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 |
|
18 | const defaults = {
|
19 | iconSrc: null,
|
20 | iconFileName: 'icon.png',
|
21 | sizes: [64, 120, 144, 152, 192, 384, 512],
|
22 | targetDir: 'icons'
|
23 | }
|
24 |
|
25 | function generateIcons (moduleOptions) {
|
26 |
|
27 | const options = Object.assign({}, defaults, this.options.icon, moduleOptions)
|
28 |
|
29 | const { publicPath } = getRouteParams(this.options)
|
30 |
|
31 |
|
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 |
|
48 | if (!existsSync(iconSrc)) {
|
49 | return
|
50 | }
|
51 |
|
52 | return Jimp.read(iconSrc).then(srcIcon => {
|
53 |
|
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 |
|
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 |
|
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 |
|
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 |
|
120 | module.exports.meta = require('./package.json')
|