Skip to content

Commit 9c2540b

Browse files
committed
Sitemap fixes
1 parent d980d53 commit 9c2540b

4 files changed

Lines changed: 100 additions & 4 deletions

File tree

astro.config.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { testimonialsLengthWarning } from './src/integrations/TestimonialsLength
3535
import { fixContentAssetPropagation } from './src/lib/plugins/fixContentAssetPropagation'
3636
import { pwaDevAssetServer } from './src/lib/plugins/pwaDevAssetServer'
3737
import { createSerializeFunction, pagesJsonWriter } from './src/integrations/sitemapSerialize'
38+
import { getDeepDiveArticleAliasPaths } from './src/integrations/sitemapSerialize/deepDiveAliases'
3839

3940
// Ensure Vite's HMR websocket connects through the same exposed dev server port used by Astro.
4041
const devServerPort = Number(process.env['DEV_SERVER_PORT'] ?? 4321)
@@ -44,6 +45,7 @@ const shouldEnableSentryIntegration = Boolean(sentryAuthToken)
4445
const sentryReleaseName = getPackageRelease()
4546
const astroEnvConfig = environmentalVariablesConfig as NonNullable<AstroUserConfig['env']>
4647
const astroMarkdownConfig = markdownConfig as unknown as NonNullable<AstroUserConfig['markdown']>
48+
const deepDiveArticleAliasPaths = getDeepDiveArticleAliasPaths()
4749

4850
const shouldSuppressViteWarning = (message: string): boolean => {
4951
return (
@@ -104,7 +106,18 @@ const standardIntegrations = [
104106
})] : []),
105107
sitemap({
106108
serialize: createSerializeFunction({
107-
exclude: ['deep-dive', 'downloads', 'print', '/articles/demo', 'testing', 'hero', 'links'],
109+
exclude: [
110+
'downloads',
111+
'offline',
112+
'print',
113+
'/articles/demo',
114+
'search',
115+
'tags',
116+
'testing',
117+
'hero',
118+
'links',
119+
...deepDiveArticleAliasPaths,
120+
],
108121
}),
109122
}),
110123
/**
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs'
2+
import { join } from 'node:path'
3+
import { tmpdir } from 'node:os'
4+
import { afterEach, describe, expect, it, vi } from 'vitest'
5+
import {
6+
getDeepDiveArticleAliasPaths,
7+
normalizeDeepDiveEntryId,
8+
} from '../deepDiveAliases'
9+
10+
describe('deepDiveAliases', () => {
11+
afterEach(() => {
12+
vi.restoreAllMocks()
13+
})
14+
15+
it('normalizes deep-dive pdf entries to route ids', () => {
16+
expect(normalizeDeepDiveEntryId('platform-architecture/pdf.mdx')).toBe('platform-architecture')
17+
expect(normalizeDeepDiveEntryId('nested/guide/pdf.mdx')).toBe('nested/guide')
18+
expect(normalizeDeepDiveEntryId('nested\\guide\\pdf.mdx')).toBe('nested/guide')
19+
})
20+
21+
it('returns article alias paths for deep-dive pdf files', () => {
22+
const contentRoot = mkdtempSync(join(tmpdir(), 'deep-dive-aliases-'))
23+
24+
mkdirSync(join(contentRoot, 'first-article'), { recursive: true })
25+
mkdirSync(join(contentRoot, 'nested', 'second-article'), { recursive: true })
26+
mkdirSync(join(contentRoot, 'ignored'), { recursive: true })
27+
28+
writeFileSync(join(contentRoot, 'first-article', 'pdf.mdx'), '---\ntitle: First\n---')
29+
writeFileSync(join(contentRoot, 'nested', 'second-article', 'pdf.mdx'), '---\ntitle: Second\n---')
30+
writeFileSync(join(contentRoot, 'ignored', 'index.mdx'), '---\ntitle: Ignored\n---')
31+
32+
expect(getDeepDiveArticleAliasPaths({ contentRoot })).toEqual([
33+
'/articles/first-article',
34+
'/articles/nested/second-article',
35+
])
36+
})
37+
})
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { readdirSync } from 'node:fs'
2+
import { relative, join } from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
5+
const deepDiveContentRoot = fileURLToPath(new URL('../../content/articles', import.meta.url))
6+
7+
export interface DeepDiveAliasOptions {
8+
contentRoot?: string
9+
}
10+
11+
export function getDeepDiveArticleAliasPaths(
12+
options: DeepDiveAliasOptions = {}
13+
): string[] {
14+
const contentRoot = options.contentRoot ?? deepDiveContentRoot
15+
const pdfEntries = collectDeepDiveEntries(contentRoot)
16+
17+
return pdfEntries
18+
.map(entryPath => `/articles/${normalizeDeepDiveEntryId(entryPath)}`)
19+
.sort((left, right) => left.localeCompare(right))
20+
}
21+
22+
export function normalizeDeepDiveEntryId(entryPath: string): string {
23+
const normalizedEntry = entryPath.replace(/\\/g, '/')
24+
const withoutExtension = normalizedEntry.replace(/\.[^/.]+$/, '')
25+
26+
return withoutExtension.endsWith('/pdf')
27+
? withoutExtension.slice(0, -'/pdf'.length)
28+
: withoutExtension
29+
}
30+
31+
function collectDeepDiveEntries(contentRoot: string, currentDir = contentRoot): string[] {
32+
const entries = readdirSync(currentDir, { withFileTypes: true })
33+
const deepDiveEntries: string[] = []
34+
35+
for (const entry of entries) {
36+
const entryPath = join(currentDir, entry.name)
37+
38+
if (entry.isDirectory()) {
39+
deepDiveEntries.push(...collectDeepDiveEntries(contentRoot, entryPath))
40+
continue
41+
}
42+
43+
if (entry.isFile() && entry.name === 'pdf.mdx') {
44+
deepDiveEntries.push(relative(contentRoot, entryPath))
45+
}
46+
}
47+
48+
return deepDiveEntries
49+
}

src/pages/robots.txt.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ const getRobotsTxt = (sitemapURL: URL) => `\
44
User-agent: *
55
Allow: /
66
Disallow: /downloads/
7-
Disallow: /articles$
8-
Disallow: /case-studies$
9-
Disallow: /deep-dive$
107
Disallow: /offline
118
Disallow: /print
129
Disallow: /search

0 commit comments

Comments
 (0)