mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-16 18:46:57 +02:00
refactor: control base styling of code blocks via CSS vars (#7172)
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
fe064a87a6
commit
ad1526aade
9 changed files with 45 additions and 17 deletions
|
@ -481,6 +481,7 @@ describe('themeConfig', () => {
|
||||||
const prismConfig = {
|
const prismConfig = {
|
||||||
prism: {
|
prism: {
|
||||||
additionalLanguages: ['kotlin', 'java'],
|
additionalLanguages: ['kotlin', 'java'],
|
||||||
|
theme: darkTheme,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(testValidateThemeConfig(prismConfig)).toEqual({
|
expect(testValidateThemeConfig(prismConfig)).toEqual({
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
.copyButton {
|
.copyButton {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: inherit;
|
/* TODO: move to base button styling */
|
||||||
|
background: var(--prism-background-color);
|
||||||
|
color: var(--prism-color);
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
border: 1px solid var(--ifm-color-emphasis-300);
|
||||||
border-radius: var(--ifm-global-radius);
|
border-radius: var(--ifm-global-radius);
|
||||||
padding: 0.4rem;
|
padding: 0.4rem;
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
containsLineNumbers,
|
containsLineNumbers,
|
||||||
ThemeClassNames,
|
ThemeClassNames,
|
||||||
usePrismTheme,
|
usePrismTheme,
|
||||||
|
getPrismCssVariables,
|
||||||
} from '@docusaurus/theme-common';
|
} from '@docusaurus/theme-common';
|
||||||
import CopyButton from '@theme/CodeBlock/CopyButton';
|
import CopyButton from '@theme/CodeBlock/CopyButton';
|
||||||
import type {Props} from '@theme/CodeBlock';
|
import type {Props} from '@theme/CodeBlock';
|
||||||
|
@ -50,6 +51,8 @@ export default function CodeBlock({
|
||||||
const codeBlockTitle = parseCodeBlockTitle(metastring) || title;
|
const codeBlockTitle = parseCodeBlockTitle(metastring) || title;
|
||||||
const prismTheme = usePrismTheme();
|
const prismTheme = usePrismTheme();
|
||||||
|
|
||||||
|
const prismCssVariables = getPrismCssVariables(prismTheme);
|
||||||
|
|
||||||
// <pre> tags in markdown map to CodeBlocks and they may contain JSX children.
|
// <pre> tags in markdown map to CodeBlocks and they may contain JSX children.
|
||||||
// When the children is not a simple string, we just return a styled block
|
// When the children is not a simple string, we just return a styled block
|
||||||
// without actually highlighting.
|
// without actually highlighting.
|
||||||
|
@ -61,7 +64,7 @@ export default function CodeBlock({
|
||||||
theme={prismTheme}
|
theme={prismTheme}
|
||||||
code=""
|
code=""
|
||||||
language={'text' as Language}>
|
language={'text' as Language}>
|
||||||
{({className, style}) => (
|
{({className}) => (
|
||||||
<pre
|
<pre
|
||||||
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
@ -73,7 +76,7 @@ export default function CodeBlock({
|
||||||
blockClassName,
|
blockClassName,
|
||||||
ThemeClassNames.common.codeBlock,
|
ThemeClassNames.common.codeBlock,
|
||||||
)}
|
)}
|
||||||
style={style}>
|
style={prismCssVariables}>
|
||||||
<code className={styles.codeBlockLines}>{children}</code>
|
<code className={styles.codeBlockLines}>{children}</code>
|
||||||
</pre>
|
</pre>
|
||||||
)}
|
)}
|
||||||
|
@ -99,7 +102,7 @@ export default function CodeBlock({
|
||||||
theme={prismTheme}
|
theme={prismTheme}
|
||||||
code={code}
|
code={code}
|
||||||
language={(language ?? 'text') as Language}>
|
language={(language ?? 'text') as Language}>
|
||||||
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
{({className, tokens, getLineProps, getTokenProps}) => (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
styles.codeBlockContainer,
|
styles.codeBlockContainer,
|
||||||
|
@ -109,13 +112,12 @@ export default function CodeBlock({
|
||||||
language && !blockClassName.includes(`language-${language}`),
|
language && !blockClassName.includes(`language-${language}`),
|
||||||
},
|
},
|
||||||
ThemeClassNames.common.codeBlock,
|
ThemeClassNames.common.codeBlock,
|
||||||
)}>
|
|
||||||
{codeBlockTitle && (
|
|
||||||
<div style={style} className={styles.codeBlockTitle}>
|
|
||||||
{codeBlockTitle}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
<div className={styles.codeBlockContent} style={style}>
|
style={prismCssVariables}>
|
||||||
|
{codeBlockTitle && (
|
||||||
|
<div className={styles.codeBlockTitle}>{codeBlockTitle}</div>
|
||||||
|
)}
|
||||||
|
<div className={styles.codeBlockContent}>
|
||||||
<pre
|
<pre
|
||||||
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.codeBlockContainer {
|
.codeBlockContainer {
|
||||||
|
background: var(--prism-background-color);
|
||||||
|
color: var(--prism-color);
|
||||||
margin-bottom: var(--ifm-leading);
|
margin-bottom: var(--ifm-leading);
|
||||||
box-shadow: var(--ifm-global-shadow-lw);
|
box-shadow: var(--ifm-global-shadow-lw);
|
||||||
border-radius: var(--ifm-code-border-radius);
|
border-radius: var(--ifm-code-border-radius);
|
||||||
|
@ -28,7 +30,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.codeBlock {
|
.codeBlock {
|
||||||
--ifm-pre-background: inherit;
|
--ifm-pre-background: var(--prism-background-color);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +46,6 @@
|
||||||
|
|
||||||
.codeBlockLines {
|
.codeBlockLines {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
background: var(--ifm-pre-background);
|
|
||||||
/* rtl:ignore */
|
/* rtl:ignore */
|
||||||
float: left;
|
float: left;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import defaultPrismTheme from 'prism-react-renderer/themes/palenight';
|
||||||
import {Joi, URISchema} from '@docusaurus/utils-validation';
|
import {Joi, URISchema} from '@docusaurus/utils-validation';
|
||||||
import type {
|
import type {
|
||||||
ThemeConfig,
|
ThemeConfig,
|
||||||
|
@ -32,6 +33,7 @@ export const DEFAULT_CONFIG = {
|
||||||
metadata: [],
|
metadata: [],
|
||||||
prism: {
|
prism: {
|
||||||
additionalLanguages: [],
|
additionalLanguages: [],
|
||||||
|
theme: defaultPrismTheme,
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
hideOnScroll: false,
|
hideOnScroll: false,
|
||||||
|
@ -335,7 +337,7 @@ export const ThemeConfigSchema = Joi.object({
|
||||||
theme: Joi.object({
|
theme: Joi.object({
|
||||||
plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||||
styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||||
}),
|
}).default(DEFAULT_CONFIG.prism.theme),
|
||||||
darkTheme: Joi.object({
|
darkTheme: Joi.object({
|
||||||
plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||||
styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import defaultTheme from 'prism-react-renderer/themes/palenight';
|
import type {PrismTheme} from 'prism-react-renderer';
|
||||||
import {useColorMode} from '../contexts/colorMode';
|
import {useColorMode} from '../contexts/colorMode';
|
||||||
import {useThemeConfig} from '../utils/useThemeConfig';
|
import {useThemeConfig} from '../utils/useThemeConfig';
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ import {useThemeConfig} from '../utils/useThemeConfig';
|
||||||
* Returns a color-mode-dependent Prism theme: whatever the user specified in
|
* Returns a color-mode-dependent Prism theme: whatever the user specified in
|
||||||
* the config. Falls back to `palenight`.
|
* the config. Falls back to `palenight`.
|
||||||
*/
|
*/
|
||||||
export function usePrismTheme(): typeof defaultTheme {
|
export function usePrismTheme(): PrismTheme {
|
||||||
const {prism} = useThemeConfig();
|
const {prism} = useThemeConfig();
|
||||||
const {colorMode} = useColorMode();
|
const {colorMode} = useColorMode();
|
||||||
const lightModeTheme = prism.theme || defaultTheme;
|
const lightModeTheme = prism.theme;
|
||||||
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
||||||
const prismTheme = colorMode === 'dark' ? darkModeTheme : lightModeTheme;
|
const prismTheme = colorMode === 'dark' ? darkModeTheme : lightModeTheme;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ export {
|
||||||
parseLanguage,
|
parseLanguage,
|
||||||
parseLines,
|
parseLines,
|
||||||
containsLineNumbers,
|
containsLineNumbers,
|
||||||
|
getPrismCssVariables,
|
||||||
} from './utils/codeBlockUtils';
|
} from './utils/codeBlockUtils';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import rangeParser from 'parse-numeric-range';
|
import rangeParser from 'parse-numeric-range';
|
||||||
|
import type {PrismTheme} from 'prism-react-renderer';
|
||||||
|
import type {CSSProperties} from 'react';
|
||||||
|
|
||||||
const codeBlockTitleRegex = /title=(?<quote>["'])(?<title>.*?)\1/;
|
const codeBlockTitleRegex = /title=(?<quote>["'])(?<title>.*?)\1/;
|
||||||
const highlightLinesRangeRegex = /\{(?<range>[\d,-]+)\}/;
|
const highlightLinesRangeRegex = /\{(?<range>[\d,-]+)\}/;
|
||||||
|
@ -173,3 +175,20 @@ export function parseLines(
|
||||||
code = lines.join('\n');
|
code = lines.join('\n');
|
||||||
return {highlightLines, code};
|
return {highlightLines, code};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPrismCssVariables(prismTheme: PrismTheme): CSSProperties {
|
||||||
|
const mapping: {[name: keyof PrismTheme['plain']]: string} = {
|
||||||
|
color: '--prism-color',
|
||||||
|
backgroundColor: '--prism-background-color',
|
||||||
|
};
|
||||||
|
|
||||||
|
const properties: CSSProperties = {};
|
||||||
|
Object.entries(prismTheme.plain).forEach(([key, value]) => {
|
||||||
|
const varName = mapping[key];
|
||||||
|
if (varName && typeof value === 'string') {
|
||||||
|
// @ts-expect-error: why css variables not in inline style type?
|
||||||
|
properties[varName] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export type AnnouncementBarConfig = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PrismConfig = {
|
export type PrismConfig = {
|
||||||
theme?: PrismTheme;
|
theme: PrismTheme;
|
||||||
darkTheme?: PrismTheme;
|
darkTheme?: PrismTheme;
|
||||||
defaultLanguage?: string;
|
defaultLanguage?: string;
|
||||||
additionalLanguages: string[];
|
additionalLanguages: string[];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue