Skip to content

Commit

Permalink
Manifest v3 migration
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikescops committed Apr 20, 2021
1 parent 1f25d54 commit ed52c87
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 117 deletions.
2 changes: 1 addition & 1 deletion .neutrinorc.js
Expand Up @@ -21,7 +21,7 @@ module.exports = {
popup: {
entry: 'src/popup',
webext: {
type: 'browser_action'
type: 'action'
}
},
content1: {
Expand Down
98 changes: 26 additions & 72 deletions lib/WexExtManifestPlugin.js
Expand Up @@ -4,6 +4,9 @@ const merge = require('deepmerge')
const open = require('open')
const argv = require('yargs-parser')(process.argv.slice(2))

const manifestV3Compilation = require('./manifestV3');
const manifestV2Compilation = require('./manifestV2');

class WexExtManifestPlugin {
constructor (options, neutrinoOpts) {
this.options = options
Expand All @@ -18,77 +21,6 @@ class WexExtManifestPlugin {
version: this.neutrinoOpts.packageJson.version
}

compilation.entrypoints.forEach((entry, name) => {
const htmlPluginOpts = this.neutrinoOpts.mains[name]
const entryOpts = htmlPluginOpts.webext
if (!entryOpts) {
return
}

switch (entryOpts.type) {
case 'content_scripts':
{
if (!neutrinoManifest.content_scripts) {
neutrinoManifest.content_scripts = []
}

const files = entry
.getFiles()
.map(file => file.replace(/\.(css|js)\?.*$/, '.$1'))
const js = files.filter(file => file.endsWith('.js'))
const css = files.filter(file => file.endsWith('.css'))
const opt = {
...(entryOpts.manifest || {})
}
if (this.options.polyfill) {
js.unshift('assets/browser-polyfill.min.js')
}
if (js.length > 0) {
opt.js = opt.js ? [...js, ...opt.js] : js
}
if (css.length > 0) {
opt.css = opt.css ? [...css, ...opt.css] : css
}
neutrinoManifest.content_scripts.push(opt)
}
break
case 'background':
{
const scripts = entry
.getFiles()
.map(file => file.replace(/\.js\?.*$/, '.$1'))
.filter(file => file.endsWith('.js'))
if (this.options.polyfill) {
scripts.unshift('assets/browser-polyfill.min.js')
}
neutrinoManifest[entryOpts.type] = {
scripts,
...(entryOpts.manifest || {})
}
}
break
case 'browser_action':
case 'page_action':
neutrinoManifest[entryOpts.type] = {
default_popup: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
case 'options_page':
neutrinoManifest[entryOpts.type] =
htmlPluginOpts.filename || `${name}.html`
break
case 'options_ui':
neutrinoManifest[entryOpts.type] = {
page: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
default:
break
}
})

let commonManifest = {}
try {
commonManifest = require(path.join(
Expand All @@ -97,6 +29,16 @@ class WexExtManifestPlugin {
))
} catch(e) {}

switch (commonManifest.manifest_version) {
case 3:
manifestV3Compilation(this, compilation, neutrinoManifest)
break
case 2:
default:
manifestV2Compilation(this, compilation, neutrinoManifest)
break
}

const browsers = (await fse.readdir(path.join(this.options.manifest)))
.map(fileName => (fileName.match(/^([^.]+)\.manifest/) || [, ''])[1])
.filter(browserName => browserName !== 'common')
Expand Down Expand Up @@ -208,10 +150,22 @@ function liverreloadModify(manifest) {
}
manifest.permissions = [...new Set([
...manifest.permissions,
"*://neutrino-webextension.reloads/*",
manifest.version === 2 && "*://neutrino-webextension.reloads/*",
"webRequest",
"webRequestBlocking",
// remove history
"browsingData"
])]

if (manifest.version === 3) {
if (!manifest.host_permissions) {
manifest.host_permissions = []
}
manifest.host_permissions = [
...new Set([
...manifest.host_permissions,
"*://neutrino-webextension.reloads/*"
])
]
}
}
2 changes: 1 addition & 1 deletion lib/index.js
Expand Up @@ -170,7 +170,7 @@ module.exports = (opts = {}) => neutrino => {
.clear()
.merge(['browser'])

neutrino.config.output.globalObject('window')
neutrino.config.output.globalObject('this')

// support native dynamic import
neutrino.config.target(WebExtensionTarget(neutrino.config.node.entries()))
Expand Down
74 changes: 74 additions & 0 deletions lib/manifestV2.js
@@ -0,0 +1,74 @@
function manifestV2Compilation(parent, compilation, neutrinoManifest) {
compilation.entrypoints.forEach((entry, name) => {
const htmlPluginOpts = parent.neutrinoOpts.mains[name]
const entryOpts = htmlPluginOpts.webext
if (!entryOpts) {
return
}

switch (entryOpts.type) {
case 'content_scripts':
{
if (!neutrinoManifest.content_scripts) {
neutrinoManifest.content_scripts = []
}

const files = entry
.getFiles()
.map(file => file.replace(/\.(css|js)\?.*$/, '.$1'))
const js = files.filter(file => file.endsWith('.js'))
const css = files.filter(file => file.endsWith('.css'))
const opt = {
...(entryOpts.manifest || {})
}
if (parent.options.polyfill) {
js.unshift('assets/browser-polyfill.min.js')
}
if (js.length > 0) {
opt.js = opt.js ? [...js, ...opt.js] : js
}
if (css.length > 0) {
opt.css = opt.css ? [...css, ...opt.css] : css
}
neutrinoManifest.content_scripts.push(opt)
}
break
case 'background':
{
const scripts = entry
.getFiles()
.map(file => file.replace(/\.js\?.*$/, '.$1'))
.filter(file => file.endsWith('.js'))
if (parent.options.polyfill) {
scripts.unshift('assets/browser-polyfill.min.js')
}
neutrinoManifest[entryOpts.type] = {
scripts,
...(entryOpts.manifest || {})
}
}
break
case 'browser_action':
case 'page_action':
neutrinoManifest[entryOpts.type] = {
default_popup: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
case 'options_page':
neutrinoManifest[entryOpts.type] =
htmlPluginOpts.filename || `${name}.html`
break
case 'options_ui':
neutrinoManifest[entryOpts.type] = {
page: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
default:
break
}
})
}

module.exports = manifestV2Compilation;
81 changes: 81 additions & 0 deletions lib/manifestV3.js
@@ -0,0 +1,81 @@
const fse = require('fs-extra')
const path = require('path')

function manifestV3Compilation(parent, compilation, neutrinoManifest) {
compilation.entrypoints.forEach((entry, name) => {
const htmlPluginOpts = parent.neutrinoOpts.mains[name]
const entryOpts = htmlPluginOpts.webext
if (!entryOpts) {
return
}

switch (entryOpts.type) {
case 'content_scripts':
{
if (!neutrinoManifest.content_scripts) {
neutrinoManifest.content_scripts = []
}

const files = entry
.getFiles()
.map(file => file.replace(/\.(css|js)\?.*$/, '.$1'))
const js = files.filter(file => file.endsWith('.js'))
const css = files.filter(file => file.endsWith('.css'))
const opt = {
...(entryOpts.manifest || {})
}
if (parent.options.polyfill) {
js.unshift('assets/browser-polyfill.min.js')
}
if (js.length > 0) {
opt.js = opt.js ? [...js, ...opt.js] : js
}
if (css.length > 0) {
opt.css = opt.css ? [...css, ...opt.css] : css
}
neutrinoManifest.content_scripts.push(opt)
}
break
case 'background':
{
const scripts = entry
.getFiles()
.map(file => file.replace(/\.js\?.*$/, '.$1'))
.filter(file => file.endsWith('.js'))
if (parent.options.polyfill) {
scripts.unshift('assets/browser-polyfill.min.js')
}

const backgroundFile = scripts.map((script) => `try {importScripts('${script}')} catch(e) {console.error(e)}`).join('\n');
const backgroundPath = path.join(parent.neutrinoOpts.output, 'background.js') // should be at the root of the extension
fse.outputFileSync(backgroundPath, backgroundFile);

neutrinoManifest[entryOpts.type] = {
service_worker: "background.js",
...(entryOpts.manifest || {})
}
}
break
case 'action':
neutrinoManifest[entryOpts.type] = {
default_popup: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
case 'options_page':
neutrinoManifest[entryOpts.type] =
htmlPluginOpts.filename || `${name}.html`
break
case 'options_ui':
neutrinoManifest[entryOpts.type] = {
page: htmlPluginOpts.filename || `${name}.html`,
...(entryOpts.manifest || {})
}
break
default:
break
}
})
}

module.exports = manifestV3Compilation;

0 comments on commit ed52c87

Please sign in to comment.