- Themes
- Internationalization
- Prefs
- SVGs
- ContextMenus
- Flow
- Logging
- Testing
- Linting
- Colors
- Configs
- Hot Reloading
- Contributing to other packages
- FAQ
- Errors
- Getting Help
The local debugger supports three themes:
Light | Dark | Firebug |
---|---|---|
You can change the theme by going to the Settings panel in the launchpad and changing the theme to either firebug
or dark
.
It is possible to add a theme specific selector. For example, this selector updates the dark debugger button colors:
.theme-dark .command-bar > span {
fill: var(--theme-body-color);
}
The Debugger supports two types of internationalization RTL (right to left) layout and L10N (localization).
L10N is a global module with two methods getStr
and getFormatStr
.
L10N.getStr("scopes.header")
L10N.getFormatStr("editor.searchResults", index + 1, count)
Translated strings are added to the debugger properties file.
RTL stands for right to left and is an important feature for arabic languages and hebrew. Here's what the debugger looks like right to left screenshot.
How do I set the Debugger to right to left?
Set the dir
field in your the local config to either "rtl" or "ltr".
configs/local.json
"dir": "rtl"
How do I change how something looks in rtl?
We use postcss-bidirection to support logical CSS properties. In practice, this means we can write float:left
or margin-inline-block: start
, and it just works. Under the hood, float: left
gets translated into two different CSS rules for html[dir="rtl"]
and html:not([dir="rtl"])
.
public/js/components/SourceFooter.css
html:not([dir="rtl"]) .source-footer .command-bar {
float: right;
}
html[dir="rtl"] .source-footer .command-bar {
float: left;
}
User preferences are stored in Prefs. Prefs uses localStorage locally and firefox's profiles in the panel.
Setting a default value
pref("devtools.debugger.client-source-maps-enabled", true);
Adding a pref
const prefs = new PrefsHelper("devtools", {
clientSourceMapsEnabled: ["Bool", "debugger.client-source-maps-enabled"],
});
Reading a pref
const { prefs } = require("./utils/prefs");
console.log(prefs.clientSourceMapsEnabled)
Setting a pref
const { prefs } = require("./utils/prefs");
prefs.clientSourceMapsEnabled = false;
We use SVGs in DevTools because they look good at any resolution.
Adding a new SVG
- add the SVG in assets/images
- add it to Svg.js
diff --git a/assets/images/Svg.js b/assets/images/Svg.js
index 775aecf..6a7c19d 100644
--- a/assets/images/Svg.js
+++ b/assets/images/Svg.js
@@ -24,7 +24,8 @@ const svg = {
"subSettings": require("./subSettings.svg"),
"toggleBreakpoints": require("./toggle-breakpoints.svg"),
"worker": require("./worker.svg"),
- "sad-face": require("./sad-face.svg")
+ "sad-face": require("./sad-face.svg"),
+ "happy-face": require("./happy-face.svg")
};
Using an SVG
- import the
Svg
module - call
Svg(<your-svg>)
diff --git a/src/components/Breakpoints.js b/src/components/Breakpoints.js
index 8c79f4d..6893673 100644
--- a/src/components/Breakpoints.js
+++ b/src/components/Breakpoints.js
@@ -4,6 +4,7 @@ const { bindActionCreators } = require("redux");
const ImPropTypes = require("react-immutable-proptypes");
const classnames = require("classnames");
const actions = require("../actions");
+const Svg = require("./shared/Svg");
const { getSource, getPause, getBreakpoints } = require("../selectors");
const { makeLocationId } = require("../reducers/breakpoints");
@@ -89,6 +90,7 @@ const Breakpoints = React.createClass({
key: locationId,
onClick: () => this.selectBreakpoint(breakpoint)
},
+ Svg("happy-face"),
dom.input({
type: "checkbox",
className: "breakpoint-checkbox",
Styling an SVG element
You can style several SVG elements (svg, i, path) just as you would other elements.
- fill is especially useful for changing the color
diff --git a/src/components/Breakpoints.css b/src/components/Breakpoints.css
index 5996700..bb828d8 100644
--- a/src/components/Breakpoints.css
+++ b/src/components/Breakpoints.css
@@ -69,3 +69,11 @@
.breakpoint:hover .close {
display: block;
}
+
+.breakpoint svg {
+ width: 16px;
+ position: absolute;
+ top: 12px;
+ left: 10px;
+ fill: var(--theme-graphs-full-red);
+}
The Debugger can create its own context menus. In the launchpad, it uses a shimmed context menu library. In Firefox, it has special permission to create native context menus.
Here's a simple example:
const { showMenu } = require("devtools-launchpad");
function onClick(event) {
const copySourceUrlLabel = L10N.getStr("copySourceUrl");
const copySourceUrlKey = L10N.getStr("copySourceUrl.accesskey");
showMenu(event, [{
id: "node-menu-copy-source",
label: copySourceUrlLabel,
accesskey: copySourceUrlKey,
disabled: false,
click: () => copyToClipboad(url),
hidden: () => url.match(/chrome:\/\//)
}]);
}
Notes:
id
helps screen readers and accessibilitylabel
menu item label shownaccesskey
keyboard shortcut useddisabled
inert itemclick
on click callbackhidden
dynamically hide items
You can use a menu item separator to create menu groups.
const { showMenu } = require("devtools-launchpad");
function onClick(event) {
const copySourceUrlLabel = L10N.getStr("copySourceUrl");
const copySourceUrlKey = L10N.getStr("copySourceUrl.accesskey");
const menuItem = {
id: "node-menu-copy-source",
label: copySourceUrlLabel,
accesskey: copySourceUrlKey,
disabled: false,
click: () => copyToClipboad(url),
hidden: () => url.match(/chrome:\/\//)
}
showMenu(event, [
menuItem,
{ item: { type: "separator" } },
]);
}
- Adding flow to a file
- Running flow
- Missing Annotation
- Where are types defined?
- Checking flow coverage
- Common Errors
Logging information can be very useful when developing, and there are a few logging options available to you.
To enable logging:
- Create a local config file if you don't already have one
- Edit your local config, changing the value of the logger type you want to see to
true
"logging": {
"client": false,
"firefoxProxy": false,
"actions": true
}
- Restart your development server by typing ctrl+c in the Terminal and run
yarn start
again
Let's cover the logging types.
-
client - This option is currently unused.
-
firefoxProxy - This logger outputs a verbose output of all the Firefox protocol packets to your shell.
-
actions - This logger outputs the Redux actions fired to the browser console.
Your code must pass all tests to be merged in. Your tests should pass locally before you create a PR and the CI should run an automated test that also passes.
Here's how can run all the unit tests, lints, and integration tests at once:
yarn run test-all
yarn test
- Run tests with jest.
Running all the tests tends to be really slow. Most of the time it is realy useful to run a single test. You can do this by invoking jest directly like this:
node_modules/jest/bin/jest.js -o
This will run all the tests that have not been commited. Basically all the files that are returned by the git status
command.
If the snapshot changes then update it with:
node_modules/jest/bin/jest.js -o -u
There are two styles of component tests: interaction, snapshot.
We shallow render the component and simulate an UI interaction like click
.
it("should call handleClick function", () => {
const onClick = jest.genMockFunction();
const wrapper = shallow(new CloseButton({ handleClick: onClick }));
wrapper.simulate("click");
expect(onClick).toBeCalled();
});
We shallow render the component to a JSON and save it to a fixture. Subsequent runs are compared to the fixture.
it("should render a button", () => {
const onClick = jest.genMockFunction();
const buttonClass = "class";
const wrapper = shallow(
new CloseButton({
handleClick: onClick,
buttonClass: buttonClass,
tooltip: "Close button"
})
);
expect(wrapper).toMatchSnapshot();
});
The Debugger integration tests are run in two contexts: firefox and the web. We recommend running the tests in the browser as it's an easier development environment.
Type | Command |
---|---|
all | yarn run lint |
css | yarn run lint-css |
js | yarn run lint-js |
markdown | yarn run lint-md |
We use Stylelint to maintain our CSS styles. The .stylelintrc file contains the style definitions, please adhere to those styles when making changes.
To test your CSS changes run the command:
yarn run lint-css
We use eslint to maintain our JavaScript styles. The .eslintrc file contains our style definitions, please adhere to those styles when making changes.
To automatically fix many errors run the command:
yarn run lint-fix
We use remark to help lint our markdown. It checks for broken images, links, and a set of style rules.
The Debugger has a styleguide that we use to keep the colors consistent across tools and themes.
The common colors are represented as css variables in a devtools variables file. This lets define the colors for each theme: light, dark, firebug.
Most color changes can be made by finding a different css variable.
For instance, --theme-splitter-color
is often good for border colors. The advantage to using an existing variable is that you know it'll look good in all the themes.
When you need to update a variable, you should check to make sure it looks good in the other places it is being used. Often, it is more practicle to create a new variable.
It's helpful to share the changes as a themes table when you're done.
It's important to make sure that the contrast ratio is sufficient.
You can check the background / text color contrast ratio with this tool.
The Debugger uses configs for settings like theme
, hotReloading
, and feature flags.
The default development configs are in development-json. It's easy to change a setting in the Launchpad's settings tab or by updating your configs/local.json
file.
When you're starting a new feature, it's always good to ask yourself if the feature should be added behind a feature flag.
- does this feature need testing or introduce risk?
- will this feature be built over several PRs?
- is it possible we'll want to turn it off quickly?
It's easy to add a new feature flag to the project.
- add the flag to
development.json
andfirefox-panel.json
- add
isEnabled
calls in the code
Here's an example of adding a new feature "awesome sauce" to the Debugger:
diff --git a/configs/development.json b/configs/development.json
index c82b299..d9de5f3 100755
--- a/configs/development.json
+++ b/configs/development.json
@@ -14,7 +14,8 @@
"eventListeners": {
"label": "Event Listeners",
"enabled": false
},
"codeCoverage": {
"label": "Code Coverage",
"enabled": false
- }
+ },
+ "awesomeSauce": {
+ "label": "Awesome Sauce",
+ "enabled": false
+ }
},
"chrome": {
"debug": true,
diff --git a/configs/firefox-panel.json b/configs/firefox-panel.json
index c91b562..bf485bb 100644
--- a/configs/firefox-panel.json
+++ b/configs/firefox-panel.json
@@ -10,6 +10,7 @@
"eventListeners": {
"label": "Event Listeners",
"enabled": false
},
"codeCoverage": {
"label": "Code Coverage",
"enabled": false
- }
+ },
+ "awesomeSauce": {
+ "label": "Awesome Sauce",
+ "enabled": false
+ }
}
}
diff --git a/src/components/Editor/index.js b/src/components/Editor/index.js
index 038fd01..ea7a545 100644
--- a/src/components/Editor/index.js
+++ b/src/components/Editor/index.js
@@ -114,6 +114,10 @@ const Editor = React.createClass({
return;
}
+ if (isEnabled("awesomeSauce")) {
+ // sauce goops out of the breakpoint...
+ }
+
- Restart your development server by typing ctrl+c in the Terminal and run
yarn start
again
🚧 Hot Reloading is currently broken as we need to upgrade react-hot-reloader
3.0 issue
Hot Reloading watches for changes in the React Components JS and CSS and propagates those changes up to the application without changing the state of the application. You want this turned on.
To enabled Hot Reloading:
- Create a local config file if you don't already have one
- edit
hotReloading
diff --git a/configs/local.json b/configs/local.json
index fdbdb4e..4759c14 100644
--- a/configs/local.json
+++ b/configs/local.json
@@ -1,6 +1,6 @@
{
"theme": "light",
- "hotReloading": false,
+ "hotReloading": true,
"logging": {
"actions": false
},
- Restart your development server by typing ctrl+c in the Terminal and run
yarn start
again
The debugger depends on several other devtools packages. Sometimes a debugger feature will necessitate working on one of these other packages. In these cases, you'll need to get the project and work on it directly.
Launchpad | Development environment |
Reps | Variable formatter |
Client Adapters | Browser connection library |
Modules | Shared modules |
Source Maps | Library for working with source maps |
There are three ways to test a change to a 3rd party package.
- yarn link
- create a local version with npm pack and yarn add
- change the file directly in the debugger's
node_modules
directory.
The reason is largely historical. Devtools historically has been developed inside the browser 1. The advantage of this approach is devtools could be written with ES6 and modules without a build step.
When we started the Debugger, we were not sure if we would keep webpack and the website workflow and did not want to re-write the JSX to raw JS.
Now that we have decided that working in github with webpack has a lot of benefits we could switch to JSX. We are open to switching if someone could help us do it, join the discussion here.
If you're running into errors associated with updating your files locally, try:
git checkout .
yarn nom
git pull --rebase
Another option is to reset your branch to master:
git fetch origin
git checkout master
git reset --hard origin/master
yarn nom
to update node modulesyarn start
to restart local server
There are lots of helpful folks who'd be happy to answer your questions on slack.
Component | 🐶 🐼 🐹 | |
---|---|---|
Editor | @jasonlaster @jbhoosreddy |
|
Sources | @arthur801031 @bomsy |
|
Call Stack | @zacqary @wldcordeiro |
|
Scopes & Variables | @bomsy @arthur801031 |
|
Breakpoints | @wldcordeiro @jbhoosreddy |
|
Product & UI | @clarkbw @jasonlaster |