From b2cee4a6b75476699f1caddef095dca53c07ec5b Mon Sep 17 00:00:00 2001 From: JounQin Date: Wed, 14 Jan 2026 11:35:28 +0800 Subject: [PATCH 1/2] feat: support linting site name usage --- packages/doom/src/remark-lint/index.ts | 1 + packages/doom/src/remark-lint/site.ts | 59 +++++++++++++++++++ packages/doom/src/remarkrc.ts | 2 + .../runtime/components/ExternalSiteLink.tsx | 13 ++-- .../runtime/components/_ExternalSiteBase.tsx | 13 ++-- 5 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 packages/doom/src/remark-lint/site.ts diff --git a/packages/doom/src/remark-lint/index.ts b/packages/doom/src/remark-lint/index.ts index 3c5a2576..63599576 100644 --- a/packages/doom/src/remark-lint/index.ts +++ b/packages/doom/src/remark-lint/index.ts @@ -14,6 +14,7 @@ export * from './no-heading-punctuation.ts' export * from './no-heading-special-characters.ts' export * from './no-heading-sup-sub.ts' export * from './no-paragraph-indent.ts' +export * from './site.ts' export * from './table-size.ts' export * from './unit-case.ts' diff --git a/packages/doom/src/remark-lint/site.ts b/packages/doom/src/remark-lint/site.ts new file mode 100644 index 00000000..554a68d0 --- /dev/null +++ b/packages/doom/src/remark-lint/site.ts @@ -0,0 +1,59 @@ +import path from 'node:path' + +import type { Root } from 'mdast' +import type { MdxJsxAttribute } from 'mdast-util-mdx-jsx' +import { lintRule } from 'unified-lint-rule' +import { visitParents } from 'unist-util-visit-parents' + +import { SITES_FILE } from '../cli/constants.ts' +import type { DoomSite } from '../shared/types.ts' +import { pathExists } from '../utils/fs.ts' +import { resolveStaticConfig } from '../utils/helpers.ts' + +const SITE_ELEMENTS = new Set([ + 'ExternalApisOverview', + 'ExternalSite', + 'ExternalSiteLink', +]) + +const sitesConfigFilePath = path.resolve(SITES_FILE) + +let sites: DoomSite[] | undefined + +export const site = lintRule('doom:lint-site', async (root, vfile) => { + if (!sites) { + if (await pathExists(sitesConfigFilePath, 'file')) { + sites = await resolveStaticConfig(sitesConfigFilePath) + } else { + sites = [] + } + } + + visitParents(root, 'mdxJsxFlowElement', (element, parents) => { + if (!sites?.length || !element.name || !SITE_ELEMENTS.has(element.name)) { + return + } + + const nameAttr = element.attributes.find( + (attr): attr is MdxJsxAttribute => + attr.type === 'mdxJsxAttribute' && attr.name === 'name', + ) + + const nameVal = nameAttr?.value + + if ( + typeof nameVal === 'string' && + sites.some((site) => site.name === nameVal) + ) { + return + } + + vfile.message( + `Invalid site \`name\` property value \`${typeof nameVal === 'string' ? nameVal : nameVal?.value}\` which should be static string matching a site name from \`${SITES_FILE}\` config.`, + { + ancestors: [...parents, element], + place: (nameAttr ?? element).position, + }, + ) + }) +}) diff --git a/packages/doom/src/remarkrc.ts b/packages/doom/src/remarkrc.ts index 90e1b1fe..eb0ffbdd 100644 --- a/packages/doom/src/remarkrc.ts +++ b/packages/doom/src/remarkrc.ts @@ -16,6 +16,7 @@ import doomLint, { noDeepHeading, noDeepList, noParagraphIndent, + site, tableSize, unitCase, } from './remark-lint/index.ts' @@ -36,6 +37,7 @@ export default { noDeepHeading, noDeepList, noParagraphIndent, + site, tableSize, unitCase, ], diff --git a/packages/doom/src/runtime/components/ExternalSiteLink.tsx b/packages/doom/src/runtime/components/ExternalSiteLink.tsx index 5860fb39..99166ee0 100644 --- a/packages/doom/src/runtime/components/ExternalSiteLink.tsx +++ b/packages/doom/src/runtime/components/ExternalSiteLink.tsx @@ -1,4 +1,4 @@ -import { useLang, useSite } from '@rspress/core/runtime' +import { isProduction, useLang, useSite } from '@rspress/core/runtime' import { addTrailingSlash, isExternalUrl, @@ -38,12 +38,11 @@ const ExternalSiteLink_ = ({ const lang = useLang() if (!site) { - return ( - - No site with name `{name}` found, please ensure it's already defined at - `sites.yaml` - - ) + const message = `No site with name \`${name}\` found, please ensure it's already defined at \`sites.yaml\`` + if (isProduction()) { + throw new Error(message) + } + return {message} } if (isExternalUrl(href)) { diff --git a/packages/doom/src/runtime/components/_ExternalSiteBase.tsx b/packages/doom/src/runtime/components/_ExternalSiteBase.tsx index 3e66855b..235ff8d1 100644 --- a/packages/doom/src/runtime/components/_ExternalSiteBase.tsx +++ b/packages/doom/src/runtime/components/_ExternalSiteBase.tsx @@ -1,4 +1,4 @@ -import { useLang } from '@rspress/core/runtime' +import { isProduction, useLang } from '@rspress/core/runtime' import virtual from 'doom-@global-virtual' import { type FC, useMemo } from 'react' @@ -107,12 +107,11 @@ export const ExternalSiteBase = ({ name, template }: ExternalSiteBaseProps) => { ) if (!site) { - return ( - - No site with name `{name}` found, please ensure it's already defined at - `sites.yaml` - - ) + const message = `No site with name \`${name}\` found, please ensure it's already defined at \`sites.yaml\`` + if (isProduction()) { + throw new Error(message) + } + return {message} } const Notes = template === 'apisOverview' ? ApisOverviewNotes : SiteNotes From c2fd5d3649fbd90c1ae3120315e7d175e360fed8 Mon Sep 17 00:00:00 2001 From: JounQin Date: Wed, 14 Jan 2026 11:37:08 +0800 Subject: [PATCH 2/2] Create lucky-wolves-whisper.md Signed-off-by: JounQin --- .changeset/lucky-wolves-whisper.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-wolves-whisper.md diff --git a/.changeset/lucky-wolves-whisper.md b/.changeset/lucky-wolves-whisper.md new file mode 100644 index 00000000..025c77ac --- /dev/null +++ b/.changeset/lucky-wolves-whisper.md @@ -0,0 +1,5 @@ +--- +"@alauda/doom": patch +--- + +feat: support linting site name usage