Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8,568 changes: 2,886 additions & 5,682 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"dependencies": {
"@diplodoc/client": "^3.1.12",
"@diplodoc/translation": "^1.7.3",
"chroma-js": "^3.1.2",
"highlight.js": "^11.10.0",
"katex": "^0.16.9",
"shelljs": "0.8.5",
Expand All @@ -76,6 +77,7 @@
"@octokit/core": "4.2.4",
"@types/async": "^3.2.15",
"@types/chalk": "2.2.0",
"@types/chroma-js": "^3.1.0",
"@types/html-escaper": "^3.0.0",
"@types/js-yaml": "4.0.9",
"@types/json-stringify-safe": "^5.0.3",
Expand Down
19 changes: 19 additions & 0 deletions src/commands/build/features/themer/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {cyan} from 'chalk';
import {option} from '~/core/config';

const themer = option({
flags: '--theme <theme>',
desc: `
Generate and applies theme from a color 'value'

Read more about themization ${cyan('wip')}

Example:
{{PROGRAM}} --theme red
{{PROGRAM}} --theme 'rgb(116, 255, 69)'
`,
});

export const options = {
themer,
};
60 changes: 60 additions & 0 deletions src/commands/build/features/themer/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {BrandDependColorOptions, ThemeVariant} from './types';

export const THEME_VARIANTS: ThemeVariant[] = ['light', 'dark'];

export const THEME_GRAVITY_VARIABLE_PREFIX = '--g-color';

export const THEME_YFM_VARIABLE_PREFIX = '--yfm-color';

export const THEME_DC_VARIABLE_PREFIX = '--dc-color';

export const BRAND_COLOR_VARIABLE_PREFIX = `${THEME_GRAVITY_VARIABLE_PREFIX}-private-brand`;

export const DEFAULT_BRAND_DEPEND_COLORS: Record<
ThemeVariant,
Required<BrandDependColorOptions>
> = {
light: {
'base-brand': 'rgb(82, 130, 255)',
'base-background': 'rgb(255,255,255)',
'base-selection': 'var(--g-color-private-brand-150)',
'text-link': 'var(--g-color-private-brand-700-solid)',
'text-link-hover': 'var(--g-color-private-brand-850-solid)',
},
dark: {
'base-brand': 'rgb(82, 130, 255)',
'base-background': 'rgb(45, 44, 51)',
'base-selection': 'var(--g-color-private-brand-150)',
'text-link': 'var(--g-color-private-brand-700-solid)',
'text-link-hover': 'var(--g-color-private-brand-850-solid)',
},
};

export const PRIVATE_SOLID_VARIABLES = [
1000, 950, 900, 850, 800, 750, 700, 650, 600, 500, 450, 400, 350, 300, 250, 200, 150, 100, 50,
];

export const PRIVATE_VARIABLES = [500, 450, 400, 350, 300, 250, 200, 150, 100, 50];

export const COLOR_MAP = {
50: {a: 0.1, c: -1},
100: {a: 0.15, c: -1},
150: {a: 0.2, c: -1},
200: {a: 0.3, c: -1},
250: {a: 0.4, c: -1},
300: {a: 0.5, c: -1},
350: {a: 0.6, c: -1},
400: {a: 0.7, c: -1},
450: {a: 0.8, c: -1},
500: {a: 0.9, c: -1},
550: {a: 1, c: 1},
600: {a: 0.9, c: 1},
650: {a: 0.8, c: 1},
700: {a: 0.7, c: 1},
750: {a: 0.6, c: 1},
800: {a: 0.5, c: 1},
850: {a: 0.4, c: 1},
900: {a: 0.3, c: 1},
950: {a: 0.2, c: 1},
1000: {a: 0.15, c: 1},
};
285 changes: 285 additions & 0 deletions src/commands/build/features/themer/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {runBuild, setupBuild, testConfig as test} from '../../__tests__';
import dedent from 'ts-dedent';
import {resolve} from 'node:path';
import * as utils from './utils';
import {THEME_CSS_PATH} from '~/constants';
import {DEFAULT_BRAND_DEPEND_COLORS} from './constants';

describe('Build themer feature', () => {
describe('config', () => {
afterEach(() => {
vi.restoreAllMocks();
});

test('should handle default', '', {
theme: false,
});

test('should handle arg', '--theme blue', {
theme: 'blue',
});
});

describe('run', () => {
const args = (...args: string[]) =>
'-i /dev/null/input -o /dev/null/output ' + args.join(' ');

describe('no theme', () => {
it('should not create theme for html build', async () => {
const build = setupBuild();

await runBuild(args(), build);

expect(build.run.write).not.toHaveBeenCalled();
});

it('should not create theme for md build', async () => {
const build = setupBuild();

await runBuild(args('-f', 'md'), build);

expect(build.run.write).not.toHaveBeenCalled();
});
});

describe('from file', () => {
beforeEach(() => {
vi.spyOn(utils, 'isThemeFileExists').mockReturnValue(true);
});

afterEach(() => {
vi.restoreAllMocks();
});

it('should create theme for html', async () => {
const build = setupBuild({
files: {
'theme.yaml': dedent`
text-secondary: blue
`,
},
});

await runBuild(args(), build);

expect(build.run.write).toHaveBeenCalledWith(
resolve(build.run.originalOutput, THEME_CSS_PATH),
`.g-root {\n --g-color-text-secondary: blue;\n}`,
);
});

it('should create theme for md ', async () => {
const build = setupBuild({
files: {
'theme.yaml': dedent`
text-secondary: blue
`,
},
});

await runBuild(args('-f', 'md'), build);

expect(build.run.write).toHaveBeenCalledWith(
resolve(build.run.originalOutput, THEME_CSS_PATH),
dedent`
.g-root {
--g-color-text-secondary: blue;
}`,
);
});

it('should create theme with base-brand', async () => {
const build = setupBuild({
files: {
'theme.yaml': dedent`
base-brand: rgb(78, 231, 228)
`,
},
});

await runBuild(args(), build);

const expectedString = dedent`
.g-root {
--g-color-base-brand: rgb(78, 231, 228);
}

.g-root_theme_light {
--g-color-private-brand-50: rgb(78 231 228 / 0.1);
--g-color-private-brand-100: rgb(78 231 228 / 0.15);
--g-color-private-brand-150: rgb(78 231 228 / 0.2);
--g-color-private-brand-200: rgb(78 231 228 / 0.3);
--g-color-private-brand-250: rgb(78 231 228 / 0.4);
--g-color-private-brand-300: rgb(78 231 228 / 0.5);
--g-color-private-brand-350: rgb(78 231 228 / 0.6);
--g-color-private-brand-400: rgb(78 231 228 / 0.7);
--g-color-private-brand-450: rgb(78 231 228 / 0.8);
--g-color-private-brand-500: rgb(78 231 228 / 0.9);
--g-color-private-brand-550-solid: rgb(78 231 228);
--g-color-private-brand-1000-solid: rgb(50 72 78);
--g-color-private-brand-950-solid: rgb(52 81 86);
--g-color-private-brand-900-solid: rgb(55 100 104);
--g-color-private-brand-850-solid: rgb(58 119 122);
--g-color-private-brand-800-solid: rgb(62 138 140);
--g-color-private-brand-750-solid: rgb(65 156 157);
--g-color-private-brand-700-solid: rgb(68 175 175);
--g-color-private-brand-650-solid: rgb(71 194 193);
--g-color-private-brand-600-solid: rgb(75 212 210);
--g-color-private-brand-500-solid: rgb(75 212 210);
--g-color-private-brand-450-solid: rgb(71 194 193);
--g-color-private-brand-400-solid: rgb(68 175 175);
--g-color-private-brand-350-solid: rgb(65 156 157);
--g-color-private-brand-300-solid: rgb(62 138 140);
--g-color-private-brand-250-solid: rgb(58 119 122);
--g-color-private-brand-200-solid: rgb(55 100 104);
--g-color-private-brand-150-solid: rgb(52 81 86);
--g-color-private-brand-100-solid: rgb(50 72 78);
--g-color-private-brand-50-solid: rgb(48 63 69);
--g-color-base-brand: rgb(78, 231, 228);
--g-color-base-background: ${DEFAULT_BRAND_DEPEND_COLORS.light['base-background']};
--g-color-base-selection: ${DEFAULT_BRAND_DEPEND_COLORS.light['base-selection']};
--g-color-text-link: ${DEFAULT_BRAND_DEPEND_COLORS.light['text-link']};
--g-color-text-link-hover: ${DEFAULT_BRAND_DEPEND_COLORS.light['text-link-hover']};
}

.g-root_theme_dark {
--g-color-private-brand-50: rgb(78 231 228 / 0.1);
--g-color-private-brand-100: rgb(78 231 228 / 0.15);
--g-color-private-brand-150: rgb(78 231 228 / 0.2);
--g-color-private-brand-200: rgb(78 231 228 / 0.3);
--g-color-private-brand-250: rgb(78 231 228 / 0.4);
--g-color-private-brand-300: rgb(78 231 228 / 0.5);
--g-color-private-brand-350: rgb(78 231 228 / 0.6);
--g-color-private-brand-400: rgb(78 231 228 / 0.7);
--g-color-private-brand-450: rgb(78 231 228 / 0.8);
--g-color-private-brand-500: rgb(78 231 228 / 0.9);
--g-color-private-brand-550-solid: rgb(78 231 228);
--g-color-private-brand-1000-solid: rgb(228 251 251);
--g-color-private-brand-950-solid: rgb(220 250 250);
--g-color-private-brand-900-solid: rgb(202 248 247);
--g-color-private-brand-850-solid: rgb(184 245 244);
--g-color-private-brand-800-solid: rgb(167 243 242);
--g-color-private-brand-750-solid: rgb(149 241 239);
--g-color-private-brand-700-solid: rgb(131 238 236);
--g-color-private-brand-650-solid: rgb(113 236 233);
--g-color-private-brand-600-solid: rgb(96 233 231);
--g-color-private-brand-500-solid: rgb(96 233 231);
--g-color-private-brand-450-solid: rgb(113 236 233);
--g-color-private-brand-400-solid: rgb(131 238 236);
--g-color-private-brand-350-solid: rgb(149 241 239);
--g-color-private-brand-300-solid: rgb(167 243 242);
--g-color-private-brand-250-solid: rgb(184 245 244);
--g-color-private-brand-200-solid: rgb(202 248 247);
--g-color-private-brand-150-solid: rgb(220 250 250);
--g-color-private-brand-100-solid: rgb(228 251 251);
--g-color-private-brand-50-solid: rgb(237 253 252);
--g-color-base-brand: rgb(78, 231, 228);
--g-color-base-background: ${DEFAULT_BRAND_DEPEND_COLORS.dark['base-background']};
--g-color-base-selection: ${DEFAULT_BRAND_DEPEND_COLORS.dark['base-selection']};
--g-color-text-link: ${DEFAULT_BRAND_DEPEND_COLORS.dark['text-link']};
--g-color-text-link-hover: ${DEFAULT_BRAND_DEPEND_COLORS.dark['text-link-hover']};
}`;

expect(build.run.write).toHaveBeenCalledWith(
resolve(build.run.originalOutput, THEME_CSS_PATH),
expectedString,
);
});
});

describe('from arg', () => {
it('should create theme from --theme arg', async () => {
const build = setupBuild();

await runBuild(args('--theme', 'blue'), build);

const expectedString = dedent`
.g-root {
--g-color-base-brand: blue;
}

.g-root_theme_light {
--g-color-private-brand-50: rgb(0 0 255 / 0.1);
--g-color-private-brand-100: rgb(0 0 255 / 0.15);
--g-color-private-brand-150: rgb(0 0 255 / 0.2);
--g-color-private-brand-200: rgb(0 0 255 / 0.3);
--g-color-private-brand-250: rgb(0 0 255 / 0.4);
--g-color-private-brand-300: rgb(0 0 255 / 0.5);
--g-color-private-brand-350: rgb(0 0 255 / 0.6);
--g-color-private-brand-400: rgb(0 0 255 / 0.7);
--g-color-private-brand-450: rgb(0 0 255 / 0.8);
--g-color-private-brand-500: rgb(0 0 255 / 0.9);
--g-color-private-brand-550-solid: rgb(0 0 255);
--g-color-private-brand-1000-solid: rgb(38 37 82);
--g-color-private-brand-950-solid: rgb(36 35 92);
--g-color-private-brand-900-solid: rgb(31 31 112);
--g-color-private-brand-850-solid: rgb(27 26 133);
--g-color-private-brand-800-solid: rgb(23 22 153);
--g-color-private-brand-750-solid: rgb(18 18 173);
--g-color-private-brand-700-solid: rgb(14 13 194);
--g-color-private-brand-650-solid: rgb(9 9 214);
--g-color-private-brand-600-solid: rgb(4 4 235);
--g-color-private-brand-500-solid: rgb(4 4 235);
--g-color-private-brand-450-solid: rgb(9 9 214);
--g-color-private-brand-400-solid: rgb(14 13 194);
--g-color-private-brand-350-solid: rgb(18 18 173);
--g-color-private-brand-300-solid: rgb(23 22 153);
--g-color-private-brand-250-solid: rgb(27 26 133);
--g-color-private-brand-200-solid: rgb(31 31 112);
--g-color-private-brand-150-solid: rgb(36 35 92);
--g-color-private-brand-100-solid: rgb(38 37 82);
--g-color-private-brand-50-solid: rgb(41 40 71);
--g-color-base-brand: blue;
--g-color-base-background: ${DEFAULT_BRAND_DEPEND_COLORS.light['base-background']};
--g-color-base-selection: ${DEFAULT_BRAND_DEPEND_COLORS.light['base-selection']};
--g-color-text-link: ${DEFAULT_BRAND_DEPEND_COLORS.light['text-link']};
--g-color-text-link-hover: ${DEFAULT_BRAND_DEPEND_COLORS.light['text-link-hover']};
}

.g-root_theme_dark {
--g-color-private-brand-50: rgb(0 0 255 / 0.1);
--g-color-private-brand-100: rgb(0 0 255 / 0.15);
--g-color-private-brand-150: rgb(0 0 255 / 0.2);
--g-color-private-brand-200: rgb(0 0 255 / 0.3);
--g-color-private-brand-250: rgb(0 0 255 / 0.4);
--g-color-private-brand-300: rgb(0 0 255 / 0.5);
--g-color-private-brand-350: rgb(0 0 255 / 0.6);
--g-color-private-brand-400: rgb(0 0 255 / 0.7);
--g-color-private-brand-450: rgb(0 0 255 / 0.8);
--g-color-private-brand-500: rgb(0 0 255 / 0.9);
--g-color-private-brand-550-solid: rgb(0 0 255);
--g-color-private-brand-1000-solid: rgb(217 217 255);
--g-color-private-brand-950-solid: rgb(204 204 255);
--g-color-private-brand-900-solid: rgb(179 179 255);
--g-color-private-brand-850-solid: rgb(153 153 255);
--g-color-private-brand-800-solid: rgb(128 128 255);
--g-color-private-brand-750-solid: rgb(102 102 255);
--g-color-private-brand-700-solid: rgb(77 77 255);
--g-color-private-brand-650-solid: rgb(51 51 255);
--g-color-private-brand-600-solid: rgb(25 25 255);
--g-color-private-brand-500-solid: rgb(25 25 255);
--g-color-private-brand-450-solid: rgb(51 51 255);
--g-color-private-brand-400-solid: rgb(77 77 255);
--g-color-private-brand-350-solid: rgb(102 102 255);
--g-color-private-brand-300-solid: rgb(128 128 255);
--g-color-private-brand-250-solid: rgb(153 153 255);
--g-color-private-brand-200-solid: rgb(179 179 255);
--g-color-private-brand-150-solid: rgb(204 204 255);
--g-color-private-brand-100-solid: rgb(217 217 255);
--g-color-private-brand-50-solid: rgb(230 230 255);
--g-color-base-brand: blue;
--g-color-base-background: ${DEFAULT_BRAND_DEPEND_COLORS.dark['base-background']};
--g-color-base-selection: ${DEFAULT_BRAND_DEPEND_COLORS.dark['base-selection']};
--g-color-text-link: ${DEFAULT_BRAND_DEPEND_COLORS.dark['text-link']};
--g-color-text-link-hover: ${DEFAULT_BRAND_DEPEND_COLORS.dark['text-link-hover']};
}`;

expect(build.run.write).toHaveBeenCalledWith(
resolve(build.run.originalOutput, THEME_CSS_PATH),
expectedString,
);
});
});
});
});
Loading