mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[kbn/optimizer] only build specified themes (#70389)
Co-authored-by: spalger <spalger@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: cchaos <caroline.horn@elastic.co>
This commit is contained in:
parent
5fcf803d3d
commit
f5b280007f
49 changed files with 545 additions and 143 deletions
|
@ -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.
|
||||
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:**
|
||||
|
||||
|
@ -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`.
|
||||
|
||||
|
|
|
@ -42,6 +42,26 @@ 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 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.
|
||||
|
||||
Currently supported theme tags: `v7light`, `v7dark`, `v8light`, `v8dark`
|
||||
|
||||
Examples:
|
||||
```sh
|
||||
# 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
|
||||
|
||||
# start Kibana with all the themes
|
||||
KBN_OPTIMIZER_THEMES=* 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.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
$globalStyleConstant: 11;
|
|
@ -0,0 +1 @@
|
|||
$globalStyleConstant: 12;
|
|
@ -0,0 +1 @@
|
|||
$globalStyleConstant: 13;
|
|
@ -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';
|
||||
|
|
92
packages/kbn-optimizer/src/common/theme_tags.test.ts
Normal file
92
packages/kbn-optimizer/src/common/theme_tags.test.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 [
|
||||
"v7dark",
|
||||
"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"`);
|
||||
});
|
65
packages/kbn-optimizer/src/common/theme_tags.ts
Normal file
65
packages/kbn-optimizer/src/common/theme_tags.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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((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');
|
||||
|
||||
export type ThemeTags = readonly ThemeTag[];
|
||||
export type ThemeTag = 'v7light' | 'v7dark' | 'v8light' | 'v8dark';
|
||||
export const DEFAULT_THEMES = tags('v7light', 'v7dark');
|
||||
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);
|
||||
}
|
|
@ -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}`);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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()
|
||||
|
@ -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()
|
||||
|
|
|
@ -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$) => {
|
||||
|
@ -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') {
|
||||
|
@ -76,6 +71,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;
|
||||
}
|
||||
|
|
|
@ -103,6 +103,10 @@ describe('getOptimizerCacheKey()', () => {
|
|||
"dist": false,
|
||||
"optimizerCacheKey": "♻",
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": Array [
|
||||
"v7dark",
|
||||
"v7light",
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
|
49
packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts
Normal file
49
packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts
Normal file
|
@ -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",
|
||||
]
|
||||
`);
|
||||
});
|
76
packages/kbn-optimizer/src/optimizer/observe_stdio.ts
Normal file
76
packages/kbn-optimizer/src/optimizer/observe_stdio.ts
Normal file
|
@ -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<string>((subscriber) => {
|
||||
let buffer = '';
|
||||
|
||||
subscriber.add(
|
||||
Rx.fromEvent<Buffer>(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<void>(stream, 'end').subscribe(() => {
|
||||
flush();
|
||||
subscriber.complete();
|
||||
})
|
||||
);
|
||||
|
||||
subscriber.add(
|
||||
Rx.fromEvent<Error>(stream, 'error').subscribe((error) => {
|
||||
flush();
|
||||
subscriber.error(error);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
|
@ -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<T>(
|
|||
);
|
||||
}
|
||||
|
||||
function observeStdio$(stream: Readable, name: WorkerStdio['stream']) {
|
||||
return Rx.fromEvent<Buffer>(stream, 'data').pipe(
|
||||
takeUntil(
|
||||
Rx.race(
|
||||
Rx.fromEvent<void>(stream, 'end'),
|
||||
Rx.fromEvent<Error>(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
|
||||
|
|
|
@ -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_THEMES;
|
||||
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_THEMES when dist = false', () => {
|
||||
process.env.KBN_OPTIMIZER_THEMES = '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": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -127,6 +151,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -154,6 +179,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -178,6 +204,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -201,6 +228,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -222,6 +250,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
"pluginScanDirs": Array [],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -243,6 +272,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
"pluginScanDirs": Array [],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -264,6 +294,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
"pluginScanDirs": Array [],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -286,6 +317,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
"pluginScanDirs": Array [],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"themeTags": undefined,
|
||||
"watch": false,
|
||||
}
|
||||
`);
|
||||
|
@ -308,6 +340,7 @@ describe('OptimizerConfig::parseOptions()', () => {
|
|||
"pluginScanDirs": Array [],
|
||||
"profileWebpack": false,
|
||||
"repoRoot": <absolute path>,
|
||||
"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 {
|
||||
|
|
|
@ -20,7 +20,14 @@
|
|||
import Path from 'path';
|
||||
import Os from 'os';
|
||||
|
||||
import { Bundle, WorkerConfig, CacheableWorkerConfig } from '../common';
|
||||
import {
|
||||
Bundle,
|
||||
WorkerConfig,
|
||||
CacheableWorkerConfig,
|
||||
ThemeTag,
|
||||
ThemeTags,
|
||||
parseThemeTags,
|
||||
} from '../common';
|
||||
|
||||
import { findKibanaPlatformPlugins, KibanaPlatformPlugin } from './kibana_platform_plugins';
|
||||
import { getPluginBundles } from './get_plugin_bundles';
|
||||
|
@ -73,6 +80,18 @@ 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:
|
||||
* - "*" when building the dist
|
||||
* - comma separated list of themes in the `KBN_OPTIMIZER_THEMES` env var
|
||||
* - "k7light"
|
||||
*/
|
||||
themes?: ThemeTag | '*' | ThemeTag[];
|
||||
}
|
||||
|
||||
interface ParsedOptions {
|
||||
|
@ -86,6 +105,7 @@ interface ParsedOptions {
|
|||
pluginScanDirs: string[];
|
||||
inspectWorkers: boolean;
|
||||
includeCoreBundle: boolean;
|
||||
themeTags: ThemeTags;
|
||||
}
|
||||
|
||||
export class OptimizerConfig {
|
||||
|
@ -139,6 +159,10 @@ export class OptimizerConfig {
|
|||
throw new TypeError('worker count must be a number');
|
||||
}
|
||||
|
||||
const themeTags = parseThemeTags(
|
||||
options.themes || (dist ? '*' : process.env.KBN_OPTIMIZER_THEMES)
|
||||
);
|
||||
|
||||
return {
|
||||
watch,
|
||||
dist,
|
||||
|
@ -150,6 +174,7 @@ export class OptimizerConfig {
|
|||
pluginPaths,
|
||||
inspectWorkers,
|
||||
includeCoreBundle,
|
||||
themeTags,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -181,7 +206,8 @@ export class OptimizerConfig {
|
|||
options.repoRoot,
|
||||
options.maxWorkerCount,
|
||||
options.dist,
|
||||
options.profileWebpack
|
||||
options.profileWebpack,
|
||||
options.themeTags
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -194,7 +220,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 +232,7 @@ export class OptimizerConfig {
|
|||
repoRoot: this.repoRoot,
|
||||
watch: this.watch,
|
||||
optimizerCacheKey,
|
||||
themeTags: this.themeTags,
|
||||
browserslistEnv: this.dist ? 'production' : process.env.BROWSERSLIST_ENV || 'dev',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ const observeCompiler = (
|
|||
*/
|
||||
const complete$ = Rx.fromEventPattern<Stats>((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;
|
||||
}
|
||||
|
|
|
@ -17,16 +17,43 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { stringifyRequest, getOptions } from 'loader-utils';
|
||||
import webpack from 'webpack';
|
||||
import { stringifyRequest } from 'loader-utils';
|
||||
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) {
|
||||
this.cacheable(true);
|
||||
|
||||
const options = getOptions(this);
|
||||
const bundleId: string = options.bundleId!;
|
||||
const themeTags = parseThemeTags(options.themeTags);
|
||||
|
||||
const cases = ALL_THEMES.map((tag) => {
|
||||
if (themeTags.includes(tag)) {
|
||||
return `
|
||||
case '${tag}':
|
||||
return require(${stringifyRequest(this, `${this.resourcePath}?${tag}`)});`;
|
||||
}
|
||||
|
||||
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}':
|
||||
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}
|
||||
}`;
|
||||
}
|
||||
|
|
|
@ -21,11 +21,10 @@ 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';
|
||||
|
@ -134,8 +133,8 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker:
|
|||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
oneOf: [
|
||||
{
|
||||
resourceQuery: /dark|light/,
|
||||
...worker.themeTags.map((theme) => ({
|
||||
resourceQuery: `?${theme}`,
|
||||
use: [
|
||||
{
|
||||
loader: 'style-loader',
|
||||
|
@ -196,34 +195,27 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker:
|
|||
loaderContext,
|
||||
Path.resolve(
|
||||
worker.repoRoot,
|
||||
'src/legacy/ui/public/styles/_styling_constants.scss'
|
||||
`src/legacy/ui/public/styles/_globals_${theme}.scss`
|
||||
)
|
||||
)};\n`;
|
||||
},
|
||||
webpackImporter: false,
|
||||
implementation: require('node-sass'),
|
||||
sassOptions(loaderContext: webpack.loader.LoaderContext) {
|
||||
const darkMode = loaderContext.resourceQuery === '?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') };
|
||||
}
|
||||
|
||||
return { file: url };
|
||||
},
|
||||
};
|
||||
sassOptions: {
|
||||
outputStyle: 'nested',
|
||||
includePaths: [Path.resolve(worker.repoRoot, 'node_modules')],
|
||||
sourceMapRoot: `/${bundle.type}:${bundle.id}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})),
|
||||
{
|
||||
loader: require.resolve('./theme_loader'),
|
||||
options: {
|
||||
bundleId: bundle.id,
|
||||
themeTags: worker.themeTags,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -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/_globals_v7light.scss')
|
||||
)};\n`;
|
||||
},
|
||||
sassOptions: {
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -23,9 +23,15 @@ const globals: any = typeof window === 'undefined' ? {} : window;
|
|||
|
||||
export type Theme = typeof LightTheme;
|
||||
|
||||
// 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;
|
||||
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 +43,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;
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import 'src/legacy/ui/public/styles/styling_constants';
|
||||
|
||||
foo {
|
||||
bar {
|
||||
display: flex;
|
||||
|
|
|
@ -29,19 +29,15 @@ 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/_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);
|
||||
|
@ -84,10 +80,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,
|
||||
|
|
12
src/legacy/ui/public/styles/_globals_v7dark.scss
Normal file
12
src/legacy/ui/public/styles/_globals_v7dark.scss
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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/functions/index';
|
||||
@import '@elastic/eui/src/global_styling/variables/index';
|
||||
@import '@elastic/eui/src/global_styling/mixins/index';
|
||||
|
||||
@import './mixins';
|
|
@ -1,9 +1,10 @@
|
|||
// EUI global scope
|
||||
// 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';
|
||||
|
||||
// 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';
|
16
src/legacy/ui/public/styles/_globals_v8dark.scss
Normal file
16
src/legacy/ui/public/styles/_globals_v8dark.scss
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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/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';
|
16
src/legacy/ui/public/styles/_globals_v8light.scss
Normal file
16
src/legacy/ui/public/styles/_globals_v8light.scss
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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/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';
|
|
@ -1,7 +1,6 @@
|
|||
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}}
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
@ -178,8 +181,7 @@ export function uiRenderMixin(kbnServer, server, config) {
|
|||
|
||||
const bootstrap = new AppBootstrap({
|
||||
templateData: {
|
||||
darkMode,
|
||||
themeVersion,
|
||||
themeTag,
|
||||
jsDependencyPaths,
|
||||
styleSheetPaths,
|
||||
publicPathMap,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import 'src/legacy/ui/public/styles/styling_constants';
|
||||
|
||||
// Prefix all styles with "tlm" to avoid conflicts.
|
||||
// Examples
|
||||
// tlmChart
|
||||
|
|
|
@ -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/_globals_v7light.scss')
|
||||
)};\n`;
|
||||
},
|
||||
sassOptions: {
|
||||
|
@ -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.scss');
|
||||
config.resolve.alias.ng_mock$ = path.resolve(KIBANA_ROOT, 'src/test_utils/public/ng_mock');
|
||||
|
||||
return config;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
@import 'src/legacy/ui/public/styles/styling_constants';
|
||||
|
||||
// Canvas core
|
||||
@import 'hackery';
|
||||
@import 'main';
|
||||
|
|
|
@ -188,7 +188,7 @@ 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/_globals_v7light.scss')
|
||||
)};\n`;
|
||||
},
|
||||
webpackImporter: false,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
@import 'src/legacy/ui/public/styles/_styling_constants';
|
||||
|
||||
@import 'components/index';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue