From dcb472814bbd9b9c14657add7abae2e393f89672 Mon Sep 17 00:00:00 2001 From: ackzell Date: Sat, 30 Aug 2025 17:06:56 +0200 Subject: [PATCH 1/3] feat(astro): add 'themes' option to the tutorialkit astro integration --- packages/astro/src/index.ts | 14 ++++++++++++-- packages/astro/src/integrations.ts | 19 ++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/astro/src/index.ts b/packages/astro/src/index.ts index 2ea81475..05c15676 100644 --- a/packages/astro/src/index.ts +++ b/packages/astro/src/index.ts @@ -1,6 +1,6 @@ import { fileURLToPath } from 'node:url'; import type { AstroConfig, AstroIntegration } from 'astro'; -import type { ExpressiveCodePlugin } from 'astro-expressive-code'; +import type { ExpressiveCodePlugin, ThemeObjectOrShikiThemeName } from 'astro-expressive-code'; import { extraIntegrations } from './integrations.js'; import { updateMarkdownConfig } from './remark/index.js'; import { tutorialkitCore } from './vite-plugins/core.js'; @@ -67,6 +67,15 @@ export interface Options { * @default [] */ expressiveCodePlugins?: ExpressiveCodePlugin[]; + + /** + * Themes for expressive code. + * Make sure to provide a light and a dark theme if you want support for both light and dark modes. + * Default values are ['light-plus', 'dark-plus'] + * + * @default ['light-plus', 'dark-plus'] + */ + themes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; } export default function createPlugin({ @@ -75,6 +84,7 @@ export default function createPlugin({ isolation, enterprise, expressiveCodePlugins = [], + themes, }: Options = {}): AstroIntegration { const webcontainerFiles = new WebContainerFiles(); @@ -149,7 +159,7 @@ export default function createPlugin({ config.integrations.splice( selfIndex + 1, 0, - ...extraIntegrations({ root: fileURLToPath(config.root), expressiveCodePlugins }), + ...extraIntegrations({ root: fileURLToPath(config.root), expressiveCodePlugins, themes }), ); }, 'astro:config:done'({ config }) { diff --git a/packages/astro/src/integrations.ts b/packages/astro/src/integrations.ts index 74348a2b..0aabcca3 100644 --- a/packages/astro/src/integrations.ts +++ b/packages/astro/src/integrations.ts @@ -4,21 +4,28 @@ import react from '@astrojs/react'; import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections'; import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'; import { getInlineContentForPackage } from '@tutorialkit/theme'; -import expressiveCode, { type ExpressiveCodePlugin } from 'astro-expressive-code'; +import expressiveCode, { type ExpressiveCodePlugin, type ThemeObjectOrShikiThemeName } from 'astro-expressive-code'; import UnoCSS from 'unocss/astro'; export function extraIntegrations({ root, expressiveCodePlugins = [], + themes = ['light-plus', 'dark-plus'], }: { root: string; expressiveCodePlugins?: ExpressiveCodePlugin[]; + + /** + * Themes for Expressive Code. + * Takes a tuple of themes, e.g. `[lightTheme, darkTheme]`. + */ + themes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; }) { return [ react(), expressiveCode({ plugins: [pluginCollapsibleSections(), pluginLineNumbers(), ...expressiveCodePlugins], - themes: ['dark-plus', 'light-plus'], + themes, customizeTheme: (theme) => { const isDark = theme.type === 'dark'; @@ -35,13 +42,7 @@ export function extraIntegrations({ }; }, themeCssSelector: (theme) => { - let customThemeName = 'light'; - - if (theme.name === 'dark-plus') { - customThemeName = 'dark'; - } - - return `[data-theme='${customThemeName}']`; + return `[data-theme='${theme.type}']`; }, defaultProps: { showLineNumbers: false, From 085c87c7a7456ba33cf1cba32815cb4338e8a251 Mon Sep 17 00:00:00 2001 From: ackzell Date: Sat, 30 Aug 2025 21:31:23 +0200 Subject: [PATCH 2/3] docs: add docs regarding themes support for Expressive Code in tutorialkit integration --- .../src/content/docs/reference/configuration.mdx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx index c70ab589..c7312bfa 100644 --- a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx +++ b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx @@ -529,3 +529,18 @@ See [Overriding Components](/guides/overriding-components/) for details of all t Controls whether the tutorial routes are automatically added to your project. When set to `true`, it additionally adds a redirect from `/` to the first tutorial. Use `"tutorial-only"` to only add the tutorial routes without the redirect. + +### `themes` + +**type**: `[ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]`
+**default**: `['light-plus', 'dark-plus']` + +Controls which themes are applied to [Expressive Code](https://expressive-code.com/). + +```ts +tutorialkit({ + themes: ['catppuccin-latte', 'catppuccin-mocha'], +}); +``` +Make sure to provide a light and a dark theme if you want support for both light and dark modes. +See the [themes](https://expressive-code.com/guides/themes/) section of Expressive Code to learn more. From bb437f65bdd5e7323acaf6d61e29e48f8ee30128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Mon, 1 Sep 2025 08:06:58 +0300 Subject: [PATCH 3/3] refactor: rename `themes` to `expressiveCodeThemes` --- .../src/content/docs/reference/configuration.mdx | 5 +++-- packages/astro/src/index.ts | 6 +++--- packages/astro/src/integrations.ts | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx index c7312bfa..ad75c46f 100644 --- a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx +++ b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx @@ -530,7 +530,7 @@ See [Overriding Components](/guides/overriding-components/) for details of all t Controls whether the tutorial routes are automatically added to your project. When set to `true`, it additionally adds a redirect from `/` to the first tutorial. Use `"tutorial-only"` to only add the tutorial routes without the redirect. -### `themes` +### `expressiveCodeThemes` **type**: `[ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]`
**default**: `['light-plus', 'dark-plus']` @@ -539,8 +539,9 @@ Controls which themes are applied to [Expressive Code](https://expressive-code.c ```ts tutorialkit({ - themes: ['catppuccin-latte', 'catppuccin-mocha'], + expressiveCodeThemes: ['catppuccin-latte', 'catppuccin-mocha'], }); ``` + Make sure to provide a light and a dark theme if you want support for both light and dark modes. See the [themes](https://expressive-code.com/guides/themes/) section of Expressive Code to learn more. diff --git a/packages/astro/src/index.ts b/packages/astro/src/index.ts index 05c15676..86eb3a5d 100644 --- a/packages/astro/src/index.ts +++ b/packages/astro/src/index.ts @@ -75,7 +75,7 @@ export interface Options { * * @default ['light-plus', 'dark-plus'] */ - themes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; + expressiveCodeThemes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; } export default function createPlugin({ @@ -84,7 +84,7 @@ export default function createPlugin({ isolation, enterprise, expressiveCodePlugins = [], - themes, + expressiveCodeThemes, }: Options = {}): AstroIntegration { const webcontainerFiles = new WebContainerFiles(); @@ -159,7 +159,7 @@ export default function createPlugin({ config.integrations.splice( selfIndex + 1, 0, - ...extraIntegrations({ root: fileURLToPath(config.root), expressiveCodePlugins, themes }), + ...extraIntegrations({ root: fileURLToPath(config.root), expressiveCodePlugins, expressiveCodeThemes }), ); }, 'astro:config:done'({ config }) { diff --git a/packages/astro/src/integrations.ts b/packages/astro/src/integrations.ts index 0aabcca3..01a95cac 100644 --- a/packages/astro/src/integrations.ts +++ b/packages/astro/src/integrations.ts @@ -10,7 +10,7 @@ import UnoCSS from 'unocss/astro'; export function extraIntegrations({ root, expressiveCodePlugins = [], - themes = ['light-plus', 'dark-plus'], + expressiveCodeThemes = ['light-plus', 'dark-plus'], }: { root: string; expressiveCodePlugins?: ExpressiveCodePlugin[]; @@ -19,13 +19,13 @@ export function extraIntegrations({ * Themes for Expressive Code. * Takes a tuple of themes, e.g. `[lightTheme, darkTheme]`. */ - themes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; + expressiveCodeThemes?: [ThemeObjectOrShikiThemeName, ThemeObjectOrShikiThemeName]; }) { return [ react(), expressiveCode({ plugins: [pluginCollapsibleSections(), pluginLineNumbers(), ...expressiveCodePlugins], - themes, + themes: expressiveCodeThemes, customizeTheme: (theme) => { const isDark = theme.type === 'dark';