@fullstackdatasolutions/articles 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/nextjs.cjs +5 -20
- package/dist/nextjs.cjs.map +1 -1
- package/dist/nextjs.js +5 -20
- package/dist/nextjs.js.map +1 -1
- package/dist/server.cjs +5 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +5 -3
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/server-articles.test.ts +21 -0
- package/src/server-articles.ts +10 -1
package/package.json
CHANGED
|
@@ -1017,6 +1017,27 @@ describe('AI markdown helpers', () => {
|
|
|
1017
1017
|
expect(blocked.status).toBe(404)
|
|
1018
1018
|
})
|
|
1019
1019
|
|
|
1020
|
+
it('links the markdown twin back to its HTML article, not to itself', async () => {
|
|
1021
|
+
setupArticleTreeMock([
|
|
1022
|
+
{
|
|
1023
|
+
slug: 'allowed',
|
|
1024
|
+
frontmatter: 'date: 2025-01-01\naiCrawl: true\n',
|
|
1025
|
+
body: '# Allowed',
|
|
1026
|
+
},
|
|
1027
|
+
])
|
|
1028
|
+
|
|
1029
|
+
const response = await getArticleMarkdownResponse('allowed', {
|
|
1030
|
+
siteUrl: 'https://example.com/',
|
|
1031
|
+
siteName: 'Example',
|
|
1032
|
+
})
|
|
1033
|
+
|
|
1034
|
+
expect(response.headers.get('Link')).toBe(
|
|
1035
|
+
'<https://example.com/articles/allowed>; rel="canonical"'
|
|
1036
|
+
)
|
|
1037
|
+
expect(response.headers.get('Link')).not.toContain('.md')
|
|
1038
|
+
expect(response.headers.get('Link')).not.toContain('alternate')
|
|
1039
|
+
})
|
|
1040
|
+
|
|
1020
1041
|
it('generates robots rules for AI crawlers and blocked articles only', async () => {
|
|
1021
1042
|
setupArticleTreeMock([
|
|
1022
1043
|
{ slug: 'allowed', frontmatter: 'date: 2025-01-01\naiCrawl: true\n' },
|
package/src/server-articles.ts
CHANGED
|
@@ -775,11 +775,20 @@ export async function getArticleMarkdownResponse(
|
|
|
775
775
|
article && config.markdownTwinHeader !== false
|
|
776
776
|
? `${buildMarkdownTwinHeader(article, config, markdown)}${markdown.trimStart()}`
|
|
777
777
|
: markdown
|
|
778
|
+
// `getArticleAiHeaders` builds a `rel="alternate"` link *to* the twin, which
|
|
779
|
+
// is correct on the HTML page and wrong here - on the twin's own response it
|
|
780
|
+
// pointed at the URL being requested, telling a client the alternate of
|
|
781
|
+
// `/articles/x.md` is `/articles/x.md`. `getArticleMarkdown` already returned
|
|
782
|
+
// null for anything not opted in, so that helper's other branch
|
|
783
|
+
// (`X-Robots-Tag: noai`) was unreachable from this call site anyway. Point
|
|
784
|
+
// back at the HTML article instead, which is the relationship a client
|
|
785
|
+
// fetching the twin actually needs: this is a representation of that page.
|
|
786
|
+
const canonicalUrl = `${config.siteUrl.replace(/\/$/, '')}/articles/${slug}`
|
|
778
787
|
return new Response(body, {
|
|
779
788
|
headers: {
|
|
780
789
|
'Content-Type': 'text/markdown; charset=utf-8',
|
|
781
790
|
'Cache-Control': 'public, max-age=3600, s-maxage=3600',
|
|
782
|
-
|
|
791
|
+
Link: `<${canonicalUrl}>; rel="canonical"`,
|
|
783
792
|
},
|
|
784
793
|
})
|
|
785
794
|
}
|