From 5ef8d166cbbac0806efb57748033d7844505eb80 Mon Sep 17 00:00:00 2001 From: Karthik Date: Fri, 21 Nov 2025 10:26:20 +0530 Subject: [PATCH 1/3] feat(techdocs): add app-config option to disable external font download Signed-off-by: Karthik --- .changeset/kind-files-press.md | 6 ++ docs/features/techdocs/how-to-guides.md | 32 ++++++- plugins/techdocs-backend/config.d.ts | 8 ++ .../src/stages/generate/helpers.test.ts | 96 +++++++++++++++++++ .../src/stages/generate/mkdocsPatchers.ts | 40 ++++++++ .../src/stages/generate/techdocs.ts | 7 ++ .../src/stages/generate/types.ts | 1 + 7 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 .changeset/kind-files-press.md diff --git a/.changeset/kind-files-press.md b/.changeset/kind-files-press.md new file mode 100644 index 0000000000..edc19b7a76 --- /dev/null +++ b/.changeset/kind-files-press.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-backend': minor +'@backstage/plugin-techdocs-node': minor +--- + +Add support for disabling external font downloads via app-config option `techdocs.generator.mkdocs.disableExternalFonts`, useful for air-gapped Backstage instances. diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 33faf44841..27725e50fa 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -551,7 +551,31 @@ Done! You now have support for TechDocs in your own software template! ### Prevent download of Google fonts -If your Backstage instance does not have internet access, the generation will fail. TechDocs tries to download the Roboto font from Google. You can disable it by adding the following lines to mkdocs.yaml: +If your Backstage instance does not have internet access, the generation will fail. TechDocs tries to download the Roboto font from Google. You can disable it by configuring your `app-config.yaml` or by manually updating your `mkdocs.yml` file. + +#### Using app-config + +Add the following configuration to your `app-config.yaml` to automatically +disable external font downloads for all TechDocs sites: + +```yaml +techdocs: + generator: + mkdocs: + disableExternalFonts: true +``` + +This configuration will automatically patch the `mkdocs.yml` file during the +generation process. If no `theme` section exists, it will create one with `name: +material` and `font: false`. If a `theme` section exists but `font` is not +configured, it will add `font: false` to the existing theme. If `font` is +already explicitly configured in your `mkdocs.yml`, the patcher will respect +your file-level configuration and not override it. + +#### Manual configuration in mkdocs.yml + +Alternatively, you can manually add the following configuration to your `mkdocs.yaml` +file: ```yaml theme: @@ -561,7 +585,11 @@ theme: :::note Note -The addition `name: material` is necessary. Otherwise it will not work +The addition `name: material` is necessary. Otherwise it will not work. + +If you explicitly set `font: true` or `font: false` in your `mkdocs.yml`, the +app-config patcher will respect that setting and not override it. The patcher +only adds `font: false` when the `font` property is not already configured. ::: diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 87369f2ccd..65e536bfd5 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -76,6 +76,14 @@ export interface Config { * @see https://www.mkdocs.org/user-guide/configuration/#hooks */ dangerouslyAllowAdditionalKeys?: string[]; + + /** + * Disable external fonts for all TechDocs sites. + * If not set, the default value is false. + * If set to true, the external font will be disabled for all TechDocs sites. + * If set to false, the external font will be enabled for all TechDocs sites. + */ + disableExternalFonts?: boolean; }; }; diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 1f198b43e9..8f6331b621 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -37,6 +37,7 @@ import { patchMkdocsYmlPreBuild, patchMkdocsYmlWithPlugins, sanitizeMkdocsYml, + patchMkdocsYmlWithFontDisabled } from './mkdocsPatchers'; import yaml from 'js-yaml'; @@ -468,6 +469,101 @@ describe('helpers', () => { }); }); + describe('patchMkdocsYmlWithFontDisabled', () => { + beforeEach(() => { + mockDir.setContent({ + 'mkdocs_without_theme.yml': `site_name: Test Site +docs_dir: docs +`, + 'mkdocs_with_theme_no_font.yml': `site_name: Test Site +docs_dir: docs +theme: + name: material +`, + 'mkdocs_with_theme_font_true.yml': `site_name: Test Site +docs_dir: docs +theme: + name: material + font: true +`, + 'mkdocs_with_theme_font_false.yml': `site_name: Test Site +docs_dir: docs +theme: + name: material + font: false +`, + }); + }); + + it('should create theme section with font disabled when no theme exists', async () => { + await patchMkdocsYmlWithFontDisabled( + mockDir.resolve('mkdocs_without_theme.yml'), + mockLogger, + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_without_theme.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as { + theme?: { name?: string; font?: boolean }; + }; + expect(parsedYml.theme).toBeDefined(); + expect(parsedYml.theme?.name).toBe('material'); + expect(parsedYml.theme?.font).toBe(false); + }); + + it('should add font: false when theme exists but font is not configured', async () => { + await patchMkdocsYmlWithFontDisabled( + mockDir.resolve('mkdocs_with_theme_no_font.yml'), + mockLogger, + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_with_theme_no_font.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as { + theme?: { name?: string; font?: boolean }; + }; + expect(parsedYml.theme).toBeDefined(); + expect(parsedYml.theme?.name).toBe('material'); + expect(parsedYml.theme?.font).toBe(false); + }); + + it('should not override font when font is already set to true', async () => { + await patchMkdocsYmlWithFontDisabled( + mockDir.resolve('mkdocs_with_theme_font_true.yml'), + mockLogger, + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_with_theme_font_true.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as { + theme?: { name?: string; font?: boolean }; + }; + expect(parsedYml.theme).toBeDefined(); + expect(parsedYml.theme?.name).toBe('material'); + expect(parsedYml.theme?.font).toBe(true); + }); + + it('should not override font when font is already set to false', async () => { + await patchMkdocsYmlWithFontDisabled( + mockDir.resolve('mkdocs_with_theme_font_false.yml'), + mockLogger, + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_with_theme_font_false.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as { + theme?: { name?: string; font?: boolean }; + }; + expect(parsedYml.theme).toBeDefined(); + expect(parsedYml.theme?.name).toBe('material'); + expect(parsedYml.theme?.font).toBe(false); + }); + }); + describe('patchIndexPreBuild', () => { afterEach(() => { warn.mockClear(); diff --git a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts index d676237b01..5f87a85c9d 100644 --- a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts +++ b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts @@ -25,11 +25,17 @@ import { assertError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { LoggerService } from '@backstage/backend-plugin-api'; +const MATERIAL_THEME = 'material'; + type MkDocsObject = { plugins?: string[]; docs_dir: string; repo_url?: string; edit_uri?: string; + theme?: { + name?: string; + font?: boolean; + }; }; const patchMkdocsFile = async ( @@ -185,6 +191,39 @@ export const patchMkdocsYmlWithPlugins = async ( }); }; +/** + * Disable external font download for the material theme. + * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site + * @param logger + */ +export const patchMkdocsYmlWithFontDisabled = async ( + mkdocsYmlPath: string, + logger: LoggerService, +) => { + await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => { + if (!('theme' in mkdocsYml)) { + // No theme section exists, create it with font disabled + mkdocsYml.theme = { + name: MATERIAL_THEME, + font: false, + }; + return true; + } + + // Theme section exists, check if font is not configured, add font: false + if ( + mkdocsYml.theme && + typeof mkdocsYml.theme === 'object' && + !('font' in mkdocsYml.theme) + ) { + mkdocsYml.theme.font = false; + return true; + } + + return false; + }); +}; + /** * Sanitize mkdocs.yml by keeping only allowed configuration keys. * @@ -249,3 +288,4 @@ export const sanitizeMkdocsYml = async ( return true; }); }; + diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 8a764eb391..905d2e3cb9 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -32,6 +32,7 @@ import { import { patchMkdocsYmlPreBuild, + patchMkdocsYmlWithFontDisabled, patchMkdocsYmlWithPlugins, sanitizeMkdocsYml, } from './mkdocsPatchers'; @@ -150,6 +151,9 @@ export class TechdocsGenerator implements GeneratorBase { } await patchMkdocsYmlWithPlugins(mkdocsYmlPath, childLogger, defaultPlugins); + if (this.options.disableExternalFonts) { + await patchMkdocsYmlWithFontDisabled(mkdocsYmlPath, childLogger); + } // Directories to bind on container const mountDirs = { @@ -264,5 +268,8 @@ export function readGeneratorConfig( dangerouslyAllowAdditionalKeys: config.getOptionalStringArray( 'techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys', ), + disableExternalFonts: config.getOptionalBoolean( + 'techdocs.generator.mkdocs.disableExternalFonts' + ), }; } diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index b716e9510b..65243129ed 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -46,6 +46,7 @@ export type GeneratorConfig = { legacyCopyReadmeMdToIndexMd?: boolean; defaultPlugins?: string[]; dangerouslyAllowAdditionalKeys?: string[]; + disableExternalFonts?: boolean; }; /** From 329f5920b68093f59bb8a45f7e64af678c5f5c2c Mon Sep 17 00:00:00 2001 From: Karthik Date: Tue, 25 Nov 2025 14:16:44 +0530 Subject: [PATCH 2/3] feat(techdocs): add techdocs-cli option to disable external font download Signed-off-by: Karthik --- .changeset/funny-animals-prove.md | 5 +++++ .../vale/config/vocabularies/Backstage/accept.txt | 1 + docs/features/techdocs/cli.md | 2 ++ docs/features/techdocs/how-to-guides.md | 14 +++++++++++++- packages/techdocs-cli/cli-report.md | 1 + .../techdocs-cli/src/commands/generate/generate.ts | 2 ++ packages/techdocs-cli/src/commands/index.ts | 5 +++++ plugins/techdocs-backend/config.d.ts | 2 +- .../src/stages/generate/helpers.test.ts | 2 +- .../src/stages/generate/mkdocsPatchers.ts | 14 ++++++++++++-- .../techdocs-node/src/stages/generate/techdocs.ts | 2 +- 11 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 .changeset/funny-animals-prove.md diff --git a/.changeset/funny-animals-prove.md b/.changeset/funny-animals-prove.md new file mode 100644 index 0000000000..e4116a8d23 --- /dev/null +++ b/.changeset/funny-animals-prove.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': minor +--- + +Add support for disabling external font downloads via techdocs-cli `techdocs-cli generate --disableExternalFonts`, useful for air-gapped Backstage instances. diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 0a96735646..c5a5deb5e0 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -587,3 +587,4 @@ zod Zolotusky zoomable zsh +patcher \ No newline at end of file diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index fa3d9148e2..616acb01e6 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -149,6 +149,8 @@ Options: Defaults to false, which means that the techdocs-core plugin is always added to the mkdocs file. --legacyCopyReadmeMdToIndexMd Attempt to ensure an index.md exists falling back to using /README.md or README.md in case a default /index.md is not provided. (default: false) + --disableExternalFonts Disable external font downloads for all TechDocs sites. Useful for air-gapped environments + where Google fonts cannot be accessed. (default: false) --runAsDefaultUser Bypass setting the container user as the same user and group id as host for Linux and MacOS (default: false) -v, --verbose Enable verbose output. (default: false) -h, --help display help for command diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 27725e50fa..e8b1304115 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -574,7 +574,7 @@ your file-level configuration and not override it. #### Manual configuration in mkdocs.yml -Alternatively, you can manually add the following configuration to your `mkdocs.yaml` +Alternatively, you can manually add the following configuration to your `mkdocs.yml` file: ```yaml @@ -593,6 +593,18 @@ only adds `font: false` when the `font` property is not already configured. ::: +#### Using techdocs-cli in CI/CD + +When generating TechDocs sites in CI/CD workflows using `techdocs-cli`, you can +use the `--disableExternalFonts` flag: + +```bash +techdocs-cli generate --disableExternalFonts +``` + +This will automatically patch the `mkdocs.yml` file during the generation +process, just like the `app-config.yaml` option does for local generation. + ## How to enable iframes in TechDocs TechDocs uses the [DOMPurify](https://github.com/cure53/DOMPurify) library to diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md index 667c4fb6b6..f682072cd7 100644 --- a/packages/techdocs-cli/cli-report.md +++ b/packages/techdocs-cli/cli-report.md @@ -27,6 +27,7 @@ Usage: techdocs-cli generate|build [options] Options: --defaultPlugin [defaultPlugins...] + --disableExternalFonts --docker-image --etag --legacyCopyReadmeMdToIndexMd diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 9a009aff00..b5b38b13d7 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -42,6 +42,7 @@ export default async function generate(opts: OptionValues) { const dockerImage = opts.dockerImage; const pullImage = opts.pull; const legacyCopyReadmeMdToIndexMd = opts.legacyCopyReadmeMdToIndexMd; + const disableExternalFonts = opts.disableExternalFonts; const defaultPlugins = opts.defaultPlugin; logger.info(`Using source dir ${sourceDir}`); @@ -64,6 +65,7 @@ export default async function generate(opts: OptionValues) { mkdocs: { legacyCopyReadmeMdToIndexMd, omitTechdocsCorePlugin, + disableExternalFonts, defaultPlugins, }, }, diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index e69cf4671a..c169815afc 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -70,6 +70,11 @@ export function registerCommands(program: Command) { 'Attempt to ensure an index.md exists falling back to using /README.md or README.md in case a default /index.md is not provided.', false, ) + .option( + '--disableExternalFonts', + 'Disable external font downloads by default by setting theme.font: false in mkdocs.yml when not already configured. Useful for air-gapped environments where Google fonts cannot be accessed.', + false, + ) .option( '--defaultPlugin [defaultPlugins...]', 'Plugins which should be added automatically to the mkdocs.yaml file', diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 65e536bfd5..64c7fdc35f 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -76,7 +76,7 @@ export interface Config { * @see https://www.mkdocs.org/user-guide/configuration/#hooks */ dangerouslyAllowAdditionalKeys?: string[]; - + /** * Disable external fonts for all TechDocs sites. * If not set, the default value is false. diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 8f6331b621..23eeaaa20e 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -37,7 +37,7 @@ import { patchMkdocsYmlPreBuild, patchMkdocsYmlWithPlugins, sanitizeMkdocsYml, - patchMkdocsYmlWithFontDisabled + patchMkdocsYmlWithFontDisabled, } from './mkdocsPatchers'; import yaml from 'js-yaml'; diff --git a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts index 5f87a85c9d..28c5928de6 100644 --- a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts +++ b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts @@ -210,16 +210,27 @@ export const patchMkdocsYmlWithFontDisabled = async ( return true; } - // Theme section exists, check if font is not configured, add font: false + // Theme section exists. Only modify it when the configured theme is Material if ( mkdocsYml.theme && typeof mkdocsYml.theme === 'object' && + (mkdocsYml.theme as any).name === MATERIAL_THEME && !('font' in mkdocsYml.theme) ) { mkdocsYml.theme.font = false; return true; } + if ( + mkdocsYml.theme && + typeof mkdocsYml.theme === 'object' && + (mkdocsYml.theme as any).name !== MATERIAL_THEME + ) { + logger.debug( + 'mkdocs.yml theme is not "material"; skipping font disabling patch', + ); + } + return false; }); }; @@ -288,4 +299,3 @@ export const sanitizeMkdocsYml = async ( return true; }); }; - diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 905d2e3cb9..e3492f2043 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -269,7 +269,7 @@ export function readGeneratorConfig( 'techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys', ), disableExternalFonts: config.getOptionalBoolean( - 'techdocs.generator.mkdocs.disableExternalFonts' + 'techdocs.generator.mkdocs.disableExternalFonts', ), }; } From 610b42f72f2391a70daf9b574c82ec7bdadca092 Mon Sep 17 00:00:00 2001 From: Karthik Date: Wed, 29 Apr 2026 00:15:28 +0530 Subject: [PATCH 3/3] update documentation and improve types Signed-off-by: Karthik --- .../config/vocabularies/Backstage/accept.txt | 4 +- docs/features/techdocs/configuration.md | 27 +++++++++++ docs/features/techdocs/how-to-guides.md | 33 ++++---------- .../src/stages/generate/helpers.test.ts | 18 ++++++++ .../src/stages/generate/mkdocsPatchers.ts | 45 +++++++++---------- 5 files changed, 77 insertions(+), 50 deletions(-) diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index c5a5deb5e0..17f8fe8173 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -343,6 +343,7 @@ params parseable passthrough passwordless +patcher Patrik pattison Peloton @@ -586,5 +587,4 @@ Zhou zod Zolotusky zoomable -zsh -patcher \ No newline at end of file +zsh \ No newline at end of file diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index cf9215ebc3..9c8c0dfc90 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -97,6 +97,33 @@ techdocs: legacyCopyReadmeMdToIndexMd: false ``` +#### Disable external fonts + +`techdocs.generator.mkdocs.disableExternalFonts` + +(Optional) Use this when the generator cannot reach the internet (for example air-gapped or restricted networks). MkDocs Material otherwise tries to download the Roboto font from Google during generation. + +When `true`, TechDocs patches each `mkdocs.yml` during generation: if no `theme` section exists it adds `name: material` and `font: false`; if a `theme` exists but `font` is omitted, it sets `font: false`; if `font` is already set in the file, your value is left unchanged. + +**Example:** + +```yaml +techdocs: + generator: + mkdocs: + disableExternalFonts: true +``` + +Alternatively, configure `mkdocs.yml` manually: + +```yaml +theme: + name: material + font: false +``` + +**Note:** When using `theme.font` in `mkdocs.yml`, `theme.name: material` is required. If `font` is already set in the file, app-config patching does not override it; it only adds `font: false` when `font` was not configured. + #### Default Plugins `techdocs.generator.mkdocs.defaultPlugins` diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index e8b1304115..9b4ec586d0 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -549,14 +549,15 @@ on how you have configured your `template.yaml`. Done! You now have support for TechDocs in your own software template! -### Prevent download of Google fonts +### Disable external fonts -If your Backstage instance does not have internet access, the generation will fail. TechDocs tries to download the Roboto font from Google. You can disable it by configuring your `app-config.yaml` or by manually updating your `mkdocs.yml` file. +`techdocs.generator.mkdocs.disableExternalFonts` -#### Using app-config +(Optional) Use this when the generator cannot reach the internet (for example air-gapped or restricted networks). MkDocs Material otherwise tries to download the Roboto font from Google during generation. -Add the following configuration to your `app-config.yaml` to automatically -disable external font downloads for all TechDocs sites: +When `true`, TechDocs patches each `mkdocs.yml` during generation: if no `theme` section exists it adds `name: material` and `font: false`; if a `theme` exists but `font` is omitted, it sets `font: false`; if `font` is already set in the file, your value is left unchanged. + +**Example:** ```yaml techdocs: @@ -565,17 +566,7 @@ techdocs: disableExternalFonts: true ``` -This configuration will automatically patch the `mkdocs.yml` file during the -generation process. If no `theme` section exists, it will create one with `name: -material` and `font: false`. If a `theme` section exists but `font` is not -configured, it will add `font: false` to the existing theme. If `font` is -already explicitly configured in your `mkdocs.yml`, the patcher will respect -your file-level configuration and not override it. - -#### Manual configuration in mkdocs.yml - -Alternatively, you can manually add the following configuration to your `mkdocs.yml` -file: +Alternatively, configure `mkdocs.yml` manually: ```yaml theme: @@ -583,15 +574,7 @@ theme: font: false ``` -:::note Note - -The addition `name: material` is necessary. Otherwise it will not work. - -If you explicitly set `font: true` or `font: false` in your `mkdocs.yml`, the -app-config patcher will respect that setting and not override it. The patcher -only adds `font: false` when the `font` property is not already configured. - -::: +**Note:** When using `theme.font` in `mkdocs.yml`, `theme.name: material` is required. If `font` is already set in the file, app-config patching does not override it; it only adds `font: false` when `font` was not configured. #### Using techdocs-cli in CI/CD diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 23eeaaa20e..ee4a07bf3c 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -491,8 +491,14 @@ docs_dir: docs theme: name: material font: false +`, + 'mkdocs_with_theme_non_material.yml': `site_name: Test Site +docs_dir: docs +theme: + name: test-theme `, }); + mockLogger.debug.mockClear(); }); it('should create theme section with font disabled when no theme exists', async () => { @@ -562,6 +568,18 @@ theme: expect(parsedYml.theme?.name).toBe('material'); expect(parsedYml.theme?.font).toBe(false); }); + + it('should not patch when theme name is not material', async () => { + const fixturePath = mockDir.resolve('mkdocs_with_theme_non_material.yml'); + const before = await fs.readFile(fixturePath, 'utf8'); + + await patchMkdocsYmlWithFontDisabled(fixturePath, mockLogger); + + await expect(fs.readFile(fixturePath, 'utf8')).resolves.toEqual(before); + expect(mockLogger.debug).toHaveBeenCalledWith( + 'mkdocs.yml theme is not "material"; skipping font disabling patch', + ); + }); }); describe('patchIndexPreBuild', () => { diff --git a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts index 28c5928de6..4ba0040086 100644 --- a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts +++ b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts @@ -27,15 +27,21 @@ import { LoggerService } from '@backstage/backend-plugin-api'; const MATERIAL_THEME = 'material'; +type MkDocsThemeObject = { + name?: string; + font?: boolean; +}; + +function isThemeObject(theme: unknown): theme is MkDocsThemeObject { + return typeof theme === 'object' && theme !== null && !Array.isArray(theme); +} + type MkDocsObject = { plugins?: string[]; docs_dir: string; repo_url?: string; edit_uri?: string; - theme?: { - name?: string; - font?: boolean; - }; + theme?: MkDocsThemeObject; }; const patchMkdocsFile = async ( @@ -210,25 +216,18 @@ export const patchMkdocsYmlWithFontDisabled = async ( return true; } - // Theme section exists. Only modify it when the configured theme is Material - if ( - mkdocsYml.theme && - typeof mkdocsYml.theme === 'object' && - (mkdocsYml.theme as any).name === MATERIAL_THEME && - !('font' in mkdocsYml.theme) - ) { - mkdocsYml.theme.font = false; - return true; - } - - if ( - mkdocsYml.theme && - typeof mkdocsYml.theme === 'object' && - (mkdocsYml.theme as any).name !== MATERIAL_THEME - ) { - logger.debug( - 'mkdocs.yml theme is not "material"; skipping font disabling patch', - ); + const theme = mkdocsYml.theme; + if (isThemeObject(theme)) { + // Theme section exists. Only modify it when the configured theme is Material + if (theme.name === MATERIAL_THEME && !('font' in theme)) { + theme.font = false; + return true; + } + if (theme.name !== MATERIAL_THEME) { + logger.debug( + 'mkdocs.yml theme is not "material"; skipping font disabling patch', + ); + } } return false;