-
Notifications
You must be signed in to change notification settings - Fork 362
feat: web-ext create simple version #771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
37d4ed3
to
68e6143
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @saintsebastian
Thanks for getting this started!
We definitely need to make this command less destructive (e.g. when the target directory already exists and it contains the files that are going to be overwritten), we should also retrieve the target dir from the parameters instead of assuming it to be the current work dir by default (which is a pretty dangerous default for a command that is going to potentially overwrite existent files).
It is also a bit unfortunate that we cannot name the property exported by src/cmd/index.js
as the command name (which is currently new
), I'm wondering if we should opt to rename the command (e.g. into web-ext init
), let see what @kumar303 thinks about it.
src/cmd/index.js
Outdated
import newCommand from './new'; | ||
|
||
export default {build, lint, run, sign}; | ||
export default {build, lint, run, sign, newCommand}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch, this is so unfortunate :-(
clearly and for obvious reason we cannot (and we shouldn't) use new
as a property name here (we can force if to be valid if we quote the key, e.g. {...,"new": newCommand}
but I'm not sure that it would make it nicer or less confusing)
@kumar303 how do we prefer to make this nicer? I currently see two options:
- we can choose a different name for the command (e.g.
web-ext init
?) - we can choose to change the convention used to name the properties here for all the commands (e.g.
{cmdBuild, cmdLint, ..., cmdNew}
)
we could also quote all the properties of this export (e.g. {"build": ..., "new": ...}) and always referring to this properties using the string key, but I'm not sure that I like it (I would probably vote for renaming this command to init
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree web-ext init
is a better option, I'll proceed with this changes. Unless @kumar303 disagrees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think renaming the command is the best solution since it will allow us to match the name of the function to the command exactly.
Here are some ideas along with how they might be mnemonically associated in the developer's mind:
web-ext create
- "Create a new web extension"
web-ext start
- "Start developing a new web extension"
- One downside is that
npm start
is a convention which usually applies more to starting a server or a test suite, depending on the project.
web-ext init
- "Initialize a new web extension"
- I'm not totally opposed to this, it just seems like an unnecessary abbreviation to me when we have options for shorter words.
Any of these are fine by me so pick your favorite :) I would probably choose create
myself.
src/cmd/new.js
Outdated
|
||
const manifest = { | ||
background: { | ||
scripts: [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we definitely need to discuss a bit about what it makes sense to include in the minimal generated webextension,
and I think that starting to review this manifest skeleton is definitely a good starting point to make this discussion to happen, e.g.
-
we should not generate a manifest with both the "background.scripts" and "background.page" properties, I think that including "background.script" with just 1 script named "background.js" in the scripts array is enough.
-
in my opinion, while it could make sense to include a
browser_action
, just as a common UI element included in an addon, I'd remove thepage_action
section, its syntax is pretty similar to thebrowser_action
property and I think that it is not very common to use both in a single addon. -
in my opinion a content script should be added to the skeleton, especially because I think that it is pretty common for a WebExtension to include one to manipulate the content.
I also think that we should probably generate the background and content script javascript files (even just two files with a single console.log call, e.g. console.log("ADDON NAME background page loaded")
or something similar).
@kumar303 what are your opinion about what we should include in this minimal generated webextension?
src/cmd/new.js
Outdated
}; | ||
|
||
export default async function newCommand(): Promise<void> { | ||
const path = process.cwd(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we should default it to process.cwd()
, but I'm pretty sure that we need to make this command less dangerous (e.g. we should check that we are not going to overwrite existent files in the target dir by mistake)
I would assume that the path is the yargs "rest", the one that are in the argv._
property after yargs has completed the command and options parsing.
Retrieving the path from argv._
is probably something that should be done in src/program.js
, and then we can pass it to the this command in its parameters.
(and we should also be sure that we raise and log an error if there are more that one element in the argv._
property, or if there is no selected target path at all)
src/cmd/new.js
Outdated
const path = process.cwd(); | ||
const title = path.match(/[A-z0-9_-]+$/); | ||
if (Array.isArray(title)) { | ||
manifest.name = title[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can probably make this part (fill the customized properties of the manifest skeleton) nicer if we wrap the manifest skeleton into a utility method, e.g.:
function generateManifest({title}) {
return {
manifest_version: 2,
name: `${title} (name)`,
description: `${title} (description)`,
...
browser_action: {
default_title: `${title} (browserAction)`,
...
},
...
};
and then we can just use it like:
const generatedManifest = createManifest({title: initTargetPath});
...
await fs.writeFile('manifest.json', generateManifest, 'utf8');
src/cmd/new.js
Outdated
manifest.name = title[0]; | ||
manifest.page_action.default_title = title[0]; | ||
manifest.browser_action.default_title = title[0]; | ||
var json = JSON.stringify(manifest, null, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no var
, we should use only const
and let
.
src/cmd/new.js
Outdated
manifest.browser_action.default_title = title[0]; | ||
var json = JSON.stringify(manifest, null, 2); | ||
try { | ||
await fs.writeFile('manifest.json', json, 'utf8'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like I wrote above, we should not overwrite any existent file in the target directory (at least not without an additional user confirmation, e.g. an additional cli option like --allow-overwrite
)
tests/unit/test-cmd/test.new.js
Outdated
describe('new', () => { | ||
|
||
after(() => { | ||
process.chdir(homeDir); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like I wrote above, we should pass the target path explicitly to this command (even if the default value is the current working dir), once we change the command to get the target path from its parameters, we can remove any process.chdir
magic from this unit test (I really prefer that the unit tests, as the code in the web-ext sources, never change the current working dir... very bad things happens if you lose track of which one is the current working dir and what has changed it :-)).
bd8ca10
to
91c6a73
Compare
8123fbb
to
647c0a1
Compare
@rpl To avoid creating a file in working directory I wrote test to |
|
||
it('creates files including manifest with correct name', () => withTempDir( | ||
(tmpDir) => { | ||
process.chdir(tmpDir.path()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like discussed, we should change the current work dir during the tests (and it should fix the failures of these tests on windows) here, in the afterEach and elsewhere in this test file.
"load-grunt-tasks": "3.5.2", | ||
"mocha": "3.2.0", | ||
"mocha-multi": "0.10.0", | ||
"mock-stdin": "0.3.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably reuse the mock that we created for #746 and do not include this as a devDependencies.
const log = createLogger(__filename); | ||
const defaultAsyncMkdirp = promisify(mkdirp); | ||
|
||
export type CreateParams = {| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should split these properties into two parameters and flow types like we do for the other commands:
- the first one should be named
SomethingParams
(e.g.CreateCmdParams
) and it should only contains what is supposed to be in the regular parameters of the command (e.g.dirPath
in this case) - the second one should be named
SomethingOptions
(e.g.CreateCmdOptions
) and it should only contains the optional injected dependencies (stdin?
in this case), which are used mostly to override the dependencies in the unit tests
stdin = process.stdin, | ||
}: CreateParams | ||
): Promise<void> { | ||
const targetPath = path.join(process.cwd(), dirPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking that instead of using process.cwd()
directly here, it would be better to turn it into a parameter (which defaults to process.cwd() if missing) and/or into an injected dependency (e.g. something like function getBaseDir(baseDir) { return baseDir || process.cwd(); }
).
This way, the command can provide much more control to the caller if needed, which should be helpful both in the unit tests and while using web-ext as a library.
950d5dc
to
37e83c7
Compare
Closing this PR, we have moved this feature into its own create-webextension npm package and github repo for now. |
fixes #540
I came up with a couple of question about this issue:
web-ext new
, at the moment name of the current directory is used to generate the manifest as the name of the addon, maybe user would rather expectweb-ext new name
which would create aname
folder and manifest file inside of itmanifest.json
may not be perfect, I'd really like to know your opinion on what elements are necessary