* Improve documentation. PanelFrame is two words.

* Copyright headers.

* Upgrading tslint brought in two bad defaults
This commit is contained in:
Adam Reineke 2018-01-19 16:58:22 -08:00 коммит произвёл GitHub
Родитель 06001aee75
Коммит 30fc3987d3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 286 добавлений и 48 удалений

Просмотреть файл

@ -1,24 +1,36 @@
# Web Perf Toolbar
A drop-in toolbar to visualize web client performance.
A component to visualize client performance on your site for the current page.
## Engineering Spec and Work Tracking
The initial work is being completed by Sway engineers.
Shipped as a single JavaScript file with no runtime dependencies, this toolbar drops into your existing sites with a single script tag and barely any configuration. Designed to be injected into a page for developers or stakeholders
The [initial engineering spec](https://microsoft.sharepoint.com/:w:/r/teams/Sway/_layouts/15/Doc.aspx?sourcedoc=%7Bb321f8b7-6492-4031-99bf-70c3f5080501%7D&action=edit) is access-limited to Microsoft employees.
## Road Map
Work tracking is within the Sway project in Office's Visual Studio, under [Task Group 2031043](https://office.visualstudio.com/Sway/_workitems/edit/2031043).
Once the core version of this tool ships, documentation will need to be updated and the initial spec will be abandoned in favor of describing, tracking, and planning work in this repository.
Note: This project follows semver and is pre-release. Until a 1.0 release, the public API may change.
## Getting Started
1. `npm install`
1. [Visual Studio Code](https://code.visualstudio.com/) is the recommended editor. We [have configured](./.vscode/extensions.json) recommended extensions for working with this project.
2. Install the npm dev dependencies. `npm install`
3. Run the demo: `npm run demo`
## Commands
## Commands (`npm run ...`)
- `npm run build` Kicks off a Webpack build.
- `npm run test` Builds then launches a test runner in IE and Chrome that watches for changes.
- `npm run demo` Builds then launches a page with a demo of the toolbar.
### Main Commands
- `demo` Builds then launches a page with a demo of the toolbar.
- `build` Kicks off a Webpack production build.
- `test` Builds then launches a test runner in IE and Chrome that watches for changes.
- `check` Compiles, lints, and tests everything. **This command must be run and the output must be clean before checking in.**
### Source Commands
- `tslint` Run tslint on the toolbar sources.
- `tsc` Compile the toolbar TypeScript sources directly (no Webpack).
- `tsc-verbose` Same as above, but verbose compiler.
### Test commands
- `test-once` Builds then launches a single test run.
- `test-tslint` Runs tslint on the test sources.
- `test-tsc` Compiles the test TypeScript sources directly (no Webpack/Karma).
- `test-tsc-verbose` Same as above, but verbose compiler.
## Contributing
@ -33,3 +45,42 @@ provided by the bot. You will only need to do this once across all repos using o
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
To get started, see [Adding To The Toolbar](./docs/adding-to-the-toolbar.md).
## Maintainers
- @AdamTReineke (Admin, primary contact)
- @JoshuaKGoldberg (Admin)
- Dadstart (Admin)
## Releasing
This project follows the [semver](https://semver.org/) versioning convention of major.minor.patch.
- Changing the [public API](./src/toolbar.ts) will bump the **major** version.
- Adding a whole new panel, changing/removing a panel configuration, or adding significant panel features will bump the **minor** version.
- Bug fixes or minor tweak to a panel, including adding new optional panel configurations, will bump the **patch** version.
0. Figure out what the new version number will be.
0. If leaving `0.1.0-alpha`, update the Security notice below and remove this line.
1. From `develop` branch, create a new branch for the release: `git checkout -b release-vxx.xx.xx`
2. `npm run check` should be clean.
3. Verify the [demo](./index.html) was updated to show any new panels.
4. `npm run demo` should show the different panels in the toolbar.
5. Bump the version in [package.json](./package.json).
6. Update the road map in this file to address completed work.
7. Make then merge a pull request from the new branch to `master`.
8. Tag with the new version number. `git tag vxx.xx.xx; git push --tags`
9. Push to NPM. *TODO: What are the steps?*
There is not a regular release schedule.
## Reporting Security Issues
**DURING ALPHA ONLY**: Open a new issue so we can address the issue before leaving alpha. Once this project leaves alpha, the default Microsoft Security message below should be unstruck and followed.
~~Security issues and bugs should be reported privately, via email, to the Microsoft Security
Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should
receive a response within 24 hours. If for some reason you do not, please follow up via
email to ensure we received your original message. Further information, including the
[MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in
the [Security TechCenter](https://technet.microsoft.com/en-us/security/default).~~

Просмотреть файл

@ -0,0 +1,62 @@
# Adding To The Toolbar
## Be Familiar With The Tech Stack
- Language: TypeScript
- Test Runner: Karma
- Assertion Library: Mocha
- Linter: tslint
- Packaging: Webpack
## Follow The Implicit Coding Guidelines
- The coding style should be pretty standard and enforced with tslint.
- Using VSCode with the recommended extensions exposes tslint violations at dev time so you aren't surprised when you build.
- Don't violate tslint rules without having a good reason and justify disabling rules for a line or block with a comment when you do.
- There is a high bar for disabling tslint rules globally through tslint.json.
TODO: Some rules are annoying formatting ones. We need to set up prettier and/or auto-fixing on save for tslint.
## Understand The Architecture
### Toolbar
- A `Toolbar` is constructed with a list of `IPanel` constructors and `IPanelConfig` configurations.
### Panels
- Panels extend from `IPanel`.
- Panels provide a list of `Button` objects displayed by the toolbar.
- Panels are rendered in a `PanelFrame` provided by the `Toolbar`.
- These panels are constructed with a configuration object that extends `IPanelConfig`.
- There should be a default configuration object with values for every configuration property. These default values should be used when
- (Recommended) UI strings should be available in a panel's configuration so they can be overridden.
### Buttons
- Buttons are so basic their design is quite opinionated.
- Buttons have a simple visual: icon, text, and background color.
- Buttons toggle the display of the `PanelFrame` when they are clicked.
- Buttons are constructed with a configuration object that extends `IButtonConfiguration`.
## Create A New Panel
1. Create an interface for the panel configuration. Start simple, maybe just a string for the panel name.
2. Create a default configuration object.
3. Create the class for your panel.
1. You probably want to duplicate the constructor from an existing panel.
2. Determine what you want your button to show. Maybe just a smiley face and a random number at first.
3. Determine what you want the panel to show. Start by setting the innerHTML of the DOM object that is passed in to the render function to something like the title you have in the config object.
4. Update `./src/index.ts` to include a reference to your panel. (Since we're a library and your panel isn't referenced, it won't be output since it isn't reachable. I wonder if this could be fixed with a config change, if it can, please send a PR.)
5. Update the Toolbar constructor configuration in `./index.html` to include references to your new panel and configuration.
6. Run the demo and see your toolbar! `npm run demo`
### What now? Share it!
If you are ready to share your panel with the world, add some tests then send a PR!
### Can't share?
If you have to keep your new panel private, don't worry. You don't have to maintain your own fork of this repository. As long as you have implemented the interfaces and your panel is loaded before you construct our toolbar, the code for your panel doesn't need to be built with this toolbar (or even be written in TypeScript). Just define the panel in your site's code and just reference it when constructing the toolbar.
We hope that by having a configurable design will make it easier to onboard this toolbar into your site since you won't need to maintain, build, and export a fork of this project into your site. If you have feedback about onboarding or the configurable design [please open an issue](https://github.com/Microsoft/webperftoolbar/issues/new) so we can discuss it.

Просмотреть файл

@ -7,6 +7,11 @@
</style>
</head>
<body>
<p>The toolbar is at the bottom of this page!</p>
<p>Ready to test this on a real site? See <a href="https://github.com/Microsoft/webperftoolbar/blob/master/docs/testing.md">the instructions on injecting this toolbar</a> via browser plugins.</p>
<p>Ready to add it to your page? View the source of this document to see how we add it to the page.</p>
<p>Ready to extend the toolbar with your own panel? Follow <a href="https://github.com/Microsoft/webperftoolbar/blob/master/docs/adding-to-the-toolbar.md">the instructions</a>.</p>
<script defer>
(function() {
var initFunc = function() {

58
package-lock.json сгенерированный
Просмотреть файл

@ -217,6 +217,15 @@
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true
},
"argparse": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
"dev": true,
"requires": {
"sprintf-js": "1.0.3"
}
},
"arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
@ -4084,6 +4093,24 @@
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true
},
"js-yaml": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
"integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
"dev": true,
"requires": {
"argparse": "1.0.9",
"esprima": "4.0.0"
},
"dependencies": {
"esprima": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
"integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
"dev": true
}
}
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@ -6751,6 +6778,12 @@
"integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
"dev": true
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
@ -7113,22 +7146,31 @@
"dev": true
},
"tslint": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz",
"integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz",
"integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=",
"dev": true,
"requires": {
"babel-code-frame": "6.26.0",
"builtin-modules": "1.1.1",
"chalk": "2.3.0",
"commander": "2.11.0",
"commander": "2.13.0",
"diff": "3.3.1",
"glob": "7.1.2",
"js-yaml": "3.10.0",
"minimatch": "3.0.4",
"resolve": "1.5.0",
"semver": "5.4.1",
"tslib": "1.8.1",
"tsutils": "2.13.1"
"tsutils": "2.19.1"
},
"dependencies": {
"commander": {
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
"integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
"dev": true
}
}
},
"tsscmp": {
@ -7139,9 +7181,9 @@
"optional": true
},
"tsutils": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.1.tgz",
"integrity": "sha512-XMOEvc2TiYesVSOJMI7OYPnBMSgcvERuGW5Li/J+2A0TuH607BPQnOLQ82oSPZCssB8c9+QGi6qhTBa/f1xQRA==",
"version": "2.19.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.19.1.tgz",
"integrity": "sha512-1B3z4H4HddgzWptqLzwrJloDEsyBt8DvZhnFO14k7A4RsQL/UhEfQjD4hpcY5NpF3veBkjJhQJ8Bl7Xp96cN+A==",
"dev": true,
"requires": {
"tslib": "1.8.1"

Просмотреть файл

@ -8,10 +8,10 @@
"test": "karma start karma.conf.js",
"test-once": "karma start karma.conf.js --single-run",
"demo": "npm run build && node gzip.js && http-server -g -o -c-1",
"tslint": "tslint -p .",
"tslint": "tslint --fix -p .",
"tsc": "tsc -p tsconfig.json",
"tsc-verbose": "tsc -p tsconfig.json --traceResolution true",
"test-tslint": "tslint -p test/.",
"test-tslint": "tslint --fix -p test/.",
"test-tsc": "tsc -p test/tsconfig.json",
"test-tsc-verbose": "tsc -p test/tsconfig.json --traceResolution true",
"check": "npm run tslint && npm run test-tslint && npm run test-tsc && npm run tsc && npm run test-once"
@ -41,7 +41,7 @@
"ts-loader": "3.2.0",
"ts-node": "4.1.0",
"tslib": "1.8.1",
"tslint": "5.8.0",
"tslint": "5.9.1",
"typescript": "2.6.2",
"uglifyjs-webpack-plugin": "1.1.6",
"webpack": "3.10.0",

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { IPanel } from "./ipanel";
/**
@ -44,7 +48,7 @@ export class Button {
this.title = config.title !== undefined ? config.title : "";
this.emoji = config.emoji !== undefined ? config.emoji : "";
this.parent = config.parent;
/* tslint:disable no-unbound-method */
/* tslint:disable no-unbound-method (because the function passed in could be unbound) */
this.getValue = config.getValue !== undefined ? config.getValue : () => "";
this.getColor = config.getColor !== undefined ? config.getColor : () => "";
/* tslint:enable no-unbound-method */

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
/** The level of precision we want to see for numbers */
export const DECIMAL_PLACES: number = 2;

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
export { Toolbar } from "./toolbar";
export { Button } from "./button";
export { NavigationTimingsPanel } from "./panels/navigation-timing";

Просмотреть файл

@ -1,5 +1,9 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { Button } from "./button";
import { PanelFrame } from "./panelframe";
import { PanelFrame } from "./panel-frame";
export interface IPanelWithConfiguration<C extends IPanelConfig, P extends IPanel> {
config: C;
@ -10,7 +14,7 @@ export interface IPanelConstructor<C, P> {
new (frame: PanelFrame, config: C): P;
}
// tslint:disable-next-line:no-empty-interface
// tslint:disable-next-line:no-empty-interface (Because configurations should share a common base type.)
export interface IPanelConfig {
}

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { IPanel } from "./ipanel";
/**

Просмотреть файл

@ -1,7 +1,11 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { Button } from "../button";
import * as Formatter from "../formatter";
import { IPanel, IPanelConfig } from "../ipanel";
import { PanelFrame } from "../panelframe";
import { PanelFrame } from "../panel-frame";
/** Describes the configuration options available for the network panel */
export interface INavigationTimingsPanelConfig extends IPanelConfig {

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { IPanelConfig } from "../ipanel";
/** Describes the configuration for the bytes over wire button. */

Просмотреть файл

@ -1,7 +1,11 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { Button } from "../button";
import * as Formatter from "../formatter";
import { IPanel } from "../ipanel";
import { PanelFrame } from "../panelframe";
import { PanelFrame } from "../panel-frame";
import {
IBytesOverWireButtonConfig,
IImageBytesOverWireButtonConfig,

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
const getButtonStyles = () => `
#PTB_buttons {
position:fixed;

Просмотреть файл

@ -1,14 +1,18 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { IPanel, IPanelConfig, IPanelWithConfiguration } from "./ipanel";
import { PanelFrame } from "./panelframe";
import { PanelFrame } from "./panel-frame";
import { addStylesToDom } from "./styler";
/** Describes the toolbar. */
export class Toolbar {
/** The panels that will be displayed in the toolbar */
private panels: IPanel[];
private readonly panels: IPanel[];
/** The root element of the toolbar. */
private toolbarRoot: HTMLElement;
private readonly toolbarRoot: HTMLElement;
/**
* Creates the toolbar.

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";
import { Button, IButtonConfiguration } from "../src/button";

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";

Просмотреть файл

@ -1,6 +1,10 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { Button } from "../../src/button";
import { IPanel, IPanelConfig } from "../../src/ipanel";
import { PanelFrame } from "../../src/panelframe";
import { PanelFrame } from "../../src/panel-frame";
/** Describes the mocked panel configuration */
export interface IMockPanelConfig extends IPanelConfig {

Просмотреть файл

@ -1,8 +1,12 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";
import { Button } from "../../src/button";
import { PanelFrame } from "../../src/panelframe";
import { PanelFrame } from "../../src/panel-frame";
import { NavigationTimingsPanel } from "../../src/panels/navigation-timing";
// Provides mocked performance timings for tests

Просмотреть файл

@ -1,8 +1,12 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";
import { Button } from "../../src/button";
import { PanelFrame } from "../../src/panelframe";
import { PanelFrame } from "../../src/panel-frame";
import * as rt from "../../src/panels/resource-timing";
import {
InitiatorTypes,
@ -47,27 +51,26 @@ const getMockSummaryRows = (): SummaryRow[] => {
/* tslint:disable:no-magic-numbers */
/**
* Get mock entries.
* We use prime numbers (greater than two) to make sure they can be added uniquely to verify test cases better.
* 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101
* We use increasing powers of 10 to make addition errors more obvious.
*/
const getMockEntries = (): IResourcePerformanceEntry[] => [
{
...zeroEntry,
initiatorType: "img",
decodedBodySize: 3,
transferSize: 5,
decodedBodySize: 1,
transferSize: 10,
},
{
...zeroEntry,
initiatorType: "img",
decodedBodySize: 7,
decodedBodySize: 100,
transferSize: 0, // Zero is the transferred size for a cached file
},
{
...zeroEntry,
initiatorType: "link",
decodedBodySize: 13,
transferSize: 17,
decodedBodySize: 1000,
transferSize: 10000,
},
];
/* tslint:enable:no-magic-numbers */
@ -99,16 +102,16 @@ describe("Resource timing panel class", () => {
/* tslint:disable:no-magic-numbers */
const image: SummaryRow = counts[InitiatorTypes.img];
expect(image.decodedBytes).to.equal(3 + 7);
expect(image.overWireBytes).to.equal(5);
expect(image.decodedBytes).to.equal(1 + 100);
expect(image.overWireBytes).to.equal(10);
expect(image.numFiles).to.equal(2);
expect(image.largestBytes).to.equal(7);
expect(image.largestBytes).to.equal(100);
const link: SummaryRow = counts[InitiatorTypes.link];
expect(link.decodedBytes).to.equal(13);
expect(link.overWireBytes).to.equal(17);
expect(link.decodedBytes).to.equal(1000);
expect(link.overWireBytes).to.equal(10000);
expect(link.numFiles).to.equal(1);
expect(link.largestBytes).to.equal(13);
expect(link.largestBytes).to.equal(1000);
const other: SummaryRow = counts[InitiatorTypes.other];
expect(other.decodedBytes).to.equal(0);

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
/**
* Throw if an argument is null.
* @param arg The value to verify isn't null

Просмотреть файл

@ -1,3 +1,7 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
*/
import { expect } from "chai";
import "mocha";

Просмотреть файл

@ -28,7 +28,14 @@
"strict-boolean-expressions": [true, "allow-undefined-union"],
"interface-over-type-literal": false,
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"],
"typedef": false
"typedef": false,
"file-header": [
true,
"Copyright \\(c\\) Microsoft Corporation. All rights reserved. Licensed under the MIT License.",
"Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License."
],
"object-literal-sort-keys": false,
"newline-per-chained-call": false
},
"jsRules": {
"max-line-length": {