From c453894ecd04d8b3dd42014b750d828329dfc681 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 30 Jun 2020 15:11:43 -0700 Subject: [PATCH 01/24] [kbn/optimizer] only build specified themes --- packages/kbn-optimizer/src/common/index.ts | 1 + .../kbn-optimizer/src/common/theme_tags.ts | 63 +++++++++++++++++++ .../kbn-optimizer/src/common/worker_config.ts | 5 ++ .../src/optimizer/optimizer_config.ts | 21 ++++++- .../kbn-optimizer/src/worker/theme_loader.ts | 30 ++++++--- .../src/worker/webpack.config.ts | 32 +++++++--- .../ui/ui_render/bootstrap/template.js.hbs | 1 + src/legacy/ui/ui_render/ui_render_mixin.js | 4 ++ 8 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 packages/kbn-optimizer/src/common/theme_tags.ts diff --git a/packages/kbn-optimizer/src/common/index.ts b/packages/kbn-optimizer/src/common/index.ts index 7d021a5ee78475..89cde2c1cd064f 100644 --- a/packages/kbn-optimizer/src/common/index.ts +++ b/packages/kbn-optimizer/src/common/index.ts @@ -29,3 +29,4 @@ export * from './array_helpers'; export * from './event_stream_helpers'; export * from './disallowed_syntax_plugin'; export * from './parse_path'; +export * from './theme_tags'; diff --git a/packages/kbn-optimizer/src/common/theme_tags.ts b/packages/kbn-optimizer/src/common/theme_tags.ts new file mode 100644 index 00000000000000..47728e1309f11a --- /dev/null +++ b/packages/kbn-optimizer/src/common/theme_tags.ts @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ascending } from './array_helpers'; + +const tags = (...themeTags: string[]) => Object.freeze(themeTags.sort(ascending()) as ThemeTag[]); +const validTag = (tag: any): tag is ThemeTag => ALL_THEMES.includes(tag); +const isArrayOfStrings = (input: unknown): input is string[] => + Array.isArray(input) && input.every((v) => typeof v === 'string'); + +export type ThemeTags = readonly ThemeTag[]; +export type ThemeTag = 'v7light' | 'v7dark' | 'v8light' | 'v8dark'; +export const DEFAULT_THEMES = tags('v7light'); +export const ALL_THEMES = tags('v7light', 'v7dark', 'v8light', 'v8dark'); + +export function parseThemeTags(input?: any): ThemeTags { + if (!input) { + return DEFAULT_THEMES; + } + + if (input === '*') { + return ALL_THEMES; + } + + if (typeof input === 'string') { + input = input.split(',').map((tag) => tag.trim()); + } + + if (!isArrayOfStrings(input)) { + throw new Error(`Invalid theme tags, must be an array of strings`); + } + + if (!input.length) { + throw new Error( + `Invalid theme tags, you must specify at least one of [${ALL_THEMES.join(', ')}]` + ); + } + + const invalidTags = input.filter((t) => !validTag(t)); + if (invalidTags.length) { + throw new Error( + `Invalid theme tags [${invalidTags.join(', ')}], options: [${ALL_THEMES.join(', ')}]` + ); + } + + return tags(...input); +} diff --git a/packages/kbn-optimizer/src/common/worker_config.ts b/packages/kbn-optimizer/src/common/worker_config.ts index a1ab51ee97c231..8726b3452ff1e1 100644 --- a/packages/kbn-optimizer/src/common/worker_config.ts +++ b/packages/kbn-optimizer/src/common/worker_config.ts @@ -20,11 +20,13 @@ import Path from 'path'; import { UnknownVals } from './ts_helpers'; +import { ThemeTags, parseThemeTags } from './theme_tags'; export interface WorkerConfig { readonly repoRoot: string; readonly watch: boolean; readonly dist: boolean; + readonly themeTags: ThemeTags; readonly cache: boolean; readonly profileWebpack: boolean; readonly browserslistEnv: string; @@ -80,6 +82,8 @@ export function parseWorkerConfig(json: string): WorkerConfig { throw new Error('`browserslistEnv` must be a string'); } + const themes = parseThemeTags(parsed.themeTags); + return { repoRoot, cache, @@ -88,6 +92,7 @@ export function parseWorkerConfig(json: string): WorkerConfig { profileWebpack, optimizerCacheKey, browserslistEnv, + themeTags: themes, }; } catch (error) { throw new Error(`unable to parse worker config: ${error.message}`); diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index c9e9b3ad01ccc6..58317aefe2846e 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -20,7 +20,7 @@ import Path from 'path'; import Os from 'os'; -import { Bundle, WorkerConfig, CacheableWorkerConfig } from '../common'; +import { Bundle, WorkerConfig, CacheableWorkerConfig, ThemeTags, parseThemeTags } from '../common'; import { findKibanaPlatformPlugins, KibanaPlatformPlugin } from './kibana_platform_plugins'; import { getPluginBundles } from './get_plugin_bundles'; @@ -73,6 +73,14 @@ interface Options { /** flag that causes the core bundle to be built along with plugins */ includeCoreBundle?: boolean; + + /** + * style themes that sass files will be converted to, the correct style will be + * loaded in the browser automatically by checking the global `__kbnThemeTag__`. + * Specifying additional styles increases build time. Defaults to all styles when + * building the dist + */ + themes?: ThemeTag[]; } interface ParsedOptions { @@ -86,6 +94,7 @@ interface ParsedOptions { pluginScanDirs: string[]; inspectWorkers: boolean; includeCoreBundle: boolean; + themeTags: ThemeTags; } export class OptimizerConfig { @@ -139,6 +148,8 @@ export class OptimizerConfig { throw new TypeError('worker count must be a number'); } + const themes = parseThemeTags(options.themes || process.env.KBN_OPTIMIZER_THEME); + return { watch, dist, @@ -150,6 +161,7 @@ export class OptimizerConfig { pluginPaths, inspectWorkers, includeCoreBundle, + themeTags: themes, }; } @@ -181,7 +193,8 @@ export class OptimizerConfig { options.repoRoot, options.maxWorkerCount, options.dist, - options.profileWebpack + options.profileWebpack, + options.themeTags ); } @@ -194,7 +207,8 @@ export class OptimizerConfig { public readonly repoRoot: string, public readonly maxWorkerCount: number, public readonly dist: boolean, - public readonly profileWebpack: boolean + public readonly profileWebpack: boolean, + public readonly themeTags: ThemeTags ) {} getWorkerConfig(optimizerCacheKey: unknown): WorkerConfig { @@ -205,6 +219,7 @@ export class OptimizerConfig { repoRoot: this.repoRoot, watch: this.watch, optimizerCacheKey, + themeTags: this.themeTags, browserslistEnv: this.dist ? 'production' : process.env.BROWSERSLIST_ENV || 'dev', }; } diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index 5d02462ef1bb87..64641daeea8099 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -17,16 +17,32 @@ * under the License. */ +import { stringifyRequest, getOptions } from 'loader-utils'; import webpack from 'webpack'; -import { stringifyRequest } from 'loader-utils'; +import { parseThemeTags, ALL_THEMES } from '../common'; // eslint-disable-next-line import/no-default-export export default function (this: webpack.loader.LoaderContext) { + this.cacheable(true); + + const themeTags = parseThemeTags(getOptions(this).themeTags); + + const cases = ALL_THEMES.map((tag) => { + if (themeTags.includes(tag)) { + return ` + case '${tag}': + return require(${stringifyRequest(this, `${this.resourcePath}?${tag}`)});`; + } + + const fallback = themeTags[0]; + const message = `Styles for [${tag}] were not built by the current @kbn/optimizer config. Falling back to [${fallback}] theme to make Kibana usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEME environment variable includes [${tag}] in a comma separated list of themes you want to use. You can also set it to "*" to build all themes.`; + return ` + case '${tag}': + console.error(new Error(${JSON.stringify(message)})); + return require(${stringifyRequest(this, `${this.resourcePath}?${fallback}`)})`; + }).join('\n'); + return ` -if (window.__kbnDarkMode__) { - require(${stringifyRequest(this, `${this.resourcePath}?dark`)}) -} else { - require(${stringifyRequest(this, `${this.resourcePath}?light`)}); -} - `; +switch (window.__kbnThemeTag__) {${cases} +}`; } diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 11f5544cd9274d..b5dd482364407e 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -30,7 +30,14 @@ import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import CompressionPlugin from 'compression-webpack-plugin'; import * as UiSharedDeps from '@kbn/ui-shared-deps'; -import { Bundle, BundleRefs, WorkerConfig, parseDirPath, DisallowedSyntaxPlugin } from '../common'; +import { + Bundle, + BundleRefs, + WorkerConfig, + parseDirPath, + DisallowedSyntaxPlugin, + validateThemeTagList, +} from '../common'; import { BundleRefsPlugin } from './bundle_refs_plugin'; const IS_CODE_COVERAGE = !!process.env.CODE_COVERAGE; @@ -135,7 +142,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: exclude: /node_modules/, oneOf: [ { - resourceQuery: /dark|light/, + resourceQuery: /^\?v\d(light|dark)$/, use: [ { loader: 'style-loader', @@ -203,19 +210,23 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: webpackImporter: false, implementation: require('node-sass'), sassOptions(loaderContext: webpack.loader.LoaderContext) { - const darkMode = loaderContext.resourceQuery === '?dark'; + const darkMode = loaderContext.resourceQuery.includes('dark'); return { outputStyle: 'nested', includePaths: [Path.resolve(worker.repoRoot, 'node_modules')], sourceMapRoot: `/${bundle.type}:${bundle.id}`, - importer: (url: string) => { - if (darkMode && url.includes('eui_colors_light')) { - return { file: url.replace('eui_colors_light', 'eui_colors_dark') }; - } + importer: !darkMode + ? undefined + : (url: string) => { + if (url.includes('eui_colors_light')) { + return { + file: url.replace('eui_colors_light', 'eui_colors_dark'), + }; + } - return { file: url }; - }, + return { file: url }; + }, }; }, }, @@ -224,6 +235,9 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: }, { loader: require.resolve('./theme_loader'), + options: { + themeTags: worker.themeTags, + }, }, ], }, diff --git a/src/legacy/ui/ui_render/bootstrap/template.js.hbs b/src/legacy/ui/ui_render/bootstrap/template.js.hbs index ca2e944489a734..3a93f292fb496b 100644 --- a/src/legacy/ui/ui_render/bootstrap/template.js.hbs +++ b/src/legacy/ui/ui_render/bootstrap/template.js.hbs @@ -2,6 +2,7 @@ var kbnCsp = JSON.parse(document.querySelector('kbn-csp').getAttribute('data')); window.__kbnStrictCsp__ = kbnCsp.strictCsp; window.__kbnDarkMode__ = {{darkMode}}; window.__kbnThemeVersion__ = "{{themeVersion}}"; +window.__kbnThemeTag__ = "{{themeTag}}"; window.__kbnPublicPath__ = {{publicPathMap}}; window.__kbnBundles__ = {{kbnBundlesLoaderSource}} diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index 0cfcb91aa94efe..e9472a6344b4c9 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -89,6 +89,7 @@ export function uiRenderMixin(kbnServer, server, config) { const isCore = !app; const uiSettings = request.getUiSettingsService(); + const darkMode = !authEnabled || request.auth.isAuthenticated ? await uiSettings.get('theme:darkMode') @@ -99,6 +100,8 @@ export function uiRenderMixin(kbnServer, server, config) { ? await uiSettings.get('theme:version') : 'v7'; + const themeTag = `${themeVersion === 'v7' ? 'v7' : 'v8'}${darkMode ? 'dark' : 'light'}`; + const buildHash = server.newPlatform.env.packageInfo.buildNum; const basePath = config.get('server.basePath'); @@ -180,6 +183,7 @@ export function uiRenderMixin(kbnServer, server, config) { templateData: { darkMode, themeVersion, + themeTag, jsDependencyPaths, styleSheetPaths, publicPathMap, From 6a09eacbe71fbf01194b36a91870407594b00886 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 30 Jun 2020 19:23:13 -0700 Subject: [PATCH 02/24] build all themes when building the dist --- packages/kbn-optimizer/src/optimizer/optimizer_config.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index 58317aefe2846e..231917bdbfd2da 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -148,7 +148,9 @@ export class OptimizerConfig { throw new TypeError('worker count must be a number'); } - const themes = parseThemeTags(options.themes || process.env.KBN_OPTIMIZER_THEME); + const themeTags = parseThemeTags( + options.themes || (dist ? '*' : process.env.KBN_OPTIMIZER_THEME) + ); return { watch, @@ -161,7 +163,7 @@ export class OptimizerConfig { pluginPaths, inspectWorkers, includeCoreBundle, - themeTags: themes, + themeTags, }; } From 5690ce636f50f35739f79d2e8ff0b8b61613b97a Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 30 Jun 2020 19:26:20 -0700 Subject: [PATCH 03/24] fix outdated types and remove @ts-ignore usage --- .../integration_tests/basic_optimization.test.ts | 2 +- .../src/optimizer/optimizer_config.ts | 9 ++++++++- packages/kbn-optimizer/src/worker/run_compilers.ts | 2 +- .../kbn-optimizer/src/worker/webpack.config.ts | 14 +++----------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index 7966a522d6809b..3f369db325904a 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -226,7 +226,7 @@ const expectFileMatchesSnapshotWithCompression = (filePath: string, snapshotLabe // Verify the brotli variant matches expect( - // @ts-ignore @types/node is missing the brotli functions + // @ts-expect-error @types/node is missing the brotli functions Zlib.brotliDecompressSync( Fs.readFileSync(Path.resolve(MOCK_REPO_DIR, `${filePath}.br`)) ).toString() diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index 231917bdbfd2da..859b634fc3a881 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -20,7 +20,14 @@ import Path from 'path'; import Os from 'os'; -import { Bundle, WorkerConfig, CacheableWorkerConfig, ThemeTags, parseThemeTags } from '../common'; +import { + Bundle, + WorkerConfig, + CacheableWorkerConfig, + ThemeTag, + ThemeTags, + parseThemeTags, +} from '../common'; import { findKibanaPlatformPlugins, KibanaPlatformPlugin } from './kibana_platform_plugins'; import { getPluginBundles } from './get_plugin_bundles'; diff --git a/packages/kbn-optimizer/src/worker/run_compilers.ts b/packages/kbn-optimizer/src/worker/run_compilers.ts index de5e9372e9e7ac..ca7673748bde91 100644 --- a/packages/kbn-optimizer/src/worker/run_compilers.ts +++ b/packages/kbn-optimizer/src/worker/run_compilers.ts @@ -77,7 +77,7 @@ const observeCompiler = ( */ const complete$ = Rx.fromEventPattern((cb) => done.tap(PLUGIN_NAME, cb)).pipe( maybeMap((stats) => { - // @ts-ignore not included in types, but it is real https://github.com/webpack/webpack/blob/ab4fa8ddb3f433d286653cd6af7e3aad51168649/lib/Watching.js#L58 + // @ts-expect-error not included in types, but it is real https://github.com/webpack/webpack/blob/ab4fa8ddb3f433d286653cd6af7e3aad51168649/lib/Watching.js#L58 if (stats.compilation.needAdditionalPass) { return undefined; } diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index b5dd482364407e..c9acb51f7ffb0b 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -21,23 +21,15 @@ import Path from 'path'; import { stringifyRequest } from 'loader-utils'; import webpack from 'webpack'; -// @ts-ignore +// @ts-expect-error import TerserPlugin from 'terser-webpack-plugin'; -// @ts-ignore +// @ts-expect-error import webpackMerge from 'webpack-merge'; -// @ts-ignore import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import CompressionPlugin from 'compression-webpack-plugin'; import * as UiSharedDeps from '@kbn/ui-shared-deps'; -import { - Bundle, - BundleRefs, - WorkerConfig, - parseDirPath, - DisallowedSyntaxPlugin, - validateThemeTagList, -} from '../common'; +import { Bundle, BundleRefs, WorkerConfig, parseDirPath, DisallowedSyntaxPlugin } from '../common'; import { BundleRefsPlugin } from './bundle_refs_plugin'; const IS_CODE_COVERAGE = !!process.env.CODE_COVERAGE; From 6fa8873b2ad6b8dbd6990909681856d72ee65141 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 1 Jul 2020 10:05:04 -0400 Subject: [PATCH 04/24] [SASS] 4 `_styling_constants_[theme].scss` files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed the normal `_styling_constants.scss` file where possible - Still some legacy imports I don’t know what to do with --- CONTRIBUTING.md | 8 ++++---- packages/kbn-ui-framework/src/kui_light.scss | 4 +--- .../ui/public/styles/_styling_constants.scss | 4 +--- .../styles/_styling_constants_k7_dark.scss | 17 +++++++++++++++++ .../styles/_styling_constants_k7_light.scss | 17 +++++++++++++++++ .../styles/_styling_constants_k8_dark.scss | 17 +++++++++++++++++ .../styles/_styling_constants_k8_light.scss | 17 +++++++++++++++++ src/plugins/tile_map/public/index.scss | 2 -- x-pack/plugins/canvas/public/style/index.scss | 2 -- .../plugins/index_management/public/index.scss | 3 --- x-pack/plugins/infra/public/index.scss | 3 --- x-pack/plugins/maps/public/index.scss | 3 --- .../plugins/ml/public/application/_index.scss | 3 --- .../public/application/index.scss | 3 --- x-pack/plugins/transform/public/app/index.scss | 3 --- .../public/application/_index.scss | 2 -- 16 files changed, 74 insertions(+), 34 deletions(-) create mode 100644 src/legacy/ui/public/styles/_styling_constants_k7_dark.scss create mode 100644 src/legacy/ui/public/styles/_styling_constants_k7_light.scss create mode 100644 src/legacy/ui/public/styles/_styling_constants_k8_dark.scss create mode 100644 src/legacy/ui/public/styles/_styling_constants_k8_light.scss diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7345f4b2897b2..5c7d9014732baa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,7 +436,7 @@ We are still to develop a proper process to accept any contributed translations. When writing a new component, create a sibling SASS file of the same name and import directly into the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). -Any JavaScript (or TypeScript) file that imports SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants.scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants.scss). However, any Legacy (file path includes `/legacy`) files will not. +Any JavaScript (or TypeScript) file that imports SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_k7_light.scss). However, any Legacy (file path includes `/legacy`) files will not. **Example:** @@ -679,15 +679,15 @@ Part of this process only applies to maintainers, since it requires access to Gi Kibana publishes [Release Notes](https://www.elastic.co/guide/en/kibana/current/release-notes.html) for major and minor releases. The Release Notes summarize what the PRs accomplish in language that is meaningful to users. To generate the Release Notes, the team runs a script against this repo to collect the merged PRs against the release. #### Create the Release Notes text -The text that appears in the Release Notes is pulled directly from your PR title, or a single paragraph of text that you specify in the PR description. +The text that appears in the Release Notes is pulled directly from your PR title, or a single paragraph of text that you specify in the PR description. To use a single paragraph of text, enter `Release note:` or a `## Release note` header in the PR description, followed by your text. For example, refer to this [PR](https://github.com/elastic/kibana/pull/65796) that uses the `## Release note` header. When you create the Release Notes text, use the following best practices: -* Use present tense. +* Use present tense. * Use sentence case. * When you create a feature PR, start with `Adds`. -* When you create an enhancement PR, start with `Improves`. +* When you create an enhancement PR, start with `Improves`. * When you create a bug fix PR, start with `Fixes`. * When you create a deprecation PR, start with `Deprecates`. diff --git a/packages/kbn-ui-framework/src/kui_light.scss b/packages/kbn-ui-framework/src/kui_light.scss index b912b6e217882c..ffeab9a9aeb5d6 100644 --- a/packages/kbn-ui-framework/src/kui_light.scss +++ b/packages/kbn-ui-framework/src/kui_light.scss @@ -1,8 +1,6 @@ // EUI global scope is used for KUI variables till fully deprecated @import '../../../node_modules/@elastic/eui/src/themes/eui/eui_colors_light'; -@import '../../../node_modules/@elastic/eui/src/global_styling/functions/index'; -@import '../../../node_modules/@elastic/eui/src/global_styling/variables/index'; -@import '../../../node_modules/@elastic/eui/src/global_styling/mixins/index'; +@import '../../../node_modules/@elastic/eui/src/global_styling/index'; // Configuration @import 'global_styling/variables/index'; diff --git a/src/legacy/ui/public/styles/_styling_constants.scss b/src/legacy/ui/public/styles/_styling_constants.scss index 74fc54b4102856..7dadee072a22d1 100644 --- a/src/legacy/ui/public/styles/_styling_constants.scss +++ b/src/legacy/ui/public/styles/_styling_constants.scss @@ -4,8 +4,6 @@ // Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug -@import '@elastic/eui/src/global_styling/functions/index'; -@import '@elastic/eui/src/global_styling/variables/index'; -@import '@elastic/eui/src/global_styling/mixins/index'; +@import '@elastic/eui/src/global_styling/index'; @import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss b/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss new file mode 100644 index 00000000000000..fc0e5e2fd8169b --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss @@ -0,0 +1,17 @@ +// EUI Dark global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui/eui_colors_dark'; +@import '@elastic/eui/src/global_styling/index'; + +@import './mixins'; + +// FOR TESTING ONLY, REMOVE BEFORE MERGE +body::before { + display: block; + content: "THIS IS THE DEFAULT DARK THEME"; + color: $euiColorPrimary; + font-weight: $euiFontWeightBold; + background-color: $euiColorEmptyShade; + padding: $euiSize; +} diff --git a/src/legacy/ui/public/styles/_styling_constants_k7_light.scss b/src/legacy/ui/public/styles/_styling_constants_k7_light.scss new file mode 100644 index 00000000000000..b4ff10990ab8d3 --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_k7_light.scss @@ -0,0 +1,17 @@ +// EUI Light global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui/eui_colors_light'; +@import '@elastic/eui/src/global_styling/index'; + +@import './mixins'; + +// FOR TESTING ONLY, REMOVE BEFORE MERGE +body::before { + display: block; + content: "THIS IS THE DEFAULT LIGHT THEME"; + color: $euiColorPrimary; + font-weight: $euiFontWeightBold; + background-color: $euiColorEmptyShade; + padding: $euiSize; +} diff --git a/src/legacy/ui/public/styles/_styling_constants_k8_dark.scss b/src/legacy/ui/public/styles/_styling_constants_k8_dark.scss new file mode 100644 index 00000000000000..d590a2c9d110a1 --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_k8_dark.scss @@ -0,0 +1,17 @@ +// EUI Amsterdam Light global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_dark'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; + +@import './mixins'; + +// FOR TESTING ONLY, REMOVE BEFORE MERGE +body::before { + display: block; + content: "THIS IS THE AMSTERDAM DARK THEME"; + color: $euiColorPrimary; + font-weight: $euiFontWeightBold; + background-color: $euiColorEmptyShade; + padding: $euiSize; +} diff --git a/src/legacy/ui/public/styles/_styling_constants_k8_light.scss b/src/legacy/ui/public/styles/_styling_constants_k8_light.scss new file mode 100644 index 00000000000000..e57184f112c6dd --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_k8_light.scss @@ -0,0 +1,17 @@ +// EUI Amsterdam Light global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_light'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; + +@import './mixins'; + +// FOR TESTING ONLY, REMOVE BEFORE MERGE +body::before { + display: block; + content: "THIS IS THE AMSTERDAM LIGHT THEME"; + color: $euiColorPrimary; + font-weight: $euiFontWeightBold; + background-color: $euiColorEmptyShade; + padding: $euiSize; +} diff --git a/src/plugins/tile_map/public/index.scss b/src/plugins/tile_map/public/index.scss index 4ce500b2da4d22..f4b86b0c31190b 100644 --- a/src/plugins/tile_map/public/index.scss +++ b/src/plugins/tile_map/public/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - // Prefix all styles with "tlm" to avoid conflicts. // Examples // tlmChart diff --git a/x-pack/plugins/canvas/public/style/index.scss b/x-pack/plugins/canvas/public/style/index.scss index 78a34a58f5f782..9cd2bdabd3f451 100644 --- a/x-pack/plugins/canvas/public/style/index.scss +++ b/x-pack/plugins/canvas/public/style/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - // Canvas core @import 'hackery'; @import 'main'; diff --git a/x-pack/plugins/index_management/public/index.scss b/x-pack/plugins/index_management/public/index.scss index 0fbf8ea5036c59..02686c4f7d6f34 100644 --- a/x-pack/plugins/index_management/public/index.scss +++ b/x-pack/plugins/index_management/public/index.scss @@ -1,6 +1,3 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - // Index management plugin styles // Prefix all styles with "ind" to avoid conflicts. diff --git a/x-pack/plugins/infra/public/index.scss b/x-pack/plugins/infra/public/index.scss index 05e045c1bd53be..a3d74e3afebe39 100644 --- a/x-pack/plugins/infra/public/index.scss +++ b/x-pack/plugins/infra/public/index.scss @@ -1,6 +1,3 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - /* Infra plugin styles */ .infra-container-element { diff --git a/x-pack/plugins/maps/public/index.scss b/x-pack/plugins/maps/public/index.scss index fe974fa610c03e..d2dd07b0f81f91 100644 --- a/x-pack/plugins/maps/public/index.scss +++ b/x-pack/plugins/maps/public/index.scss @@ -1,8 +1,5 @@ /* GIS plugin styles */ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - // Prefix all styles with "map" to avoid conflicts. // Examples // mapChart diff --git a/x-pack/plugins/ml/public/application/_index.scss b/x-pack/plugins/ml/public/application/_index.scss index 11dc593a235a14..65e914a1ac923a 100644 --- a/x-pack/plugins/ml/public/application/_index.scss +++ b/x-pack/plugins/ml/public/application/_index.scss @@ -1,6 +1,3 @@ -// Should import both the EUI constants and any Kibana ones that are considered global -@import 'src/legacy/ui/public/styles/styling_constants'; - // ML has it's own variables for coloring @import 'variables'; diff --git a/x-pack/plugins/snapshot_restore/public/application/index.scss b/x-pack/plugins/snapshot_restore/public/application/index.scss index b680f4d3ebf903..3e16e3b5301e79 100644 --- a/x-pack/plugins/snapshot_restore/public/application/index.scss +++ b/x-pack/plugins/snapshot_restore/public/application/index.scss @@ -1,6 +1,3 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - // Snapshot and Restore plugin styles // Prefix all styles with "snapshotRestore" to avoid conflicts. diff --git a/x-pack/plugins/transform/public/app/index.scss b/x-pack/plugins/transform/public/app/index.scss index beb5ee6be67e66..cc5cc87c754c9c 100644 --- a/x-pack/plugins/transform/public/app/index.scss +++ b/x-pack/plugins/transform/public/app/index.scss @@ -1,6 +1,3 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - // Transform plugin styles // Prefix all styles with "transform" to avoid conflicts. diff --git a/x-pack/plugins/upgrade_assistant/public/application/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/_index.scss index 6000af5498cd6e..841415620d6917 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/_index.scss +++ b/x-pack/plugins/upgrade_assistant/public/application/_index.scss @@ -1,3 +1 @@ -@import 'src/legacy/ui/public/styles/_styling_constants'; - @import 'components/index'; From 5c541cefc3e128c988142c46864301dfddbc5463 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 09:25:53 -0700 Subject: [PATCH 05/24] add tests --- .../src/common/theme_tags.test.ts | 91 +++++++++++++++++++ .../kbn-optimizer/src/common/theme_tags.ts | 4 +- .../src/optimizer/cache_keys.test.ts | 3 + .../src/optimizer/optimizer_config.test.ts | 39 +++++++- 4 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 packages/kbn-optimizer/src/common/theme_tags.test.ts diff --git a/packages/kbn-optimizer/src/common/theme_tags.test.ts b/packages/kbn-optimizer/src/common/theme_tags.test.ts new file mode 100644 index 00000000000000..cd3add0dfd2005 --- /dev/null +++ b/packages/kbn-optimizer/src/common/theme_tags.test.ts @@ -0,0 +1,91 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { parseThemeTags } from './theme_tags'; + +it('returns default tags when passed undefined', () => { + expect(parseThemeTags()).toMatchInlineSnapshot(` + Array [ + "v7light", + ] + `); +}); + +it('returns all tags when passed *', () => { + expect(parseThemeTags('*')).toMatchInlineSnapshot(` + Array [ + "v7dark", + "v7light", + "v8dark", + "v8light", + ] + `); +}); + +it('returns specific tag when passed a single value', () => { + expect(parseThemeTags('v8light')).toMatchInlineSnapshot(` + Array [ + "v8light", + ] + `); +}); + +it('returns specific tags when passed a comma separated list', () => { + expect(parseThemeTags('v8light, v7dark,v7light')).toMatchInlineSnapshot(` + Array [ + "v7dark", + "v7light", + "v8light", + ] + `); +}); + +it('returns specific tags when passed an array', () => { + expect(parseThemeTags(['v8light', 'v7light'])).toMatchInlineSnapshot(` + Array [ + "v7light", + "v8light", + ] + `); +}); + +it('throws when an invalid tag is in the array', () => { + expect(() => parseThemeTags(['v8light', 'v7light', 'bar'])).toThrowErrorMatchingInlineSnapshot( + `"Invalid theme tags [bar], options: [v7dark, v7light, v8dark, v8light]"` + ); +}); + +it('throws when an invalid tags in comma separated list', () => { + expect(() => parseThemeTags('v8light ,v7light,bar,box ')).toThrowErrorMatchingInlineSnapshot( + `"Invalid theme tags [bar, box], options: [v7dark, v7light, v8dark, v8light]"` + ); +}); + +it('returns tags in alphabetical order', () => { + const tags = parseThemeTags(['v7light', 'v8light']); + expect(tags).toEqual(tags.slice().sort((a, b) => a.localeCompare(b))); +}); + +it('returns an immutable array', () => { + expect(() => { + const tags = parseThemeTags('v8light'); + // @ts-expect-error + tags.push('foo'); + }).toThrowErrorMatchingInlineSnapshot(`"Cannot add property 1, object is not extensible"`); +}); diff --git a/packages/kbn-optimizer/src/common/theme_tags.ts b/packages/kbn-optimizer/src/common/theme_tags.ts index 47728e1309f11a..d3cc73ee5b81ae 100644 --- a/packages/kbn-optimizer/src/common/theme_tags.ts +++ b/packages/kbn-optimizer/src/common/theme_tags.ts @@ -19,7 +19,9 @@ import { ascending } from './array_helpers'; -const tags = (...themeTags: string[]) => Object.freeze(themeTags.sort(ascending()) as ThemeTag[]); +const tags = (...themeTags: string[]) => + Object.freeze(themeTags.sort(ascending((tag) => tag)) as ThemeTag[]); + const validTag = (tag: any): tag is ThemeTag => ALL_THEMES.includes(tag); const isArrayOfStrings = (input: unknown): input is string[] => Array.isArray(input) && input.every((v) => typeof v === 'string'); diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts index 9d7f1709506f9f..63b253b78f4d43 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts @@ -103,6 +103,9 @@ describe('getOptimizerCacheKey()', () => { "dist": false, "optimizerCacheKey": "♻", "repoRoot": , + "themeTags": Array [ + "v7light", + ], }, } `); diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index d4152133f289de..13664e1496b250 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -20,6 +20,7 @@ jest.mock('./assign_bundles_to_workers.ts'); jest.mock('./kibana_platform_plugins.ts'); jest.mock('./get_plugin_bundles.ts'); +jest.mock('../common/theme_tags.ts'); import Path from 'path'; import Os from 'os'; @@ -27,6 +28,7 @@ import Os from 'os'; import { REPO_ROOT, createAbsolutePathSerializer } from '@kbn/dev-utils'; import { OptimizerConfig } from './optimizer_config'; +import { parseThemeTags } from '../common'; jest.spyOn(Os, 'cpus').mockReturnValue(['foo'] as any); @@ -35,6 +37,7 @@ expect.addSnapshotSerializer(createAbsolutePathSerializer()); beforeEach(() => { delete process.env.KBN_OPTIMIZER_MAX_WORKERS; delete process.env.KBN_OPTIMIZER_NO_CACHE; + delete process.env.KBN_OPTIMIZER_THEME; jest.clearAllMocks(); }); @@ -81,6 +84,26 @@ describe('OptimizerConfig::parseOptions()', () => { }).toThrowErrorMatchingInlineSnapshot(`"worker count must be a number"`); }); + it('defaults to * theme when dist = true', () => { + OptimizerConfig.parseOptions({ + repoRoot: REPO_ROOT, + dist: true, + }); + + expect(parseThemeTags).toBeCalledWith('*'); + }); + + it('defaults to KBN_OPTIMIZER_THEME when dist = false', () => { + process.env.KBN_OPTIMIZER_THEME = 'foo'; + + OptimizerConfig.parseOptions({ + repoRoot: REPO_ROOT, + dist: false, + }); + + expect(parseThemeTags).toBeCalledWith('foo'); + }); + it('applies defaults', () => { expect( OptimizerConfig.parseOptions({ @@ -102,6 +125,7 @@ describe('OptimizerConfig::parseOptions()', () => { ], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -127,6 +151,7 @@ describe('OptimizerConfig::parseOptions()', () => { ], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -154,6 +179,7 @@ describe('OptimizerConfig::parseOptions()', () => { ], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -178,6 +204,7 @@ describe('OptimizerConfig::parseOptions()', () => { ], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -201,6 +228,7 @@ describe('OptimizerConfig::parseOptions()', () => { ], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -222,6 +250,7 @@ describe('OptimizerConfig::parseOptions()', () => { "pluginScanDirs": Array [], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -243,6 +272,7 @@ describe('OptimizerConfig::parseOptions()', () => { "pluginScanDirs": Array [], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -264,6 +294,7 @@ describe('OptimizerConfig::parseOptions()', () => { "pluginScanDirs": Array [], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -286,6 +317,7 @@ describe('OptimizerConfig::parseOptions()', () => { "pluginScanDirs": Array [], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -308,6 +340,7 @@ describe('OptimizerConfig::parseOptions()', () => { "pluginScanDirs": Array [], "profileWebpack": false, "repoRoot": , + "themeTags": undefined, "watch": false, } `); @@ -346,6 +379,7 @@ describe('OptimizerConfig::create()', () => { pluginScanDirs: Symbol('parsed plugin scan dirs'), repoRoot: Symbol('parsed repo root'), watch: Symbol('parsed watch'), + themeTags: Symbol('theme tags'), inspectWorkers: Symbol('parsed inspect workers'), profileWebpack: Symbol('parsed profile webpack'), })); @@ -369,6 +403,7 @@ describe('OptimizerConfig::create()', () => { "plugins": Symbol(new platform plugins), "profileWebpack": Symbol(parsed profile webpack), "repoRoot": Symbol(parsed repo root), + "themeTags": Symbol(theme tags), "watch": Symbol(parsed watch), } `); @@ -385,7 +420,7 @@ describe('OptimizerConfig::create()', () => { [Window], ], "invocationCallOrder": Array [ - 7, + 21, ], "results": Array [ Object { @@ -408,7 +443,7 @@ describe('OptimizerConfig::create()', () => { [Window], ], "invocationCallOrder": Array [ - 8, + 22, ], "results": Array [ Object { From 2f32a664b6e08386e35dd8a10532c6d0f879378d Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 09:38:25 -0700 Subject: [PATCH 06/24] integrate new styling_constants* files --- CONTRIBUTING.md | 2 +- .../src/worker/webpack.config.ts | 136 +++++++++--------- .../storybook_config/webpack.config.js | 2 +- .../styles/_styling_constants_k7_dark.scss | 17 --- .../styles/_styling_constants_k7_light.scss | 17 --- .../styles/_styling_constants_v7dark.scss | 7 + .../styles/_styling_constants_v7light.scss | 7 + ...rk.scss => _styling_constants_v8dark.scss} | 10 -- ...t.scss => _styling_constants_v8light.scss} | 10 -- .../canvas/.storybook/webpack.config.js | 4 +- .../shareable_runtime/webpack.config.js | 5 +- 11 files changed, 90 insertions(+), 127 deletions(-) delete mode 100644 src/legacy/ui/public/styles/_styling_constants_k7_dark.scss delete mode 100644 src/legacy/ui/public/styles/_styling_constants_k7_light.scss create mode 100644 src/legacy/ui/public/styles/_styling_constants_v7dark.scss create mode 100644 src/legacy/ui/public/styles/_styling_constants_v7light.scss rename src/legacy/ui/public/styles/{_styling_constants_k8_dark.scss => _styling_constants_v8dark.scss} (53%) rename src/legacy/ui/public/styles/{_styling_constants_k8_light.scss => _styling_constants_v8light.scss} (53%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c7d9014732baa..ecf179506c8687 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,7 +436,7 @@ We are still to develop a proper process to accept any contributed translations. When writing a new component, create a sibling SASS file of the same name and import directly into the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). -Any JavaScript (or TypeScript) file that imports SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_k7_light.scss). However, any Legacy (file path includes `/legacy`) files will not. +Any JavaScript (or TypeScript) file that imports SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_v7light.scss). However, any Legacy (file path includes `/legacy`) files will not. **Example:** diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index c9acb51f7ffb0b..813d4bc0f0357b 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -133,78 +133,78 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: test: /\.scss$/, exclude: /node_modules/, oneOf: [ - { - resourceQuery: /^\?v\d(light|dark)$/, - use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - options: { - sourceMap: !worker.dist, + ...worker.themeTags.map((theme) => { + const darkMode = theme.includes('dark'); + + return { + resourceQuery: `?${theme}`, + use: [ + { + loader: 'style-loader', }, - }, - { - loader: 'postcss-loader', - options: { - sourceMap: !worker.dist, - config: { - path: require.resolve('./postcss.config'), + { + loader: 'css-loader', + options: { + sourceMap: !worker.dist, }, }, - }, - { - loader: 'resolve-url-loader', - options: { - join: (_: string, __: any) => (uri: string, base?: string) => { - // apply only to legacy platform styles - if (!base || !parseDirPath(base).dirs.includes('legacy')) { - return null; - } + { + loader: 'postcss-loader', + options: { + sourceMap: !worker.dist, + config: { + path: require.resolve('./postcss.config'), + }, + }, + }, + { + loader: 'resolve-url-loader', + options: { + join: (_: string, __: any) => (uri: string, base?: string) => { + // apply only to legacy platform styles + if (!base || !parseDirPath(base).dirs.includes('legacy')) { + return null; + } - if (uri.startsWith('ui/assets')) { - return Path.resolve( - worker.repoRoot, - 'src/core/server/core_app/', - uri.replace('ui/', '') - ); - } + if (uri.startsWith('ui/assets')) { + return Path.resolve( + worker.repoRoot, + 'src/core/server/core_app/', + uri.replace('ui/', '') + ); + } - // manually force ui/* urls in legacy styles to resolve to ui/legacy/public - if (uri.startsWith('ui/')) { - return Path.resolve( - worker.repoRoot, - 'src/legacy/ui/public', - uri.replace('ui/', '') - ); - } + // manually force ui/* urls in legacy styles to resolve to ui/legacy/public + if (uri.startsWith('ui/')) { + return Path.resolve( + worker.repoRoot, + 'src/legacy/ui/public', + uri.replace('ui/', '') + ); + } - return null; + return null; + }, }, }, - }, - { - loader: 'sass-loader', - options: { - // must always be enabled as long as we're using the `resolve-url-loader` to - // rewrite `ui/*` urls. They're dropped by subsequent loaders though - sourceMap: true, - prependData(loaderContext: webpack.loader.LoaderContext) { - return `@import ${stringifyRequest( - loaderContext, - Path.resolve( - worker.repoRoot, - 'src/legacy/ui/public/styles/_styling_constants.scss' - ) - )};\n`; - }, - webpackImporter: false, - implementation: require('node-sass'), - sassOptions(loaderContext: webpack.loader.LoaderContext) { - const darkMode = loaderContext.resourceQuery.includes('dark'); - - return { + { + loader: 'sass-loader', + options: { + // must always be enabled as long as we're using the `resolve-url-loader` to + // rewrite `ui/*` urls. They're dropped by subsequent loaders though + sourceMap: true, + prependData(loaderContext: webpack.loader.LoaderContext) { + return `@import ${stringifyRequest( + loaderContext, + Path.resolve( + worker.repoRoot, + `src/legacy/ui/public/styles/_styling_constants_${theme}.scss` + ) + )};\n`; + }, + webpackImporter: false, + implementation: require('node-sass'), + sassOptions: { outputStyle: 'nested', includePaths: [Path.resolve(worker.repoRoot, 'node_modules')], sourceMapRoot: `/${bundle.type}:${bundle.id}`, @@ -219,12 +219,12 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: return { file: url }; }, - }; + }, }, }, - }, - ], - }, + ], + }; + }), { loader: require.resolve('./theme_loader'), options: { diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js index caeffaabea62be..a9f3f6093a78e6 100644 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ b/packages/kbn-storybook/storybook_config/webpack.config.js @@ -122,7 +122,7 @@ module.exports = async ({ config }) => { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - resolve(REPO_ROOT, 'src/legacy/ui/public/styles/_styling_constants.scss') + resolve(REPO_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss') )};\n`; }, sassOptions: { diff --git a/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss b/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss deleted file mode 100644 index fc0e5e2fd8169b..00000000000000 --- a/src/legacy/ui/public/styles/_styling_constants_k7_dark.scss +++ /dev/null @@ -1,17 +0,0 @@ -// EUI Dark global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug - -@import '@elastic/eui/src/themes/eui/eui_colors_dark'; -@import '@elastic/eui/src/global_styling/index'; - -@import './mixins'; - -// FOR TESTING ONLY, REMOVE BEFORE MERGE -body::before { - display: block; - content: "THIS IS THE DEFAULT DARK THEME"; - color: $euiColorPrimary; - font-weight: $euiFontWeightBold; - background-color: $euiColorEmptyShade; - padding: $euiSize; -} diff --git a/src/legacy/ui/public/styles/_styling_constants_k7_light.scss b/src/legacy/ui/public/styles/_styling_constants_k7_light.scss deleted file mode 100644 index b4ff10990ab8d3..00000000000000 --- a/src/legacy/ui/public/styles/_styling_constants_k7_light.scss +++ /dev/null @@ -1,17 +0,0 @@ -// EUI Light global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug - -@import '@elastic/eui/src/themes/eui/eui_colors_light'; -@import '@elastic/eui/src/global_styling/index'; - -@import './mixins'; - -// FOR TESTING ONLY, REMOVE BEFORE MERGE -body::before { - display: block; - content: "THIS IS THE DEFAULT LIGHT THEME"; - color: $euiColorPrimary; - font-weight: $euiFontWeightBold; - background-color: $euiColorEmptyShade; - padding: $euiSize; -} diff --git a/src/legacy/ui/public/styles/_styling_constants_v7dark.scss b/src/legacy/ui/public/styles/_styling_constants_v7dark.scss new file mode 100644 index 00000000000000..f36265b088b81c --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_v7dark.scss @@ -0,0 +1,7 @@ +// EUI Dark global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui/eui_colors_dark'; +@import '@elastic/eui/src/global_styling/index'; + +@import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_v7light.scss b/src/legacy/ui/public/styles/_styling_constants_v7light.scss new file mode 100644 index 00000000000000..0e714d1df36fb9 --- /dev/null +++ b/src/legacy/ui/public/styles/_styling_constants_v7light.scss @@ -0,0 +1,7 @@ +// EUI Light global scope +// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug + +@import '@elastic/eui/src/themes/eui/eui_colors_light'; +@import '@elastic/eui/src/global_styling/index'; + +@import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_k8_dark.scss b/src/legacy/ui/public/styles/_styling_constants_v8dark.scss similarity index 53% rename from src/legacy/ui/public/styles/_styling_constants_k8_dark.scss rename to src/legacy/ui/public/styles/_styling_constants_v8dark.scss index d590a2c9d110a1..7aa6ee2c9ef8b9 100644 --- a/src/legacy/ui/public/styles/_styling_constants_k8_dark.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v8dark.scss @@ -5,13 +5,3 @@ @import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; @import './mixins'; - -// FOR TESTING ONLY, REMOVE BEFORE MERGE -body::before { - display: block; - content: "THIS IS THE AMSTERDAM DARK THEME"; - color: $euiColorPrimary; - font-weight: $euiFontWeightBold; - background-color: $euiColorEmptyShade; - padding: $euiSize; -} diff --git a/src/legacy/ui/public/styles/_styling_constants_k8_light.scss b/src/legacy/ui/public/styles/_styling_constants_v8light.scss similarity index 53% rename from src/legacy/ui/public/styles/_styling_constants_k8_light.scss rename to src/legacy/ui/public/styles/_styling_constants_v8light.scss index e57184f112c6dd..8907c52af481c4 100644 --- a/src/legacy/ui/public/styles/_styling_constants_k8_light.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v8light.scss @@ -5,13 +5,3 @@ @import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; @import './mixins'; - -// FOR TESTING ONLY, REMOVE BEFORE MERGE -body::before { - display: block; - content: "THIS IS THE AMSTERDAM LIGHT THEME"; - color: $euiColorPrimary; - font-weight: $euiFontWeightBold; - background-color: $euiColorEmptyShade; - padding: $euiSize; -} diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js index 45a5303d8b0db1..137bcc6a452041 100644 --- a/x-pack/plugins/canvas/.storybook/webpack.config.js +++ b/x-pack/plugins/canvas/.storybook/webpack.config.js @@ -80,7 +80,7 @@ module.exports = async ({ config }) => { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants.scss') + path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss') )};\n`; }, sassOptions: { @@ -199,7 +199,7 @@ module.exports = async ({ config }) => { config.resolve.alias['ui/url/absolute_to_parsed_url'] = path.resolve(__dirname, '../tasks/mocks/uiAbsoluteToParsedUrl'); config.resolve.alias['ui/chrome'] = path.resolve(__dirname, '../tasks/mocks/uiChrome'); config.resolve.alias.ui = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public'); - config.resolve.alias['src/legacy/ui/public/styles/styling_constants'] = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants.scss'); + config.resolve.alias['src/legacy/ui/public/styles/styling_constants'] = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss'); config.resolve.alias.ng_mock$ = path.resolve(KIBANA_ROOT, 'src/test_utils/public/ng_mock'); return config; diff --git a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js index 66b0a7bc558cb6..4ea0c99d7cd465 100644 --- a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js +++ b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js @@ -188,7 +188,10 @@ module.exports = { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants.scss') + path.resolve( + KIBANA_ROOT, + 'src/legacy/ui/public/styles/_styling_constants_v7light.scss' + ) )};\n`; }, webpackImporter: false, From 0e6e0231a73caf9eb2fcbaf9ddf05c331c4431b8 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 10:00:33 -0700 Subject: [PATCH 07/24] remove sass importer, now that we have specific constants files for each theme --- .../src/worker/webpack.config.ts | 149 ++++++++---------- 1 file changed, 67 insertions(+), 82 deletions(-) diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 813d4bc0f0357b..de8675bf86fe37 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -133,98 +133,83 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: test: /\.scss$/, exclude: /node_modules/, oneOf: [ - ...worker.themeTags.map((theme) => { - const darkMode = theme.includes('dark'); - - return { - resourceQuery: `?${theme}`, - use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - options: { - sourceMap: !worker.dist, - }, + ...worker.themeTags.map((theme) => ({ + resourceQuery: `?${theme}`, + use: [ + { + loader: 'style-loader', + }, + { + loader: 'css-loader', + options: { + sourceMap: !worker.dist, }, - { - loader: 'postcss-loader', - options: { - sourceMap: !worker.dist, - config: { - path: require.resolve('./postcss.config'), - }, + }, + { + loader: 'postcss-loader', + options: { + sourceMap: !worker.dist, + config: { + path: require.resolve('./postcss.config'), }, }, - { - loader: 'resolve-url-loader', - options: { - join: (_: string, __: any) => (uri: string, base?: string) => { - // apply only to legacy platform styles - if (!base || !parseDirPath(base).dirs.includes('legacy')) { - return null; - } + }, + { + loader: 'resolve-url-loader', + options: { + join: (_: string, __: any) => (uri: string, base?: string) => { + // apply only to legacy platform styles + if (!base || !parseDirPath(base).dirs.includes('legacy')) { + return null; + } - if (uri.startsWith('ui/assets')) { - return Path.resolve( - worker.repoRoot, - 'src/core/server/core_app/', - uri.replace('ui/', '') - ); - } + if (uri.startsWith('ui/assets')) { + return Path.resolve( + worker.repoRoot, + 'src/core/server/core_app/', + uri.replace('ui/', '') + ); + } - // manually force ui/* urls in legacy styles to resolve to ui/legacy/public - if (uri.startsWith('ui/')) { - return Path.resolve( - worker.repoRoot, - 'src/legacy/ui/public', - uri.replace('ui/', '') - ); - } + // manually force ui/* urls in legacy styles to resolve to ui/legacy/public + if (uri.startsWith('ui/')) { + return Path.resolve( + worker.repoRoot, + 'src/legacy/ui/public', + uri.replace('ui/', '') + ); + } - return null; - }, + return null; }, }, - { - loader: 'sass-loader', - options: { - // must always be enabled as long as we're using the `resolve-url-loader` to - // rewrite `ui/*` urls. They're dropped by subsequent loaders though - sourceMap: true, - prependData(loaderContext: webpack.loader.LoaderContext) { - return `@import ${stringifyRequest( - loaderContext, - Path.resolve( - worker.repoRoot, - `src/legacy/ui/public/styles/_styling_constants_${theme}.scss` - ) - )};\n`; - }, - webpackImporter: false, - implementation: require('node-sass'), - sassOptions: { - outputStyle: 'nested', - includePaths: [Path.resolve(worker.repoRoot, 'node_modules')], - sourceMapRoot: `/${bundle.type}:${bundle.id}`, - importer: !darkMode - ? undefined - : (url: string) => { - if (url.includes('eui_colors_light')) { - return { - file: url.replace('eui_colors_light', 'eui_colors_dark'), - }; - } - - return { file: url }; - }, - }, + }, + { + loader: 'sass-loader', + options: { + // must always be enabled as long as we're using the `resolve-url-loader` to + // rewrite `ui/*` urls. They're dropped by subsequent loaders though + sourceMap: true, + prependData(loaderContext: webpack.loader.LoaderContext) { + return `@import ${stringifyRequest( + loaderContext, + Path.resolve( + worker.repoRoot, + `src/legacy/ui/public/styles/_styling_constants_${theme}.scss` + ) + )};\n`; + }, + webpackImporter: false, + implementation: require('node-sass'), + sassOptions: { + outputStyle: 'nested', + includePaths: [Path.resolve(worker.repoRoot, 'node_modules')], + sourceMapRoot: `/${bundle.type}:${bundle.id}`, }, }, - ], - }; - }), + }, + ], + })), { loader: require.resolve('./theme_loader'), options: { From a8bfe9783752db02df7ce1f018c4553342952a10 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 12:06:48 -0700 Subject: [PATCH 08/24] unify automatic insertion of globals with legacy styles (which only use v7) --- CONTRIBUTING.md | 2 +- src/core/public/index.scss | 4 ---- .../core_plugins/kibana/public/index.scss | 2 -- .../tests_bundle/public/index.scss | 2 -- .../core_plugins/timelion/public/index.scss | 3 --- .../server/sass/__fixtures__/index.scss | 2 -- src/legacy/server/sass/build.js | 24 ++++++++++++------- .../ui/public/styles/_styling_constants.scss | 9 ------- .../styles/_styling_constants_v7dark.scss | 11 ++++++--- .../styles/_styling_constants_v7light.scss | 11 ++++++--- .../styles/_styling_constants_v8dark.scss | 10 +++++--- .../styles/_styling_constants_v8light.scss | 10 +++++--- .../canvas/.storybook/webpack.config.js | 1 - 13 files changed, 47 insertions(+), 44 deletions(-) delete mode 100644 src/legacy/ui/public/styles/_styling_constants.scss diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ecf179506c8687..8e93fa831b4e7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,7 +436,7 @@ We are still to develop a proper process to accept any contributed translations. When writing a new component, create a sibling SASS file of the same name and import directly into the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). -Any JavaScript (or TypeScript) file that imports SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_v7light.scss). However, any Legacy (file path includes `/legacy`) files will not. +All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_v7light.scss). **Example:** diff --git a/src/core/public/index.scss b/src/core/public/index.scss index 4be46899cff67b..87825350b4e98f 100644 --- a/src/core/public/index.scss +++ b/src/core/public/index.scss @@ -1,7 +1,3 @@ -// This file is built by both the legacy and KP build systems so we need to -// import this explicitly -@import '../../legacy/ui/public/styles/_styling_constants'; - @import './core'; @import './chrome/index'; @import './overlays/index'; diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss index e9810a747c8c78..7de0c8fc15f943 100644 --- a/src/legacy/core_plugins/kibana/public/index.scss +++ b/src/legacy/core_plugins/kibana/public/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - // Elastic charts @import '@elastic/charts/dist/theme'; @import '@elastic/eui/src/themes/charts/theme'; diff --git a/src/legacy/core_plugins/tests_bundle/public/index.scss b/src/legacy/core_plugins/tests_bundle/public/index.scss index 8020cef8d84927..d8dbf8d6dc8856 100644 --- a/src/legacy/core_plugins/tests_bundle/public/index.scss +++ b/src/legacy/core_plugins/tests_bundle/public/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - // This file pulls some styles of NP plugins into the legacy test stylesheet // so they are available for karma browser tests. @import '../../../../plugins/vis_type_vislib/public/index'; diff --git a/src/legacy/core_plugins/timelion/public/index.scss b/src/legacy/core_plugins/timelion/public/index.scss index ebf000d160b546..cf2a7859a505d8 100644 --- a/src/legacy/core_plugins/timelion/public/index.scss +++ b/src/legacy/core_plugins/timelion/public/index.scss @@ -1,6 +1,3 @@ -// Should import both the EUI constants and any Kibana ones that are considered global -@import 'src/legacy/ui/public/styles/styling_constants'; - /* Timelion plugin styles */ // Prefix all styles with "tim" to avoid conflicts. diff --git a/src/legacy/server/sass/__fixtures__/index.scss b/src/legacy/server/sass/__fixtures__/index.scss index 019941534cadd3..ed2657ed3f6ee5 100644 --- a/src/legacy/server/sass/__fixtures__/index.scss +++ b/src/legacy/server/sass/__fixtures__/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - foo { bar { display: flex; diff --git a/src/legacy/server/sass/build.js b/src/legacy/server/sass/build.js index 2c0a2d84be2c00..692bb6091f31af 100644 --- a/src/legacy/server/sass/build.js +++ b/src/legacy/server/sass/build.js @@ -29,19 +29,21 @@ import isPathInside from 'is-path-inside'; import { PUBLIC_PATH_PLACEHOLDER } from '../../../optimize/public_path_placeholder'; const renderSass = promisify(sass.render); +const readFile = promisify(fs.readFile); const writeFile = promisify(fs.writeFile); const access = promisify(fs.access); const copyFile = promisify(fs.copyFile); const mkdirAsync = promisify(fs.mkdir); const UI_ASSETS_DIR = resolve(__dirname, '../../../core/server/core_app/assets'); -const DARK_THEME_IMPORTER = (url) => { - if (url.includes('eui_colors_light')) { - return { file: url.replace('eui_colors_light', 'eui_colors_dark') }; - } - - return { file: url }; -}; +const LIGHT_GLOBALS_PATH = resolve( + __dirname, + '../../../legacy/ui/public/styles/_styling_constants_v7light' +); +const DARK_GLOBALS_PATH = resolve( + __dirname, + '../../../legacy/ui/public/styles/_styling_constants_v7dark' +); const makeAsset = (request, { path, root, boundry, copyRoot, urlRoot }) => { const relativePath = relative(root, path); @@ -84,10 +86,16 @@ export class Build { */ async build() { + const scss = await readFile(this.sourcePath); + const relativeGlobalsPath = + this.theme === 'dark' + ? relative(this.sourceDir, DARK_GLOBALS_PATH) + : relative(this.sourceDir, LIGHT_GLOBALS_PATH); + const rendered = await renderSass({ file: this.sourcePath, + data: `@import '${relativeGlobalsPath}';\n${scss}`, outFile: this.targetPath, - importer: this.theme === 'dark' ? DARK_THEME_IMPORTER : undefined, sourceMap: true, outputStyle: 'nested', sourceMapEmbed: true, diff --git a/src/legacy/ui/public/styles/_styling_constants.scss b/src/legacy/ui/public/styles/_styling_constants.scss deleted file mode 100644 index 7dadee072a22d1..00000000000000 --- a/src/legacy/ui/public/styles/_styling_constants.scss +++ /dev/null @@ -1,9 +0,0 @@ -// EUI global scope - -@import '@elastic/eui/src/themes/eui/eui_colors_light'; - -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug - -@import '@elastic/eui/src/global_styling/index'; - -@import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_v7dark.scss b/src/legacy/ui/public/styles/_styling_constants_v7dark.scss index f36265b088b81c..d5a8535f327188 100644 --- a/src/legacy/ui/public/styles/_styling_constants_v7dark.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v7dark.scss @@ -1,7 +1,12 @@ -// EUI Dark global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug +// v7dark global scope +// +// prepended to all .scss imports (from JS, when v7dark theme selected) and +// legacy uiExports.styleSheetPaths when any dark theme is selected @import '@elastic/eui/src/themes/eui/eui_colors_dark'; -@import '@elastic/eui/src/global_styling/index'; + +@import '@elastic/eui/src/global_styling/functions/index'; +@import '@elastic/eui/src/global_styling/variables/index'; +@import '@elastic/eui/src/global_styling/mixins/index'; @import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_v7light.scss b/src/legacy/ui/public/styles/_styling_constants_v7light.scss index 0e714d1df36fb9..522b346b64900b 100644 --- a/src/legacy/ui/public/styles/_styling_constants_v7light.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v7light.scss @@ -1,7 +1,12 @@ -// EUI Light global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug +// v7light global scope +// +// prepended to all .scss imports (from JS, when v7light theme selected) and +// legacy uiExports.styleSheetPaths when any dark theme is selected @import '@elastic/eui/src/themes/eui/eui_colors_light'; -@import '@elastic/eui/src/global_styling/index'; + +@import '@elastic/eui/src/global_styling/functions/index'; +@import '@elastic/eui/src/global_styling/variables/index'; +@import '@elastic/eui/src/global_styling/mixins/index'; @import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_v8dark.scss b/src/legacy/ui/public/styles/_styling_constants_v8dark.scss index 7aa6ee2c9ef8b9..067d2490caa811 100644 --- a/src/legacy/ui/public/styles/_styling_constants_v8dark.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v8dark.scss @@ -1,7 +1,11 @@ -// EUI Amsterdam Light global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug +// v8dark global scope +// +// prepended to all .scss imports (from JS, when v8dark theme selected) @import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_dark'; -@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; + +@import '@elastic/eui/src/eui-amsterdam/global_styling/functions/index'; +@import '@elastic/eui/src/eui-amsterdam/global_styling/variables/index'; +@import '@elastic/eui/src/eui-amsterdam/global_styling/mixins/index'; @import './mixins'; diff --git a/src/legacy/ui/public/styles/_styling_constants_v8light.scss b/src/legacy/ui/public/styles/_styling_constants_v8light.scss index 8907c52af481c4..ef79ccfe85b219 100644 --- a/src/legacy/ui/public/styles/_styling_constants_v8light.scss +++ b/src/legacy/ui/public/styles/_styling_constants_v8light.scss @@ -1,7 +1,11 @@ -// EUI Amsterdam Light global scope -// Note that fonts are loaded directly by src/legacy/ui/ui_render/views/chrome.pug +// v8light global scope +// +// prepended to all .scss imports (from JS, when v8light theme selected) @import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_light'; -@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/index'; + +@import '@elastic/eui/src/eui-amsterdam/global_styling/functions/index'; +@import '@elastic/eui/src/eui-amsterdam/global_styling/variables/index'; +@import '@elastic/eui/src/eui-amsterdam/global_styling/mixins/index'; @import './mixins'; diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js index 137bcc6a452041..55e8fa955c3f2b 100644 --- a/x-pack/plugins/canvas/.storybook/webpack.config.js +++ b/x-pack/plugins/canvas/.storybook/webpack.config.js @@ -199,7 +199,6 @@ module.exports = async ({ config }) => { config.resolve.alias['ui/url/absolute_to_parsed_url'] = path.resolve(__dirname, '../tasks/mocks/uiAbsoluteToParsedUrl'); config.resolve.alias['ui/chrome'] = path.resolve(__dirname, '../tasks/mocks/uiChrome'); config.resolve.alias.ui = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public'); - config.resolve.alias['src/legacy/ui/public/styles/styling_constants'] = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss'); config.resolve.alias.ng_mock$ = path.resolve(KIBANA_ROOT, 'src/test_utils/public/ng_mock'); return config; From 645b4b04b77627e09cf28a2fa4b3ff53667c822c Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 12:14:59 -0700 Subject: [PATCH 09/24] revert usage of global_styling/index as it creates duplicate selectors --- packages/kbn-ui-framework/src/kui_light.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/kbn-ui-framework/src/kui_light.scss b/packages/kbn-ui-framework/src/kui_light.scss index ffeab9a9aeb5d6..b912b6e217882c 100644 --- a/packages/kbn-ui-framework/src/kui_light.scss +++ b/packages/kbn-ui-framework/src/kui_light.scss @@ -1,6 +1,8 @@ // EUI global scope is used for KUI variables till fully deprecated @import '../../../node_modules/@elastic/eui/src/themes/eui/eui_colors_light'; -@import '../../../node_modules/@elastic/eui/src/global_styling/index'; +@import '../../../node_modules/@elastic/eui/src/global_styling/functions/index'; +@import '../../../node_modules/@elastic/eui/src/global_styling/variables/index'; +@import '../../../node_modules/@elastic/eui/src/global_styling/mixins/index'; // Configuration @import 'global_styling/variables/index'; From 7d2cc0b7e2d73ecad6b6d974d47414e5f5ad6cd6 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 12:23:09 -0700 Subject: [PATCH 10/24] rename globals to `_globals_[theme].scss` --- CONTRIBUTING.md | 2 +- packages/kbn-optimizer/src/worker/webpack.config.ts | 2 +- .../kbn-storybook/storybook_config/webpack.config.js | 2 +- src/legacy/server/sass/build.js | 10 ++-------- ...ling_constants_v7dark.scss => _globals_v7dark.scss} | 0 ...ng_constants_v7light.scss => _globals_v7light.scss} | 0 ...ling_constants_v8dark.scss => _globals_v8dark.scss} | 0 ...ng_constants_v8light.scss => _globals_v8light.scss} | 0 x-pack/plugins/canvas/.storybook/webpack.config.js | 2 +- .../plugins/canvas/shareable_runtime/webpack.config.js | 5 +---- 10 files changed, 7 insertions(+), 16 deletions(-) rename src/legacy/ui/public/styles/{_styling_constants_v7dark.scss => _globals_v7dark.scss} (100%) rename src/legacy/ui/public/styles/{_styling_constants_v7light.scss => _globals_v7light.scss} (100%) rename src/legacy/ui/public/styles/{_styling_constants_v8dark.scss => _globals_v8dark.scss} (100%) rename src/legacy/ui/public/styles/{_styling_constants_v8light.scss => _globals_v8light.scss} (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e93fa831b4e7d..11d686d6b630d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,7 +436,7 @@ We are still to develop a proper process to accept any contributed translations. When writing a new component, create a sibling SASS file of the same name and import directly into the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). -All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`styling_constants_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_styling_constants_v7light.scss). +All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_globals_v7light.scss). **Example:** diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index de8675bf86fe37..338e4effad2226 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -195,7 +195,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: loaderContext, Path.resolve( worker.repoRoot, - `src/legacy/ui/public/styles/_styling_constants_${theme}.scss` + `src/legacy/ui/public/styles/_globals_${theme}.scss` ) )};\n`; }, diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js index a9f3f6093a78e6..b2df4f40d4fbe9 100644 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ b/packages/kbn-storybook/storybook_config/webpack.config.js @@ -122,7 +122,7 @@ module.exports = async ({ config }) => { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - resolve(REPO_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss') + resolve(REPO_ROOT, 'src/legacy/ui/public/styles/_globals_v7light.scss') )};\n`; }, sassOptions: { diff --git a/src/legacy/server/sass/build.js b/src/legacy/server/sass/build.js index 692bb6091f31af..536a6dc581db6c 100644 --- a/src/legacy/server/sass/build.js +++ b/src/legacy/server/sass/build.js @@ -36,14 +36,8 @@ const copyFile = promisify(fs.copyFile); const mkdirAsync = promisify(fs.mkdir); const UI_ASSETS_DIR = resolve(__dirname, '../../../core/server/core_app/assets'); -const LIGHT_GLOBALS_PATH = resolve( - __dirname, - '../../../legacy/ui/public/styles/_styling_constants_v7light' -); -const DARK_GLOBALS_PATH = resolve( - __dirname, - '../../../legacy/ui/public/styles/_styling_constants_v7dark' -); +const LIGHT_GLOBALS_PATH = resolve(__dirname, '../../../legacy/ui/public/styles/_globals_v7light'); +const DARK_GLOBALS_PATH = resolve(__dirname, '../../../legacy/ui/public/styles/_globals_v7dark'); const makeAsset = (request, { path, root, boundry, copyRoot, urlRoot }) => { const relativePath = relative(root, path); diff --git a/src/legacy/ui/public/styles/_styling_constants_v7dark.scss b/src/legacy/ui/public/styles/_globals_v7dark.scss similarity index 100% rename from src/legacy/ui/public/styles/_styling_constants_v7dark.scss rename to src/legacy/ui/public/styles/_globals_v7dark.scss diff --git a/src/legacy/ui/public/styles/_styling_constants_v7light.scss b/src/legacy/ui/public/styles/_globals_v7light.scss similarity index 100% rename from src/legacy/ui/public/styles/_styling_constants_v7light.scss rename to src/legacy/ui/public/styles/_globals_v7light.scss diff --git a/src/legacy/ui/public/styles/_styling_constants_v8dark.scss b/src/legacy/ui/public/styles/_globals_v8dark.scss similarity index 100% rename from src/legacy/ui/public/styles/_styling_constants_v8dark.scss rename to src/legacy/ui/public/styles/_globals_v8dark.scss diff --git a/src/legacy/ui/public/styles/_styling_constants_v8light.scss b/src/legacy/ui/public/styles/_globals_v8light.scss similarity index 100% rename from src/legacy/ui/public/styles/_styling_constants_v8light.scss rename to src/legacy/ui/public/styles/_globals_v8light.scss diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js index 55e8fa955c3f2b..3148a6742f76a4 100644 --- a/x-pack/plugins/canvas/.storybook/webpack.config.js +++ b/x-pack/plugins/canvas/.storybook/webpack.config.js @@ -80,7 +80,7 @@ module.exports = async ({ config }) => { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants_v7light.scss') + path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_globals_v7light.scss') )};\n`; }, sassOptions: { diff --git a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js index 4ea0c99d7cd465..1a5a21985ba72d 100644 --- a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js +++ b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js @@ -188,10 +188,7 @@ module.exports = { prependData(loaderContext) { return `@import ${stringifyRequest( loaderContext, - path.resolve( - KIBANA_ROOT, - 'src/legacy/ui/public/styles/_styling_constants_v7light.scss' - ) + path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_globals_v7light.scss') )};\n`; }, webpackImporter: false, From 8c9ff5fd6b7c6008dc22b976793362d3165d4de7 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 12:32:47 -0700 Subject: [PATCH 11/24] use relative path for globals link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11d686d6b630d6..a0aeed7a34949d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -436,7 +436,7 @@ We are still to develop a proper process to accept any contributed translations. When writing a new component, create a sibling SASS file of the same name and import directly into the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). -All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/styles/_globals_v7light.scss). +All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](src/legacy/ui/public/styles/_globals_v7light.scss). **Example:** From e49871896d0492eefadaeb153668fdf015ef87bf Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 12:40:32 -0700 Subject: [PATCH 12/24] expand docs and opitions for new `themes` param --- .../kbn-optimizer/src/optimizer/optimizer_config.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index 859b634fc3a881..54d521d45b3ada 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -84,10 +84,14 @@ interface Options { /** * style themes that sass files will be converted to, the correct style will be * loaded in the browser automatically by checking the global `__kbnThemeTag__`. - * Specifying additional styles increases build time. Defaults to all styles when - * building the dist + * Specifying additional styles increases build time. + * + * Defaults: + * - "*" when building the dist + * - comma separated list of themes in the `KBN_OPTIMIZER_THEME` env var + * - "k7light" */ - themes?: ThemeTag[]; + themes?: ThemeTag | '*' | ThemeTag[]; } interface ParsedOptions { From 3ddeed11e8260c815faa7d66bde3a651e37e97e0 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 13:17:27 -0700 Subject: [PATCH 13/24] log a warning when only a subset of themes are being built --- packages/kbn-optimizer/src/log_optimizer_state.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/kbn-optimizer/src/log_optimizer_state.ts b/packages/kbn-optimizer/src/log_optimizer_state.ts index cbec159bd27a02..ec973b15daa53c 100644 --- a/packages/kbn-optimizer/src/log_optimizer_state.ts +++ b/packages/kbn-optimizer/src/log_optimizer_state.ts @@ -24,7 +24,7 @@ import { tap } from 'rxjs/operators'; import { OptimizerConfig } from './optimizer'; import { OptimizerUpdate$ } from './run_optimizer'; -import { CompilerMsg, pipeClosure } from './common'; +import { CompilerMsg, pipeClosure, ALL_THEMES } from './common'; export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) { return pipeClosure((update$: OptimizerUpdate$) => { @@ -76,6 +76,11 @@ export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) { if (!loggedInit) { loggedInit = true; log.info(`initialized, ${state.offlineBundles.length} bundles cached`); + if (config.themeTags.length !== ALL_THEMES.length) { + log.warning( + `only building [${config.themeTags}] themes, customize with the KBN_OPTIMIZER_THEMES environment variable` + ); + } } return; } From 5899072dfaa6c9781cc13851d08899bf19c7e44a Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 13:18:05 -0700 Subject: [PATCH 14/24] use plural KBN_OPTIMIZER_THEMES env var --- .../kbn-optimizer/src/optimizer/optimizer_config.test.ts | 6 +++--- packages/kbn-optimizer/src/optimizer/optimizer_config.ts | 4 ++-- packages/kbn-optimizer/src/worker/theme_loader.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index 13664e1496b250..5b46d67479fd58 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -37,7 +37,7 @@ expect.addSnapshotSerializer(createAbsolutePathSerializer()); beforeEach(() => { delete process.env.KBN_OPTIMIZER_MAX_WORKERS; delete process.env.KBN_OPTIMIZER_NO_CACHE; - delete process.env.KBN_OPTIMIZER_THEME; + delete process.env.KBN_OPTIMIZER_THEMES; jest.clearAllMocks(); }); @@ -93,8 +93,8 @@ describe('OptimizerConfig::parseOptions()', () => { expect(parseThemeTags).toBeCalledWith('*'); }); - it('defaults to KBN_OPTIMIZER_THEME when dist = false', () => { - process.env.KBN_OPTIMIZER_THEME = 'foo'; + it('defaults to KBN_OPTIMIZER_THEMES when dist = false', () => { + process.env.KBN_OPTIMIZER_THEMES = 'foo'; OptimizerConfig.parseOptions({ repoRoot: REPO_ROOT, diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index 54d521d45b3ada..7757004139d0d4 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -88,7 +88,7 @@ interface Options { * * Defaults: * - "*" when building the dist - * - comma separated list of themes in the `KBN_OPTIMIZER_THEME` env var + * - comma separated list of themes in the `KBN_OPTIMIZER_THEMES` env var * - "k7light" */ themes?: ThemeTag | '*' | ThemeTag[]; @@ -160,7 +160,7 @@ export class OptimizerConfig { } const themeTags = parseThemeTags( - options.themes || (dist ? '*' : process.env.KBN_OPTIMIZER_THEME) + options.themes || (dist ? '*' : process.env.KBN_OPTIMIZER_THEMES) ); return { diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index 64641daeea8099..a2d3c54e6f4df2 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -35,7 +35,7 @@ export default function (this: webpack.loader.LoaderContext) { } const fallback = themeTags[0]; - const message = `Styles for [${tag}] were not built by the current @kbn/optimizer config. Falling back to [${fallback}] theme to make Kibana usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEME environment variable includes [${tag}] in a comma separated list of themes you want to use. You can also set it to "*" to build all themes.`; + const message = `Styles for [${tag}] were not built by the current @kbn/optimizer config. Falling back to [${fallback}] theme to make Kibana usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEMES environment variable includes [${tag}] in a comma separated list of themes you want to use. You can also set it to "*" to build all themes.`; return ` case '${tag}': console.error(new Error(${JSON.stringify(message)})); From 54e67cdbf3e14a40beff4e6efc4fccaddc20447d Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 13:18:39 -0700 Subject: [PATCH 15/24] fix v8 import paths and include unthemed imports --- src/legacy/ui/public/styles/_globals_v8dark.scss | 11 ++++++++--- src/legacy/ui/public/styles/_globals_v8light.scss | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/legacy/ui/public/styles/_globals_v8dark.scss b/src/legacy/ui/public/styles/_globals_v8dark.scss index 067d2490caa811..972365e9e9d0ec 100644 --- a/src/legacy/ui/public/styles/_globals_v8dark.scss +++ b/src/legacy/ui/public/styles/_globals_v8dark.scss @@ -4,8 +4,13 @@ @import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_dark'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/functions/index'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/variables/index'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/mixins/index'; +@import '@elastic/eui/src/global_styling/functions/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/functions/index'; + +@import '@elastic/eui/src/global_styling/variables/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/variables/index'; + +@import '@elastic/eui/src/global_styling/mixins/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/mixins/index'; @import './mixins'; diff --git a/src/legacy/ui/public/styles/_globals_v8light.scss b/src/legacy/ui/public/styles/_globals_v8light.scss index ef79ccfe85b219..dc99f4d45082ed 100644 --- a/src/legacy/ui/public/styles/_globals_v8light.scss +++ b/src/legacy/ui/public/styles/_globals_v8light.scss @@ -4,8 +4,13 @@ @import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_light'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/functions/index'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/variables/index'; -@import '@elastic/eui/src/eui-amsterdam/global_styling/mixins/index'; +@import '@elastic/eui/src/global_styling/functions/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/functions/index'; + +@import '@elastic/eui/src/global_styling/variables/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/variables/index'; + +@import '@elastic/eui/src/global_styling/mixins/index'; +@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/mixins/index'; @import './mixins'; From 552c35c4ba705093da1d257e44c7be3ab93afd2a Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 14:35:54 -0700 Subject: [PATCH 16/24] parse actual lines from worker stdio so that sass deprecation messages are readable --- .../kbn-optimizer/src/log_optimizer_state.ts | 7 +- .../src/optimizer/observe_stdio.test.ts | 49 ++++++++++++ .../src/optimizer/observe_stdio.ts | 76 +++++++++++++++++++ .../src/optimizer/observe_worker.ts | 46 +++++------ .../src/optimizer/optimizer_state.ts | 2 +- 5 files changed, 147 insertions(+), 33 deletions(-) create mode 100644 packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts create mode 100644 packages/kbn-optimizer/src/optimizer/observe_stdio.ts diff --git a/packages/kbn-optimizer/src/log_optimizer_state.ts b/packages/kbn-optimizer/src/log_optimizer_state.ts index ec973b15daa53c..23767be610da4f 100644 --- a/packages/kbn-optimizer/src/log_optimizer_state.ts +++ b/packages/kbn-optimizer/src/log_optimizer_state.ts @@ -37,12 +37,7 @@ export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) { const { event, state } = update; if (event?.type === 'worker stdio') { - const chunk = event.chunk.toString('utf8'); - log.warning( - `worker`, - event.stream, - chunk.slice(0, chunk.length - (chunk.endsWith('\n') ? 1 : 0)) - ); + log.warning(`worker`, event.stream, event.line); } if (event?.type === 'bundle not cached') { diff --git a/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts b/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts new file mode 100644 index 00000000000000..9bf8f9db1fe450 --- /dev/null +++ b/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Readable } from 'stream'; + +import { toArray } from 'rxjs/operators'; + +import { observeStdio$ } from './observe_stdio'; + +it('notifies on every line, uncluding partial content at the end without a newline', async () => { + const chunks = [`foo\nba`, `r\nb`, `az`]; + + await expect( + observeStdio$( + new Readable({ + read() { + this.push(chunks.shift()!); + if (!chunks.length) { + this.push(null); + } + }, + }) + ) + .pipe(toArray()) + .toPromise() + ).resolves.toMatchInlineSnapshot(` + Array [ + "foo", + "bar", + "baz", + ] + `); +}); diff --git a/packages/kbn-optimizer/src/optimizer/observe_stdio.ts b/packages/kbn-optimizer/src/optimizer/observe_stdio.ts new file mode 100644 index 00000000000000..e8daecef8e0dd9 --- /dev/null +++ b/packages/kbn-optimizer/src/optimizer/observe_stdio.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Readable } from 'stream'; +import * as Rx from 'rxjs'; + +// match newline characters followed either by a non-space character or another newline +const NEWLINE = /\r?\n/; + +/** + * Observe a readable stdio stream and emit the entire lines + * of text produced, completing once the stdio stream emits "end" + * and erroring if it emits "error". + */ +export function observeStdio$(stream: Readable) { + return new Rx.Observable((subscriber) => { + let buffer = ''; + + subscriber.add( + Rx.fromEvent(stream, 'data').subscribe({ + next(chunk) { + buffer += chunk.toString('utf8'); + + while (true) { + const match = NEWLINE.exec(buffer); + if (!match) { + break; + } + + const multilineChunk = buffer.slice(0, match.index); + buffer = buffer.slice(match.index + match[0].length); + subscriber.next(multilineChunk); + } + }, + }) + ); + + const flush = () => { + while (buffer.length && !subscriber.closed) { + const line = buffer; + buffer = ''; + subscriber.next(line); + } + }; + + subscriber.add( + Rx.fromEvent(stream, 'end').subscribe(() => { + flush(); + subscriber.complete(); + }) + ); + + subscriber.add( + Rx.fromEvent(stream, 'error').subscribe((error) => { + flush(); + subscriber.error(error); + }) + ); + }); +} diff --git a/packages/kbn-optimizer/src/optimizer/observe_worker.ts b/packages/kbn-optimizer/src/optimizer/observe_worker.ts index fef3efc13a516a..31b34bd5c59385 100644 --- a/packages/kbn-optimizer/src/optimizer/observe_worker.ts +++ b/packages/kbn-optimizer/src/optimizer/observe_worker.ts @@ -17,7 +17,6 @@ * under the License. */ -import { Readable } from 'stream'; import { inspect } from 'util'; import execa from 'execa'; @@ -26,12 +25,13 @@ import { map, takeUntil, first, ignoreElements } from 'rxjs/operators'; import { isWorkerMsg, WorkerConfig, WorkerMsg, Bundle, BundleRefs } from '../common'; +import { observeStdio$ } from './observe_stdio'; import { OptimizerConfig } from './optimizer_config'; export interface WorkerStdio { type: 'worker stdio'; stream: 'stdout' | 'stderr'; - chunk: Buffer; + line: string; } export interface WorkerStarted { @@ -99,28 +99,6 @@ function usingWorkerProc( ); } -function observeStdio$(stream: Readable, name: WorkerStdio['stream']) { - return Rx.fromEvent(stream, 'data').pipe( - takeUntil( - Rx.race( - Rx.fromEvent(stream, 'end'), - Rx.fromEvent(stream, 'error').pipe( - map((error) => { - throw error; - }) - ) - ) - ), - map( - (chunk): WorkerStdio => ({ - type: 'worker stdio', - chunk, - stream: name, - }) - ) - ); -} - /** * We used to pass configuration to the worker as JSON encoded arguments, but they * grew too large for argv, especially on Windows, so we had to move to an async init @@ -186,8 +164,24 @@ export function observeWorker( type: 'worker started', bundles, }), - observeStdio$(proc.stdout, 'stdout'), - observeStdio$(proc.stderr, 'stderr'), + observeStdio$(proc.stdout).pipe( + map( + (line): WorkerStdio => ({ + type: 'worker stdio', + line, + stream: 'stdout', + }) + ) + ), + observeStdio$(proc.stderr).pipe( + map( + (line): WorkerStdio => ({ + type: 'worker stdio', + line, + stream: 'stderr', + }) + ) + ), Rx.fromEvent<[unknown]>(proc, 'message') .pipe( // validate the messages from the process diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_state.ts b/packages/kbn-optimizer/src/optimizer/optimizer_state.ts index 1572f459e6ee5f..09f8ca10c61818 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_state.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_state.ts @@ -127,7 +127,7 @@ export function createOptimizerStateSummarizer( } if (event.type === 'worker stdio' || event.type === 'worker started') { - // same state, but updated to the event is shared externally + // same state, but updated so the event is shared externally return createOptimizerState(state); } From 2b0b0cd241d16a55fb7b27dd1ede01981bf6b5b4 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 14:46:35 -0700 Subject: [PATCH 17/24] update fixtures and snapshots for integration tests --- .../styles/{_styling_constants.scss => _globals_v7dark.scss} | 0 .../src/legacy/ui/public/styles/_globals_v7light.scss | 1 + .../src/legacy/ui/public/styles/_globals_v8dark.scss | 1 + .../src/legacy/ui/public/styles/_globals_v8light.scss | 1 + .../__snapshots__/basic_optimization.test.ts.snap | 5 ++++- .../src/integration_tests/basic_optimization.test.ts | 2 +- 6 files changed, 8 insertions(+), 2 deletions(-) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/{_styling_constants.scss => _globals_v7dark.scss} (100%) create mode 100644 packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7light.scss create mode 100644 packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8dark.scss create mode 100644 packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8light.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_styling_constants.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7dark.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_styling_constants.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7dark.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7light.scss new file mode 100644 index 00000000000000..63beb9927b9f57 --- /dev/null +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v7light.scss @@ -0,0 +1 @@ +$globalStyleConstant: 11; diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8dark.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8dark.scss new file mode 100644 index 00000000000000..4040cab1878fc6 --- /dev/null +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8dark.scss @@ -0,0 +1 @@ +$globalStyleConstant: 12; diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8light.scss new file mode 100644 index 00000000000000..3918413c068639 --- /dev/null +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/legacy/ui/public/styles/_globals_v8light.scss @@ -0,0 +1 @@ +$globalStyleConstant: 13; diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index b6b0973f0d5398..b88318d65c154c 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -58,11 +58,14 @@ OptimizerConfig { ], "profileWebpack": false, "repoRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, + "themeTags": Array [ + "v7light", + ], "watch": false, } `; -exports[`prepares assets for distribution: bar bundle 1`] = `"(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!==\\"undefined\\"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:\\"Module\\"})}Object.defineProperty(exports,\\"__esModule\\",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value===\\"object\\"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,\\"default\\",{enumerable:true,value:value});if(mode&2&&typeof value!=\\"string\\")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module[\\"default\\"]}:function getModuleExports(){return module};__webpack_require__.d(getter,\\"a\\",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p=\\"\\";return __webpack_require__(__webpack_require__.s=5)})([function(module,exports,__webpack_require__){\\"use strict\\";var isOldIE=function isOldIE(){var memo;return function memorize(){if(typeof memo===\\"undefined\\"){memo=Boolean(window&&document&&document.all&&!window.atob)}return memo}}();var getTarget=function getTarget(){var memo={};return function memorize(target){if(typeof memo[target]===\\"undefined\\"){var styleTarget=document.querySelector(target);if(window.HTMLIFrameElement&&styleTarget instanceof window.HTMLIFrameElement){try{styleTarget=styleTarget.contentDocument.head}catch(e){styleTarget=null}}memo[target]=styleTarget}return memo[target]}}();var stylesInDom=[];function getIndexByIdentifier(identifier){var result=-1;for(var i=0;i { bar.cache.refresh(); expect(bar.cache.getModuleCount()).toBe( // code + styles + style/css-loader runtimes + public path updater - 18 + 14 ); expect(bar.cache.getReferencedFiles()).toMatchInlineSnapshot(` From 47ef9597ee066c275368c5b904e6f631463dcba5 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 1 Jul 2020 15:40:20 -0700 Subject: [PATCH 18/24] fix use of WorkerStdio --- .../src/integration_tests/basic_optimization.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index 6d2f5b7f52519b..a2eec2c0819ab1 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -180,7 +180,7 @@ it('uses cache on second run and exist cleanly', async () => { tap((state) => { if (state.event?.type === 'worker stdio') { // eslint-disable-next-line no-console - console.log('worker', state.event.stream, state.event.chunk.toString('utf8')); + console.log('worker', state.event.stream, state.event.line); } }), toArray() From 80cf27151d5b39d6b7c5e06cb7d6468e2642dbec Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 09:57:31 -0700 Subject: [PATCH 19/24] remove unnecessary globals, rely on theme tag everywhere --- packages/kbn-ui-shared-deps/entry.js | 9 --------- packages/kbn-ui-shared-deps/theme.ts | 7 +++++-- src/legacy/ui/ui_render/bootstrap/template.js.hbs | 2 -- src/legacy/ui/ui_render/ui_render_mixin.js | 2 -- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 02b64157686c19..0f981f3d07610f 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -51,15 +51,6 @@ export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibServices = require('@elastic/eui/lib/services'); export const ElasticEuiLibServicesFormat = require('@elastic/eui/lib/services/format'); export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme'); -export let ElasticEuiLightTheme; -export let ElasticEuiDarkTheme; -if (window.__kbnThemeVersion__ === 'v7') { - ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_light.json'); - ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_dark.json'); -} else { - ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_amsterdam_light.json'); - ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_amsterdam_dark.json'); -} import * as Theme from './theme.ts'; export { Theme }; diff --git a/packages/kbn-ui-shared-deps/theme.ts b/packages/kbn-ui-shared-deps/theme.ts index ca4714779d39e1..f5b1ac3adb92ed 100644 --- a/packages/kbn-ui-shared-deps/theme.ts +++ b/packages/kbn-ui-shared-deps/theme.ts @@ -23,9 +23,12 @@ const globals: any = typeof window === 'undefined' ? {} : window; export type Theme = typeof LightTheme; +export const version: 7 | 8 = globals.__kbnThemeTag__.startsWith('v7') ? 7 : 8; +export const darkMode: boolean = globals.__kbnThemeTag__.endsWith('dark'); + export let euiLightVars: Theme; export let euiDarkVars: Theme; -if (globals.__kbnThemeVersion__ === 'v7') { +if (version === 7) { euiLightVars = require('@elastic/eui/dist/eui_theme_light.json'); euiDarkVars = require('@elastic/eui/dist/eui_theme_dark.json'); } else { @@ -37,7 +40,7 @@ if (globals.__kbnThemeVersion__ === 'v7') { * EUI Theme vars that automatically adjust to light/dark theme */ export let euiThemeVars: Theme; -if (globals.__kbnDarkTheme__) { +if (darkMode) { euiThemeVars = euiDarkVars; } else { euiThemeVars = euiLightVars; diff --git a/src/legacy/ui/ui_render/bootstrap/template.js.hbs b/src/legacy/ui/ui_render/bootstrap/template.js.hbs index 3a93f292fb496b..bbca051ce31a1d 100644 --- a/src/legacy/ui/ui_render/bootstrap/template.js.hbs +++ b/src/legacy/ui/ui_render/bootstrap/template.js.hbs @@ -1,7 +1,5 @@ var kbnCsp = JSON.parse(document.querySelector('kbn-csp').getAttribute('data')); window.__kbnStrictCsp__ = kbnCsp.strictCsp; -window.__kbnDarkMode__ = {{darkMode}}; -window.__kbnThemeVersion__ = "{{themeVersion}}"; window.__kbnThemeTag__ = "{{themeTag}}"; window.__kbnPublicPath__ = {{publicPathMap}}; window.__kbnBundles__ = {{kbnBundlesLoaderSource}} diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index e9472a6344b4c9..b4b18e086e809f 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -181,8 +181,6 @@ export function uiRenderMixin(kbnServer, server, config) { const bootstrap = new AppBootstrap({ templateData: { - darkMode, - themeVersion, themeTag, jsDependencyPaths, styleSheetPaths, From d0f1d1569e77cea07c08a245fd73ce9c00e8aaa7 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 10:30:29 -0700 Subject: [PATCH 20/24] add docs about using the `KBN_OPTIMIZER_THEMES` env var --- packages/kbn-optimizer/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/kbn-optimizer/README.md b/packages/kbn-optimizer/README.md index 9ff0f563442749..f0d809991eed16 100644 --- a/packages/kbn-optimizer/README.md +++ b/packages/kbn-optimizer/README.md @@ -42,6 +42,23 @@ When a directory is listed in the "extraPublicDirs" it will always be included i Any import in a bundle which resolves into another bundles "context" directory, ie `src/plugins/*`, must map explicitly to a "public dir" exported by that plugin. If the resolved import is not in the list of public dirs an error will be thrown and the optimizer will fail to build that bundle until the error is fixed. +## Themes + +SASS imports in bundles are automatically converted to CSS for one or more themes. In development we use the `v7light` theme by default and only build CSS for that theme to improve performance. When producing distributable bundles the default shifts to `*`, so that the distributable bundles will include all themes, preventing the bundles from needing to be rebuilt when users change the active theme in Kibana's advanced settings. + +To customize the themes that are built for development you can specify the `KBN_OPTIMIZER_THEMES` environment variable to one or more theme tags, or use `*` to build styles for all themes. Unfortunately building more than one theme significantly impacts build performance, so try to be strategic about which themes you build. + +Currently supported theme tags: `v7light`, `v7dark`, `v8light`, `v8dark` + +Examples: +```sh +# build all themes and start Kibana +KBN_OPTIMIZER_THEMES=* yarn start + +# build the v7 and v8 light themes and start Kibana +KBN_OPTIMIZER_THEMES=v7light,v8light yarn start +``` + ## API To run the optimizer from code, you can import the [`OptimizerConfig`][OptimizerConfig] class and [`runOptimizer`][Optimizer] function. Create an [`OptimizerConfig`][OptimizerConfig] instance by calling it's static `create()` method with some options, then pass it to the [`runOptimizer`][Optimizer] function. `runOptimizer()` returns an observable of update objects, which are summaries of the optimizer state plus an optional `event` property which describes the internal events occuring and may be of use. You can use the [`logOptimizerState()`][LogOptimizerState] helper to write the relevant bits of state to a tooling log or checkout it's implementation to see how the internal events like [`WorkerStdio`][ObserveWorker] and [`WorkerStarted`][ObserveWorker] are used. From 1a4924eb0b492d4f1ac9370860c0de4de8329c30 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 10:51:12 -0700 Subject: [PATCH 21/24] improve error message to make it more obvious that a specific part of the total styles failed --- packages/kbn-optimizer/src/worker/theme_loader.ts | 6 ++++-- packages/kbn-optimizer/src/worker/webpack.config.ts | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index a2d3c54e6f4df2..04c5666402e5b5 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -25,7 +25,9 @@ import { parseThemeTags, ALL_THEMES } from '../common'; export default function (this: webpack.loader.LoaderContext) { this.cacheable(true); - const themeTags = parseThemeTags(getOptions(this).themeTags); + const options = getOptions(this); + const bundleId: string = options.bundleId!; + const themeTags = parseThemeTags(options.themeTags); const cases = ALL_THEMES.map((tag) => { if (themeTags.includes(tag)) { @@ -35,7 +37,7 @@ export default function (this: webpack.loader.LoaderContext) { } const fallback = themeTags[0]; - const message = `Styles for [${tag}] were not built by the current @kbn/optimizer config. Falling back to [${fallback}] theme to make Kibana usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEMES environment variable includes [${tag}] in a comma separated list of themes you want to use. You can also set it to "*" to build all themes.`; + const message = `SASS files in [${bundleId}] were not built for theme [${tag}]. Styles were compiled using the [${fallback}] theme instead to keep Kibana somewhat usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEMES environment variable includes [${tag}] in a comma separated list of themes you want to compile. You can also set it to "*" to build all themes.`; return ` case '${tag}': console.error(new Error(${JSON.stringify(message)})); diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 338e4effad2226..aaea70d12c60d6 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -213,6 +213,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: { loader: require.resolve('./theme_loader'), options: { + bundleId: bundle.id, themeTags: worker.themeTags, }, }, From addbc68797bf38701c4b4e39ea1d045dd314d2d3 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 11:05:39 -0700 Subject: [PATCH 22/24] build `v7light` and `v7dark` by default --- packages/kbn-optimizer/README.md | 13 ++++++++----- packages/kbn-optimizer/src/common/theme_tags.ts | 2 +- packages/kbn-optimizer/src/worker/theme_loader.ts | 13 +++++++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/kbn-optimizer/README.md b/packages/kbn-optimizer/README.md index f0d809991eed16..5d5c5e3b6eb748 100644 --- a/packages/kbn-optimizer/README.md +++ b/packages/kbn-optimizer/README.md @@ -44,7 +44,7 @@ Any import in a bundle which resolves into another bundles "context" directory, ## Themes -SASS imports in bundles are automatically converted to CSS for one or more themes. In development we use the `v7light` theme by default and only build CSS for that theme to improve performance. When producing distributable bundles the default shifts to `*`, so that the distributable bundles will include all themes, preventing the bundles from needing to be rebuilt when users change the active theme in Kibana's advanced settings. +SASS imports in bundles are automatically converted to CSS for one or more themes. In development we build the `v7light` and `v7dark` themes by default to improve build performance. When producing distributable bundles the default shifts to `*` so that the distributable bundles will include all themes, preventing the bundles from needing to be rebuilt when users change the active theme in Kibana's advanced settings. To customize the themes that are built for development you can specify the `KBN_OPTIMIZER_THEMES` environment variable to one or more theme tags, or use `*` to build styles for all themes. Unfortunately building more than one theme significantly impacts build performance, so try to be strategic about which themes you build. @@ -52,11 +52,14 @@ Currently supported theme tags: `v7light`, `v7dark`, `v8light`, `v8dark` Examples: ```sh -# build all themes and start Kibana -KBN_OPTIMIZER_THEMES=* yarn start +# start Kibana with only a single theme +KBN_OPTIMIZER_THEMES=v7light yarn start + +# start Kibana with dark themes for version 7 and 8 +KBN_OPTIMIZER_THEMES=v7dark,v8dark yarn start -# build the v7 and v8 light themes and start Kibana -KBN_OPTIMIZER_THEMES=v7light,v8light yarn start +# start Kibana with all the themes +KBN_OPTIMIZER_THEMES=* yarn start ``` ## API diff --git a/packages/kbn-optimizer/src/common/theme_tags.ts b/packages/kbn-optimizer/src/common/theme_tags.ts index d3cc73ee5b81ae..27b5e12b807a87 100644 --- a/packages/kbn-optimizer/src/common/theme_tags.ts +++ b/packages/kbn-optimizer/src/common/theme_tags.ts @@ -28,7 +28,7 @@ const isArrayOfStrings = (input: unknown): input is string[] => export type ThemeTags = readonly ThemeTag[]; export type ThemeTag = 'v7light' | 'v7dark' | 'v8light' | 'v8dark'; -export const DEFAULT_THEMES = tags('v7light'); +export const DEFAULT_THEMES = tags('v7light', 'v7dark'); export const ALL_THEMES = tags('v7light', 'v7dark', 'v8light', 'v8dark'); export function parseThemeTags(input?: any): ThemeTags { diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index 04c5666402e5b5..f2f685bde65d96 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -19,7 +19,12 @@ import { stringifyRequest, getOptions } from 'loader-utils'; import webpack from 'webpack'; -import { parseThemeTags, ALL_THEMES } from '../common'; +import { parseThemeTags, ALL_THEMES, ThemeTag } from '../common'; + +const getVersion = (tag: ThemeTag) => (tag.includes('v7') ? 7 : 8); +const getIsDark = (tag: ThemeTag) => tag.includes('dark'); +const compare = (a: ThemeTag, b: ThemeTag) => + (getVersion(a) === getVersion(b) ? 1 : 0) + (getIsDark(a) === getIsDark(b) ? 1 : 0); // eslint-disable-next-line import/no-default-export export default function (this: webpack.loader.LoaderContext) { @@ -36,7 +41,11 @@ export default function (this: webpack.loader.LoaderContext) { return require(${stringifyRequest(this, `${this.resourcePath}?${tag}`)});`; } - const fallback = themeTags[0]; + const fallback = themeTags + .slice() + .sort((a, b) => compare(b, tag) - compare(a, tag)) + .shift()!; + const message = `SASS files in [${bundleId}] were not built for theme [${tag}]. Styles were compiled using the [${fallback}] theme instead to keep Kibana somewhat usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEMES environment variable includes [${tag}] in a comma separated list of themes you want to compile. You can also set it to "*" to build all themes.`; return ` case '${tag}': From ca991fcd14638ad34901d590e0e0f170de321554 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 11:38:55 -0700 Subject: [PATCH 23/24] handle undefined __kbnThemeTag__ globals caused by test runners --- packages/kbn-ui-shared-deps/theme.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/kbn-ui-shared-deps/theme.ts b/packages/kbn-ui-shared-deps/theme.ts index f5b1ac3adb92ed..4b2758516fc260 100644 --- a/packages/kbn-ui-shared-deps/theme.ts +++ b/packages/kbn-ui-shared-deps/theme.ts @@ -23,8 +23,11 @@ const globals: any = typeof window === 'undefined' ? {} : window; export type Theme = typeof LightTheme; -export const version: 7 | 8 = globals.__kbnThemeTag__.startsWith('v7') ? 7 : 8; -export const darkMode: boolean = globals.__kbnThemeTag__.endsWith('dark'); +// in the Kibana app we can rely on this global being defined, but in +// some cases (like jest, or karma tests) the global is undefined +export const tag: string = globals.__kbnThemeTag__ || 'v7light'; +export const version = tag.startsWith('v7') ? 7 : 8; +export const darkMode = tag.endsWith('dark'); export let euiLightVars: Theme; export let euiDarkVars: Theme; From 3f6830f917fee5639a15418541b6ec03ac444444 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 2 Jul 2020 13:07:52 -0700 Subject: [PATCH 24/24] update snapshots --- packages/kbn-optimizer/src/common/theme_tags.test.ts | 1 + .../__snapshots__/basic_optimization.test.ts.snap | 1 + .../src/integration_tests/basic_optimization.test.ts | 2 +- packages/kbn-optimizer/src/optimizer/cache_keys.test.ts | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/kbn-optimizer/src/common/theme_tags.test.ts b/packages/kbn-optimizer/src/common/theme_tags.test.ts index cd3add0dfd2005..019a9b7bdee3e6 100644 --- a/packages/kbn-optimizer/src/common/theme_tags.test.ts +++ b/packages/kbn-optimizer/src/common/theme_tags.test.ts @@ -22,6 +22,7 @@ import { parseThemeTags } from './theme_tags'; it('returns default tags when passed undefined', () => { expect(parseThemeTags()).toMatchInlineSnapshot(` Array [ + "v7dark", "v7light", ] `); diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index b88318d65c154c..211cfac3806ad7 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -59,6 +59,7 @@ OptimizerConfig { "profileWebpack": false, "repoRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, "themeTags": Array [ + "v7dark", "v7light", ], "watch": false, diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index a2eec2c0819ab1..93a7240849b949 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -149,7 +149,7 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { bar.cache.refresh(); expect(bar.cache.getModuleCount()).toBe( // code + styles + style/css-loader runtimes + public path updater - 14 + 18 ); expect(bar.cache.getReferencedFiles()).toMatchInlineSnapshot(` diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts index 63b253b78f4d43..47d01347a8f7d1 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts @@ -104,6 +104,7 @@ describe('getOptimizerCacheKey()', () => { "optimizerCacheKey": "♻", "repoRoot": , "themeTags": Array [ + "v7dark", "v7light", ], },