Spike: Using CSS Modules in React (with generated and ignored typings) (#688)

* Introducing CSS modules

* Example of using/adding CSS module: no-displayable-preview-features-message component

* Manually adding copyright to scss.d.ts file

* Use typed-scss-modules to generate typings at build time

* Added step in build to generate typings + fixed tests + comment for jest config

* Added css module for action and cancel buttons component

* Produce reproducible in dev vs using hash in prod

* Use ID for E2E tests + remove places where scss typings generation is redundant

* Fixed unresolved merge conflict

* Fix build for electron

* Generate scss typings for unit tests
This commit is contained in:
Wahaj 2019-05-24 15:43:55 -07:00 коммит произвёл GitHub
Родитель ad928e5873
Коммит 3daf8a4882
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
28 изменённых файлов: 682 добавлений и 65 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -4,5 +4,6 @@
/extension/
/test-results/
/drop/
*.scss.d.ts
# Dependency directories
node_modules/

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

@ -142,6 +142,7 @@ module.exports = function(grunt) {
'webpack-prod': `${path.resolve('./node_modules/.bin/webpack')} --config-name prod`,
'webpack-electron': `${path.resolve('./node_modules/.bin/webpack')} --config-name electron`,
'webpack-all': `${path.resolve('./node_modules/.bin/webpack')}`,
'generate-scss-typings': `${path.resolve('./node_modules/.bin/tsm')} src`,
},
sass: {
options: {
@ -216,7 +217,7 @@ module.exports = function(grunt) {
files: [
{
cwd: path.resolve(extensionPath, bundleFolder),
src: ['*.js', '*.js.map'],
src: ['*.js', '*.js.map', '*.css'],
dest: path.resolve(dropExtensionPath, 'bundle'),
expand: true,
},
@ -335,11 +336,24 @@ module.exports = function(grunt) {
grunt.registerTask('build-assets', ['sass', 'copy:code', 'copy:styles', 'embed-styles:code', 'copy:images']);
// Main entry points for npm scripts:
grunt.registerTask('build-dev', ['clean:intermediates', 'exec:webpack-dev', 'build-assets', 'drop:dev']);
grunt.registerTask('build-prod', ['clean:intermediates', 'exec:webpack-prod', 'build-assets', 'drop:production']);
grunt.registerTask('build-electron', ['clean:intermediates', 'exec:webpack-electron', 'build-assets', 'drop:electron']);
grunt.registerTask('build-dev', ['clean:intermediates', 'exec:generate-scss-typings', 'exec:webpack-dev', 'build-assets', 'drop:dev']);
grunt.registerTask('build-prod', [
'clean:intermediates',
'exec:generate-scss-typings',
'exec:webpack-prod',
'build-assets',
'drop:production',
]);
grunt.registerTask('build-electron', [
'clean:intermediates',
'exec:generate-scss-typings',
'exec:webpack-electron',
'build-assets',
'drop:electron',
]);
grunt.registerTask('build-all', [
'clean:intermediates',
'exec:generate-scss-typings',
'exec:webpack-all',
'build-assets',
'drop:dev',

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

@ -18,6 +18,9 @@ jobs:
- script: yarn copyrightheaders
displayName: check copyrightheaders
- script: yarn generate-scss-typings
displayName: generate typings for scss files
- script: yarn test --ci
displayName: run unit tests

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

@ -21,14 +21,16 @@
"copyrightheaders:fix": "grunt copyright-add",
"format": "prettier --config prettier.config.js --write \"**/*\"",
"format-check": "prettier --config prettier.config.js --check \"**/*\"",
"generate-scss-typings": "tsm src/**/*.scss",
"precheckin": "npm-run-all --serial format-check tslint copyrightheaders build:all test test:e2e",
"start:electron": "electron drop/electron/extension/bundle/main.bundle.js",
"test": "jest --projects src/tests/unit",
"test:e2e": "jest --projects src/tests/end-to-end --runInBand",
"tslint": "tslint -c ./tslint.json -p ./tsconfig.json",
"tslint:fix": "tslint --fix -c ./tslint.json -p ./tsconfig.json",
"watch": "npm-run-all --parallel --race --print-label watch:grunt watch:test watch:webpack",
"watch:build": "npm-run-all --parallel --race --print-label watch:grunt watch:webpack",
"watch": "npm-run-all --parallel --race --print-label watch:scss watch:grunt watch:test watch:webpack",
"watch:build": "npm-run-all --parallel --race --print-label watch:scss watch:grunt watch:webpack",
"watch:scss": "tsm src/**/*.scss --watch",
"watch:grunt": "grunt watch",
"watch:test": "jest --watch --coverage false --colors",
"watch:webpack": "webpack --watch --config-name dev --colors --progress"
@ -52,6 +54,7 @@
"@types/serve-static": "^1.13.2",
"@types/uuid": "^3.4.4",
"case-sensitive-paths-webpack-plugin": "^2.2.0",
"css-loader": "^2.1.1",
"electron": "^5.0.1",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
@ -66,16 +69,19 @@
"grunt-contrib-watch": "^1.1.0",
"grunt-exec": "^3.0.0",
"grunt-sass": "^3.0.2",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.7.1",
"jest-circus": "^24.7.1",
"jest-junit": "^6.3.0",
"license-check-and-add": "2.3.6",
"make-dir": "^1.3.0",
"mini-css-extract-plugin": "^0.6.0",
"node-sass": "^4.12.0",
"npm-run-all": "^4.1.5",
"preprocess": "^3.1.0",
"prettier": "^1.17.0",
"puppeteer": "^1.15.0",
"sass-loader": "^7.1.0",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"source-map-loader": "^0.2.4",
@ -83,6 +89,7 @@
"ts-loader": "^4.4.2",
"tslint": "^5.16.0",
"tslint-microsoft-contrib": "6.1.0",
"typed-scss-modules": "^0.0.10",
"typemoq": "^2.1.0",
"typescript": "^2.9.2",
"uglifyjs-webpack-plugin": "^2.1.2",

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

@ -215,8 +215,8 @@ div.insights-file-issue-details-dialog-container {
}
.failure-instance-panel {
.action-and-cancel-buttons-component {
padding-top: 12px;
.observed-failure-textfield {
padding-bottom: 12px;
}
.add-failure-instruction {
font-weight: 500;
@ -229,14 +229,6 @@ div.insights-file-issue-details-dialog-container {
}
}
.action-and-cancel-buttons-component {
display: flex;
justify-content: flex-end;
.action-cancel-button-col + .action-cancel-button-col {
margin-left: 8px;
}
}
.preview-features-panel {
.preview-feature-toggle-list {
margin-top: 2vh;

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

@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
.action-and-cancel-buttons-component {
display: flex;
justify-content: flex-end;
.action-cancel-button-col + .action-cancel-button-col {
margin-left: 8px;
}
}

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

@ -4,6 +4,8 @@ import { isEmpty } from 'lodash';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import * as React from 'react';
import { actionAndCancelButtonsComponent, actionCancelButtonCol } from './action-and-cancel-buttons-component.scss';
export interface ActionAndCancelButtonsComponentProps {
isHidden: boolean;
primaryButtonDisabled: boolean;
@ -16,11 +18,11 @@ export interface ActionAndCancelButtonsComponentProps {
export class ActionAndCancelButtonsComponent extends React.Component<ActionAndCancelButtonsComponentProps> {
public render(): JSX.Element {
return (
<div className="action-and-cancel-buttons-component" hidden={this.props.isHidden}>
<div className="button action-cancel-button-col">
<div className={actionAndCancelButtonsComponent} hidden={this.props.isHidden}>
<div className={actionCancelButtonCol}>
<DefaultButton text={'Cancel'} onClick={this.props.cancelButtonOnClick} />
</div>
<div className="button action-cancel-button-col">
<div className={actionCancelButtonCol}>
<DefaultButton
primary={true}
text={this.props.primaryButtonText}

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

@ -93,6 +93,7 @@ export class FailureInstancePanelControl extends React.Component<FailureInstance
<GenericPanel {...panelProps}>
{testStepConfig.addFailureInstruction}
<TextField
className="observed-failure-textfield"
label="Observed failure"
multiline={true}
rows={8}

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

@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
@import '../../common/styles/fonts.scss';
.no-preview-feature-message {
font-size: 20px;
font-family: $semiBoldFontFamily;
}

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

@ -1,10 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import * as React from 'react';
import { DisplayableStrings } from '../../common/constants/displayable-strings';
import { DisplayableStrings } from '../../common/constants/displayable-strings';
import * as styles from './no-displayable-preview-features-message.scss';
export const componentId = 'no-displayable-feature-flag-message';
export const NoDisplayableFeatureFlagMessage = () => (
<>
<div className="no-preview-feature-message">{DisplayableStrings.noPreviewFeatureDisplayMessage}</div>
<div id={componentId} className={styles.noPreviewFeatureMessage}>
{DisplayableStrings.noPreviewFeatureDisplayMessage}
</div>
</>
);

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

@ -8,6 +8,7 @@ Licensed under the MIT License.
<link rel="shortcut icon" type="image/x-icon" href="../icons/brand/blue/brand-blue-16px.png" />
<link rel="stylesheet" type="text/css" href="../common/styles/fabric.min.css" />
<link rel="stylesheet" type="text/css" href="./styles/default/detailsview.css" />
<link rel="stylesheet" type="text/css" href="../bundle/detailsview.css" />
<title>Accessibility Insights for Web</title>
<script src="../insights.config.js"></script>
</head>

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

@ -7,7 +7,7 @@ import { BrowserAdapter } from '../browser-adapters/browser-adapter';
export class ContentScriptInjector {
public static readonly jsFiles: string[] = ['bundle/injected.bundle.js'];
public static readonly cssFiles: string[] = ['injected/styles/default/injected.css'];
public static readonly cssFiles: string[] = ['injected/styles/default/injected.css', 'bundle/injected.css'];
public static timeoutInMilliSec = 5e4;
private readonly _chromeAdapter: BrowserAdapter;

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

@ -9,6 +9,7 @@ import { rootContainerId } from './constants';
export class ShadowInitializer {
public static readonly injectedCssPath: string = 'injected/styles/default/injected.css';
public static readonly generatedBundleInjectedCssPath: string = 'bundle/injected.css';
constructor(
private chromeAdapter: ClientBrowserAdapter,
@ -21,7 +22,9 @@ export class ShadowInitializer {
try {
const shadowContainer = this.createShadowContainer();
const injectedCssContent = await this.getFileContentByPath(ShadowInitializer.injectedCssPath);
const generatedBundleInjectedCssContent = await this.getFileContentByPath(ShadowInitializer.generatedBundleInjectedCssPath);
this.addStyleElement(injectedCssContent, shadowContainer);
this.addStyleElement(generatedBundleInjectedCssContent, shadowContainer);
} catch (err) {
this.logger.log('unable to insert styles under shadow', err);
}

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

@ -22,7 +22,7 @@
"persistent": true
},
"devtools_page": "devtools/devtools.html",
"web_accessible_resources": ["insights.html", "assessments/*", "injected/*", "background/*", "common/*", "DetailsView/*"],
"web_accessible_resources": ["insights.html", "assessments/*", "injected/*", "background/*", "common/*", "DetailsView/*", "bundle/*"],
"permissions": ["storage", "webNavigation", "tabs", "notifications", "https://*/*", "http://*/*", "file://*/*"],
"commands": {
"_execute_browser_action": {

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

@ -7,6 +7,7 @@ Licensed under the MIT License.
<head>
<link rel="stylesheet" type="text/css" href="../common/styles/fabric.min.css" />
<link rel="stylesheet" type="text/css" href="./styles/default/popup.css" />
<link rel="stylesheet" type="text/css" href="../bundle/popup.css" />
<title>Accessibility Insights for Web</title>
<script src="../insights.config.js"></script>
</head>

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

@ -3,5 +3,4 @@
export const detailsViewSelectors = {
previewFeaturesPanel: '.preview-features-panel',
previewFeaturesPanelToggleList: '.preview-feature-toggle-list',
noPreviewFeaturesMessage: '.no-preview-feature-message',
};

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

@ -64,6 +64,10 @@ export class Page {
);
}
public async waitForId(id: string): Promise<Puppeteer.ElementHandle<Element>> {
return this.waitForSelector(`#${id}`);
}
public async waitForSelectorToDisappear(selector: string): Promise<void> {
await this.screenshotOnError(
async () =>

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

@ -66,6 +66,7 @@ exports[`Preview Features Panel Normal mode should match content in snapshot 1`]
>
<div
class="no-preview-feature-message"
id="no-displayable-feature-flag-message"
>
No preview features are currently available to manage. Follow this page for future cool features.
</div>

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

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { componentId } from '../../../../DetailsView/components/no-displayable-preview-features-message';
import { Browser } from '../../common/browser';
import { launchBrowser } from '../../common/browser-factory';
import { CommonSelectors } from '../../common/element-identifiers/common-selectors';
@ -76,7 +77,7 @@ describe('Preview Features Panel', () => {
const detailsViewPage = await waitForDetailsViewWithPreviewFeaturesPanel(browser, popupPage, targetTabId);
await detailsViewPage.waitForSelector(detailsViewSelectors.noPreviewFeaturesMessage);
await detailsViewPage.waitForId(componentId);
return detailsViewPage;
}

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

@ -6,6 +6,8 @@ module.exports = {
'office-ui-fabric-react/lib/(.*)$': 'office-ui-fabric-react/lib-commonjs/$1',
'@uifabric/utilities': '@uifabric/utilities/lib-commonjs',
'@uifabric/styling': '@uifabric/styling/lib-commonjs',
/* Using proxy to handle css modules, as per: https://jestjs.io/docs/en/webpack#mocking-css-modules */
'\\.(scss)$': 'identity-obj-proxy',
},
// This ensures that failures in beforeAll/beforeEach result in dependent tests not trying to run.
// See https://github.com/facebook/jest/issues/2713

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

@ -2,11 +2,11 @@
exports[`ActionAndCancelButtonsComponent render with primary button href == null 1`] = `
<div
className="action-and-cancel-buttons-component"
className="actionAndCancelButtonsComponent"
hidden={false}
>
<div
className="button action-cancel-button-col"
className="actionCancelButtonCol"
>
<CustomizedDefaultButton
onClick={[Function]}
@ -14,7 +14,7 @@ exports[`ActionAndCancelButtonsComponent render with primary button href == null
/>
</div>
<div
className="button action-cancel-button-col"
className="actionCancelButtonCol"
>
<CustomizedDefaultButton
disabled={false}
@ -30,11 +30,11 @@ exports[`ActionAndCancelButtonsComponent render with primary button href == null
exports[`ActionAndCancelButtonsComponent render with primary button href == sample href 1`] = `
<div
className="action-and-cancel-buttons-component"
className="actionAndCancelButtonsComponent"
hidden={false}
>
<div
className="button action-cancel-button-col"
className="actionCancelButtonCol"
>
<CustomizedDefaultButton
onClick={[Function]}
@ -42,7 +42,7 @@ exports[`ActionAndCancelButtonsComponent render with primary button href == samp
/>
</div>
<div
className="button action-cancel-button-col"
className="actionCancelButtonCol"
>
<CustomizedDefaultButton
disabled={false}

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

@ -1,25 +1,82 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FailureInstancePanelControlTest render FailureInstancePanelControl: add instance 1`] = `
"<Fragment>
<CustomizedActionButton ariaLabel=\\"Add a failure instance\\" ariaDescription=\\"Open add a failure instance panel\\" iconProps={{...}} onClick={[Function: bound ]}>
<React.Fragment>
<CustomizedActionButton
ariaDescription="Open add a failure instance panel"
ariaLabel="Add a failure instance"
iconProps={
Object {
"iconName": "Add",
}
}
onClick={[Function]}
>
Add a failure instance
</CustomizedActionButton>
<GenericPanel isOpen={false} className=\\"failure-instance-panel\\" onDismiss={[Function: bound ]} title=\\"Add a failure instance\\" hasCloseButton={false} closeButtonAriaLabel={{...}}>
<StyledTextFieldBase label=\\"Observed failure\\" multiline={true} rows={8} value=\\"\\" onChange={[Function: bound ]} resizable={false} />
<ActionAndCancelButtonsComponent isHidden={false} primaryButtonDisabled={true} primaryButtonText=\\"Add\\" primaryButtonOnClick={[Function: bound ]} cancelButtonOnClick={[Function: bound ]} />
<GenericPanel
className="failure-instance-panel"
closeButtonAriaLabel={null}
hasCloseButton={false}
isOpen={false}
onDismiss={[Function]}
title="Add a failure instance"
>
<StyledTextFieldBase
className="observed-failure-textfield"
label="Observed failure"
multiline={true}
onChange={[Function]}
resizable={false}
rows={8}
value=""
/>
<ActionAndCancelButtonsComponent
cancelButtonOnClick={[Function]}
isHidden={false}
primaryButtonDisabled={true}
primaryButtonOnClick={[Function]}
primaryButtonText="Add"
/>
</GenericPanel>
</Fragment>"
</React.Fragment>
`;
exports[`FailureInstancePanelControlTest render FailureInstancePanelControl: edit instance 1`] = `
"<Fragment>
<StyledLinkBase className=\\"edit-button\\" onClick={[Function: bound ]}>
<StyledIconBase iconName=\\"edit\\" ariaLabel=\\"edit instance\\" />
<React.Fragment>
<StyledLinkBase
className="edit-button"
onClick={[Function]}
>
<StyledIconBase
ariaLabel="edit instance"
iconName="edit"
/>
</StyledLinkBase>
<GenericPanel isOpen={false} className=\\"failure-instance-panel\\" onDismiss={[Function: bound ]} title=\\"Edit failure instance\\" hasCloseButton={false} closeButtonAriaLabel={{...}}>
<StyledTextFieldBase label=\\"Observed failure\\" multiline={true} rows={8} value=\\"\\" onChange={[Function: bound ]} resizable={false} />
<ActionAndCancelButtonsComponent isHidden={false} primaryButtonDisabled={true} primaryButtonText=\\"Save\\" primaryButtonOnClick={[Function: bound ]} cancelButtonOnClick={[Function: bound ]} />
<GenericPanel
className="failure-instance-panel"
closeButtonAriaLabel={null}
hasCloseButton={false}
isOpen={false}
onDismiss={[Function]}
title="Edit failure instance"
>
<StyledTextFieldBase
className="observed-failure-textfield"
label="Observed failure"
multiline={true}
onChange={[Function]}
resizable={false}
rows={8}
value=""
/>
<ActionAndCancelButtonsComponent
cancelButtonOnClick={[Function]}
isHidden={false}
primaryButtonDisabled={true}
primaryButtonOnClick={[Function]}
primaryButtonText="Save"
/>
</GenericPanel>
</Fragment>"
</React.Fragment>
`;

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

@ -3,7 +3,8 @@
exports[`no displayableFeatureFlags message test the no feature flag message component 1`] = `
<React.Fragment>
<div
className="no-preview-feature-message"
className="noPreviewFeatureMessage"
id="no-displayable-feature-flag-message"
>
No preview features are currently available to manage. Follow this page for future cool features.
</div>

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

@ -29,14 +29,14 @@ describe('FailureInstancePanelControlTest', () => {
const props = createPropsWithType(CapturedInstanceActionType.CREATE);
const rendered = shallow(<FailureInstancePanelControl {...props} />);
expect(rendered.debug()).toMatchSnapshot();
expect(rendered.getElement()).toMatchSnapshot();
});
test('render FailureInstancePanelControl: edit instance', () => {
const props = createPropsWithType(CapturedInstanceActionType.EDIT);
const rendered = shallow(<FailureInstancePanelControl {...props} />);
expect(rendered.debug()).toMatchSnapshot();
expect(rendered.getElement()).toMatchSnapshot();
});
test('onFailureDescriptionChange', () => {
@ -120,7 +120,6 @@ describe('FailureInstancePanelControlTest', () => {
const props = createPropsWithType(CapturedInstanceActionType.CREATE);
addInstanceMock.setup(handler => handler(description, props.test, props.step)).verifiable(Times.once());
const wrapper = Enzyme.shallow(<FailureInstancePanelControl {...props} />);
wrapper

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

@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ShadowInitializerTests add style data to shadow container 1`] = `
<div>
<div
id="insights-shadow-host"
/>
</div>
`;
exports[`ShadowInitializerTests add style data to shadow container 2`] = `
<div>
<div
id="insights-shadow-container"
>
<style>
injectedCss style content
</style>
<style>
generatedBundleInjectedCss style content
</style>
</div>
</div>
`;
exports[`ShadowInitializerTests remove existing & create new shadow container on initialize 1`] = `
<div>
<div
id="insights-shadow-host"
/>
</div>
`;
exports[`ShadowInitializerTests remove existing & create new shadow container on initialize 2`] = `
<div>
<div
id="insights-shadow-container"
>
<style>
injectedCss style content
</style>
<style>
generatedBundleInjectedCss style content
</style>
</div>
</div>
`;

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

@ -9,7 +9,8 @@ import { rootContainerId } from '../../../../injected/constants';
import { ShadowInitializer } from '../../../../injected/shadow-initializer';
describe('ShadowInitializerTests', () => {
const cssFileUrl: string = 'cssFileUrl';
const injectedCssPathFileUrl: string = 'injectedCssPathFileUrl';
const generatedBundleInjectedCssPathFileUrl: string = 'generatedBundleInjectedCssPathFileUrl';
let testSubject: ShadowInitializer;
let chromeAdapter: IMock<ClientBrowserAdapter>;
let htmlElementUtilsMock: IMock<HTMLElementUtils>;
@ -42,9 +43,13 @@ describe('ShadowInitializerTests', () => {
chromeAdapter
.setup(x => x.getUrl(ShadowInitializer.injectedCssPath))
.returns(() => cssFileUrl)
.returns(() => injectedCssPathFileUrl)
.verifiable();
chromeAdapter
.setup(x => x.getUrl(ShadowInitializer.generatedBundleInjectedCssPath))
.returns(() => generatedBundleInjectedCssPathFileUrl);
const loggerMock = Mock.ofType<Logger>();
testSubject = new ShadowInitializer(
chromeAdapter.object,
@ -62,15 +67,19 @@ describe('ShadowInitializerTests', () => {
htmlElementUtilsMock.setup(x => x.deleteAllElements('#insights-shadow-host')).verifiable();
fileRequestHelperMock
.setup(x => x.getFileContent(cssFileUrl))
.returns(async () => 'new style content')
.setup(x => x.getFileContent(injectedCssPathFileUrl))
.returns(async () => 'injectedCss style content')
.verifiable(Times.once());
fileRequestHelperMock
.setup(x => x.getFileContent(generatedBundleInjectedCssPathFileUrl))
.returns(async () => 'generatedBundleInjectedCss style content')
.verifiable(Times.once());
await testSubject.initialize();
expect(rootContainer.querySelectorAll('#insights-shadow-host').length).toEqual(1);
expect(shadowRoot.querySelectorAll('div#insights-shadow-container').length).toEqual(1);
expect(shadowRoot.querySelectorAll('div#insights-shadow-container *').length).toEqual(1);
expect(rootContainer).toMatchSnapshot();
expect(shadowRoot).toMatchSnapshot();
htmlElementUtilsMock.verifyAll();
fileRequestHelperMock.verifyAll();
@ -78,20 +87,22 @@ describe('ShadowInitializerTests', () => {
});
test('add style data to shadow container', async () => {
const styleContent = 'style content';
fileRequestHelperMock
.setup(x => x.getFileContent(injectedCssPathFileUrl))
.returns(async () => 'injectedCss style content')
.verifiable(Times.once());
fileRequestHelperMock
.setup(x => x.getFileContent(cssFileUrl))
.returns(async () => styleContent)
.setup(x => x.getFileContent(generatedBundleInjectedCssPathFileUrl))
.returns(async () => 'generatedBundleInjectedCss style content')
.verifiable(Times.once());
expect(shadowRoot.querySelectorAll('div#insights-shadow-container style').length).toEqual(0);
await testSubject.initialize();
expect(shadowRoot.querySelectorAll('div#insights-shadow-container style').length).toEqual(1);
const styleElement = shadowRoot.querySelector('div#insights-shadow-container style');
expect(styleElement.innerHTML).toEqual(styleContent);
expect(rootContainer).toMatchSnapshot();
expect(shadowRoot).toMatchSnapshot();
fileRequestHelperMock.verifyAll();
chromeAdapter.verifyAll();

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

@ -5,6 +5,25 @@ const webpack = require('webpack');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const getCSSModulesLoadersConfig = isDevMode => {
return {
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
camelCase: 'only',
localIdentName: isDevMode ? '[local]' : '[local][hash:base64:5]',
},
},
'sass-loader',
],
};
};
const commonPlugins = [
new webpack.optimize.LimitChunkCountPlugin({
@ -17,6 +36,12 @@ const commonPlugins = [
// tslint separate from webpack.
new ForkTsCheckerWebpackPlugin(),
new CaseSensitivePathsPlugin(),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
];
const commonEntryFiles = {
@ -67,8 +92,17 @@ const commonConfig = {
},
};
const devModules = {
rules: [...commonConfig.module.rules, getCSSModulesLoadersConfig(true)],
};
const prodModules = {
rules: [...commonConfig.module.rules, getCSSModulesLoadersConfig(false)],
};
const electronConfig = {
...commonConfig,
module: devModules,
entry: electronEntryFiles,
name: 'electron',
mode: 'development',
@ -89,6 +123,7 @@ const electronConfig = {
const devConfig = {
...commonConfig,
module: devModules,
name: 'dev',
mode: 'development',
devtool: 'eval-source-map',
@ -103,6 +138,7 @@ const devConfig = {
const prodConfig = {
...commonConfig,
module: prodModules,
name: 'prod',
mode: 'production',
devtool: false,

420
yarn.lock
Просмотреть файл

@ -516,6 +516,11 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/reserved-words@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@types/reserved-words/-/reserved-words-0.1.0.tgz#a9d5318bb4ac4466862b93fc702542b75d2cd3ac"
integrity sha512-ls6lSkkhEFm8XSVQjHj47pJoCL9sVK91mwIONw0Iwjqkmy98ForMFYa5+/vb6sytTaK0HSwkzKKYzREPTUhhhg==
"@types/serve-static@^1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48"
@ -1455,7 +1460,7 @@ camelcase@^4.1.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
camelcase@^5.0.0:
camelcase@^5.0.0, camelcase@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@ -1528,6 +1533,25 @@ chokidar@^2.0.2, chokidar@^2.0.4:
optionalDependencies:
fsevents "^1.2.7"
chokidar@^2.1.2:
version "2.1.6"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5"
integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==
dependencies:
anymatch "^2.0.0"
async-each "^1.0.1"
braces "^2.3.2"
glob-parent "^3.1.0"
inherits "^2.0.3"
is-binary-path "^1.0.0"
is-glob "^4.0.0"
normalize-path "^3.0.0"
path-is-absolute "^1.0.0"
readdirp "^2.2.1"
upath "^1.1.1"
optionalDependencies:
fsevents "^1.2.7"
chownr@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
@ -1591,6 +1615,16 @@ cliui@^4.0.0:
strip-ansi "^4.0.0"
wrap-ansi "^2.0.0"
clone-deep@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713"
integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==
dependencies:
for-own "^1.0.0"
is-plain-object "^2.0.4"
kind-of "^6.0.0"
shallow-clone "^1.0.0"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@ -1823,6 +1857,35 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
css-loader@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea"
integrity sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==
dependencies:
camelcase "^5.2.0"
icss-utils "^4.1.0"
loader-utils "^1.2.3"
normalize-path "^3.0.0"
postcss "^7.0.14"
postcss-modules-extract-imports "^2.0.0"
postcss-modules-local-by-default "^2.0.6"
postcss-modules-scope "^2.1.0"
postcss-modules-values "^2.0.0"
postcss-value-parser "^3.3.0"
schema-utils "^1.0.0"
css-modules-loader-core@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16"
integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY=
dependencies:
icss-replace-symbols "1.1.0"
postcss "6.0.1"
postcss-modules-extract-imports "1.1.0"
postcss-modules-local-by-default "1.2.0"
postcss-modules-scope "1.1.0"
postcss-modules-values "1.3.0"
css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
@ -1833,11 +1896,30 @@ css-select@~1.2.0:
domutils "1.5.1"
nth-check "~1.0.1"
css-selector-tokenizer@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==
dependencies:
cssesc "^0.1.0"
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css-what@2.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
version "0.3.6"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.6.tgz#f85206cee04efa841f3c5982a74ba96ab20d65ad"
@ -2550,6 +2632,11 @@ fast-levenshtein@~2.0.4:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fastparse@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
faye-websocket@~0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
@ -2677,6 +2764,11 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
for-in@^0.1.3:
version "0.1.8"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
integrity sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=
for-in@^1.0.1, for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@ -3102,6 +3194,11 @@ har-validator@~5.1.0:
ajv "^6.5.5"
har-schema "^2.0.0"
harmony-reflect@^1.4.6:
version "1.6.1"
resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9"
integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA==
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
@ -3109,6 +3206,11 @@ has-ansi@^2.0.0:
dependencies:
ansi-regex "^2.0.0"
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -3298,6 +3400,25 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
dependencies:
safer-buffer ">= 2.1.2 < 3"
icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
icss-utils@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.0.tgz#339dbbffb9f8729a243b701e1c29d4cc58c52f0e"
integrity sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==
dependencies:
postcss "^7.0.14"
identity-obj-proxy@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14"
integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ=
dependencies:
harmony-reflect "^1.4.6"
ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
@ -3340,6 +3461,11 @@ indent-string@^2.1.0:
dependencies:
repeating "^2.0.0"
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
@ -3560,6 +3686,11 @@ is-number@^3.0.0:
dependencies:
kind-of "^3.0.2"
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -4182,6 +4313,11 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@ -4351,7 +4487,7 @@ loader-runner@^2.3.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
loader-utils@^1.0.2, loader-utils@^1.1.0:
loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
@ -4388,6 +4524,11 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash.tail@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=
lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@~4.17.10, lodash@~4.17.5:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
@ -4408,6 +4549,11 @@ loud-rejection@^1.0.0:
currently-unhandled "^0.4.1"
signal-exit "^3.0.0"
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
lru-cache@^4.0.1:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@ -4609,6 +4755,16 @@ mimic-fn@^2.0.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mini-css-extract-plugin@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz#a3f13372d6fcde912f3ee4cd039665704801e3b9"
integrity sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==
dependencies:
loader-utils "^1.1.0"
normalize-url "^2.0.1"
schema-utils "^1.0.0"
webpack-sources "^1.1.0"
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@ -4680,6 +4836,14 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
mixin-object@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e"
integrity sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=
dependencies:
for-in "^0.1.3"
is-extendable "^0.1.1"
mkdirp@0.5.1, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
@ -4781,6 +4945,13 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
no-case@^2.2.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"
node-gyp@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
@ -4925,6 +5096,15 @@ normalize-path@^3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
normalize-url@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6"
integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==
dependencies:
prepend-http "^2.0.0"
query-string "^5.0.1"
sort-keys "^2.0.0"
npm-bundled@^1.0.1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"
@ -5267,6 +5447,13 @@ parallel-transform@^1.1.0:
inherits "^2.0.3"
readable-stream "^2.1.5"
param-case@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"
parse-asn1@^5.0.0:
version "5.1.4"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc"
@ -5407,6 +5594,14 @@ path-type@^3.0.0:
dependencies:
pify "^3.0.0"
path@^0.12.7:
version "0.12.7"
resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f"
integrity sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=
dependencies:
process "^0.11.1"
util "^0.10.3"
pbkdf2@^3.0.3:
version "3.0.17"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
@ -5494,6 +5689,110 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-modules-extract-imports@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb"
integrity sha1-thTJcgvmgW6u41+zpfqh26agXds=
dependencies:
postcss "^6.0.1"
postcss-modules-extract-imports@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==
dependencies:
postcss "^7.0.5"
postcss-modules-local-by-default@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
postcss-modules-local-by-default@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz#dd9953f6dd476b5fd1ef2d8830c8929760b56e63"
integrity sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==
dependencies:
postcss "^7.0.6"
postcss-selector-parser "^6.0.0"
postcss-value-parser "^3.3.1"
postcss-modules-scope@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
postcss-modules-scope@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb"
integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==
dependencies:
postcss "^7.0.6"
postcss-selector-parser "^6.0.0"
postcss-modules-values@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
dependencies:
icss-replace-symbols "^1.1.0"
postcss "^6.0.1"
postcss-modules-values@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64"
integrity sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==
dependencies:
icss-replace-symbols "^1.1.0"
postcss "^7.0.6"
postcss-selector-parser@^6.0.0:
version "6.0.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==
dependencies:
cssesc "^3.0.0"
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
postcss@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2"
integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=
dependencies:
chalk "^1.1.3"
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@^6.0.1:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
dependencies:
chalk "^2.4.1"
source-map "^0.6.1"
supports-color "^5.4.0"
postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.16"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.16.tgz#48f64f1b4b558cb8b52c88987724359acb010da2"
integrity sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==
dependencies:
chalk "^2.4.2"
source-map "^0.6.1"
supports-color "^6.1.0"
postinstall-build@^5.0.1:
version "5.0.3"
resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
@ -5504,6 +5803,11 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
prepend-http@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
preprocess@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/preprocess/-/preprocess-3.1.0.tgz#a44e5cdd5bbb5a54f0ad289aaeed80995d7d938a"
@ -5539,7 +5843,7 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
process@^0.11.10:
process@^0.11.1, process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
@ -5697,6 +6001,15 @@ qs@^6.4.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
query-string@^5.0.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==
dependencies:
decode-uri-component "^0.2.0"
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@ -5978,6 +6291,11 @@ reflect.ownkeys@^0.2.0:
resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
regenerate@^1.2.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
regenerator-runtime@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
@ -5991,6 +6309,27 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=
dependencies:
regenerate "^1.2.1"
regjsgen "^0.2.0"
regjsparser "^0.1.4"
regjsgen@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
regjsparser@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=
dependencies:
jsesc "~0.5.0"
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@ -6075,6 +6414,11 @@ requirejs@2.3.5:
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.5.tgz#617b9acbbcb336540ef4914d790323a8d4b861b0"
integrity sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==
reserved-words@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1"
integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@ -6211,6 +6555,18 @@ sass-graph@^2.2.4:
scss-tokenizer "^0.2.3"
yargs "^7.0.0"
sass-loader@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d"
integrity sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==
dependencies:
clone-deep "^2.0.1"
loader-utils "^1.0.1"
lodash.tail "^4.1.1"
neo-async "^2.5.0"
pify "^3.0.0"
semver "^5.5.0"
sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@ -6340,6 +6696,15 @@ sha.js@^2.4.0, sha.js@^2.4.8:
inherits "^2.0.1"
safe-buffer "^5.0.1"
shallow-clone@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571"
integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==
dependencies:
is-extendable "^0.1.1"
kind-of "^5.0.0"
mixin-object "^2.0.1"
shallowequal@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
@ -6424,6 +6789,13 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
sort-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=
dependencies:
is-plain-obj "^1.0.0"
source-list-map@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
@ -6615,6 +6987,11 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
string-length@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
@ -6744,7 +7121,14 @@ supports-color@^2.0.0:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
supports-color@^5.3.0, supports-color@^5.5.0:
supports-color@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
dependencies:
has-flag "^1.0.0"
supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@ -7071,6 +7455,22 @@ type-is@~1.6.16:
media-typer "0.3.0"
mime-types "~2.1.24"
typed-scss-modules@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/typed-scss-modules/-/typed-scss-modules-0.0.10.tgz#2a9f8d1657b5e299b630df195b84ee21bffd1d9e"
integrity sha512-uI3eoAsghJEaiGaex9PzQA6qHY4KX6Qx4iTXRWshBR/yMagivWxd24c7ku7C3422w11m+vgCgA4/zZqwc/9uWQ==
dependencies:
"@types/reserved-words" "^0.1.0"
camelcase "^5.0.0"
chalk "^2.4.2"
chokidar "^2.1.2"
css-modules-loader-core "^1.1.0"
glob "^7.1.3"
param-case "^2.1.1"
path "^0.12.7"
reserved-words "^0.1.2"
yargs "^12.0.5"
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@ -7155,6 +7555,11 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^0.4.3"
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
unique-filename@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
@ -7237,6 +7642,13 @@ util@0.10.3:
dependencies:
inherits "2.0.1"
util@^0.10.3:
version "0.10.4"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901"
integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==
dependencies:
inherits "2.0.3"
util@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"