Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions docs/content/3.advanced/2.content.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ relatedPages:

Nuxt Robots comes with an integration for Nuxt Content that allows you to configure robots straight from your markdown directly.

The integration needs Nuxt Content v3. Nuxt Robots v7 does not support Nuxt Content v2.

## Setup Nuxt Content v3

Add `defineRobotsSchema()`{lang="ts"} to your collection's schema to enable the `robots` frontmatter key.
Expand Down Expand Up @@ -93,17 +95,6 @@ useRobotsRule(page.value?.robots ?? undefined)

See [Usage](#usage) for the values the `robots` key accepts.

## Setup Nuxt Content v2

In Nuxt Content v2 markdown files require either [Document Driven Mode](https://content.nuxt.com/document-driven/introduction) or a `path` key to be set
in the frontmatter.

```md [content/foo.md]
---
path: /foo
---
```

## Usage

You can use any boolean or string value as `robots` that will be forwarded as a
Expand Down
18 changes: 2 additions & 16 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export default defineNuxtModule<ModuleOptions>({
version: '>=5.0.0',
},
'@nuxt/content': {
version: '>=2',
version: '>=3',
optional: true,
},
'@harlan-zw/comark-content': {
Expand Down Expand Up @@ -470,11 +470,9 @@ export default defineNuxtModule<ModuleOptions>({
const nitroPreset = resolveNitroPreset(nuxt.options.nitro)
const contentProvider = await resolveContentProvider(nuxt)
const isNuxtContentV3 = contentProvider._tag === 'NuxtContent' && contentProvider.version === 3
let isNuxtContentV2 = !config.disableNuxtContentIntegration && contentProvider._tag === 'NuxtContent' && contentProvider.version === 2
const isComarkContent = contentProvider._tag === 'Comark'
// comark-content fires the same build hook with the same context shape, so the
// frontmatter mapping is identical. It reads Markdown into Nitro server assets
// rather than a database, so unlike Nuxt Content v2 it needs no Cloudflare opt out.
// frontmatter mapping is identical.
if (!config.disableNuxtContentIntegration && (isNuxtContentV3 || isComarkContent)) {
nuxt.hooks.hook('content:file:afterParse' as any, (ctx: FileAfterParseHook) => {
if (ctx.content.robots != null) {
Expand All @@ -491,10 +489,6 @@ export default defineNuxtModule<ModuleOptions>({
}
})
}
else if (isNuxtContentV2 && nitroPreset.startsWith('cloudflare')) {
logger.warn('The Nuxt Robots, Nuxt Content integration does not work with CloudFlare yet, the integration will be disabled. Learn more at: https://nuxtseo.com/docs/robots/guides/content')
isNuxtContentV2 = false
}

nuxt.hook('nitro:build:public-assets', (nitro: any) => {
nitro.hooks.hook('close', async () => {
Expand Down Expand Up @@ -608,7 +602,6 @@ export default defineNuxtModule<ModuleOptions>({

const robotsRuntimeConfig: NuxtRobotsRuntimeConfig = {
version: version || '',
isNuxtContentV2,
debug: config.debug,
credits: config.credits,
groups,
Expand Down Expand Up @@ -667,13 +660,6 @@ export default defineNitroPlugin((nitroApp) => {
}).filename)
}

if (isNuxtContentV2) {
addServerHandler({
route: '/__robots__/nuxt-content.json',
handler: resolve('./runtime/server/routes/__robots__/nuxt-content-v2'),
})
}

if (config.debug || nuxt.options.dev) {
addServerHandler({
route: '/__robots__/debug.json',
Expand Down
17 changes: 3 additions & 14 deletions src/runtime/server/composables/getPathRobotConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function parseRuntimeI18nConfig(input: unknown): RuntimeI18nConfig | null {
export function getPathRobotConfig(e: RequestEvent, options?: { userAgent?: string, skipSiteIndexable?: boolean, path?: string }): RobotsContext {
const runtimeConfig = useRuntimeConfig()
// has already been resolved
const { robotsDisabledValue, robotsEnabledValue, isNuxtContentV2 } = useRuntimeConfigNuxtRobots(e)
const { robotsDisabledValue, robotsEnabledValue } = useRuntimeConfigNuxtRobots(e)
if (!options?.skipSiteIndexable) {
if (!getSiteRobotConfig(e).indexable) {
return {
Expand Down Expand Up @@ -108,18 +108,7 @@ export function getPathRobotConfig(e: RequestEvent, options?: { userAgent?: stri
}
}

// 2. nuxt content rules
if (isNuxtContentV2 && nitroApp._robots?.nuxtContentUrls?.has(withoutTrailingSlash(path))) {
return {
indexable: false,
rule: robotsDisabledValue,
debug: {
source: 'Nuxt Content',
},
}
}

// 3. nitro route rules
// 2. nitro route rules
const baseURL = runtimeConfig.app.baseURL
const matchRules = (pathOrUrl: string) => matchRouteRules(withoutBase(withoutTrailingSlash((pathOrUrl.startsWith('/') ? pathOrUrl : parseURL(pathOrUrl, baseURL).pathname).split('?')[0]!), baseURL))
let robotRouteRules = matchRules(path)
Expand All @@ -145,7 +134,7 @@ export function getPathRobotConfig(e: RequestEvent, options?: { userAgent?: stri
},
}
}
// 4. page meta robots
// 3. page meta robots
const pagePath = withoutBase(parseURL(path).pathname || '/', runtimeConfig.app.baseURL)
const pageMetaRule = pageMetaMatchers.find((page: { re: RegExp }) => page.re.test(pagePath))?.robots
if (typeof pageMetaRule !== 'undefined') {
Expand Down
20 changes: 1 addition & 19 deletions src/runtime/server/plugins/initContext.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { createPatternMap } from '@nuxtjs/robots/util'
import { getRouteRules } from 'nuxt/server'
import { withoutTrailingSlash } from 'ufo'
// @ts-expect-error Virtual server template registered by the module.
import { ROBOTS_SSR_DEFAULT } from '#nuxt-robots/ssr-default.mjs'
import { defineNitroPlugin } from '#nuxtseo/nitro'
import { useRuntimeConfigNuxtRobots } from '../composables/useRuntimeConfigNuxtRobots'
import { logger } from '../logger'
import { resolveRobotsTxtContext } from '../util'

const PRERENDER_NO_SSR_ROUTES = new Set(['/index.html', '/200.html', '/404.html'])

// we need to init our state using a nitro plugin so the user doesn't throttle the resolve context hook
// important when we integrate with nuxt-simple-sitemap and we're checking thousands of URLs
export default defineNitroPlugin(async (nitroApp) => {
const { isNuxtContentV2, robotsDisabledValue, botDetection } = useRuntimeConfigNuxtRobots()
const { robotsDisabledValue, botDetection } = useRuntimeConfigNuxtRobots()

// Initialize bot detection pattern map if enabled
if (botDetection !== false) {
Expand All @@ -22,22 +20,6 @@ export default defineNitroPlugin(async (nitroApp) => {

nitroApp._robots = {} as typeof nitroApp._robots
await resolveRobotsTxtContext(undefined, nitroApp)
const nuxtContentUrls = new Set<string>()
if (isNuxtContentV2) {
let urls: string[] | undefined
try {
urls = await (await nitroApp.localFetch('/__robots__/nuxt-content.json', {})).json()
}
catch (e) {
logger.error('Failed to read robot rules from content files.', e)
}
if (urls && Array.isArray(urls) && urls.length) {
urls.forEach((url: string) => nuxtContentUrls.add(withoutTrailingSlash(url)))
}
}
if (nuxtContentUrls.size) {
nitroApp._robots.nuxtContentUrls = nuxtContentUrls
}

if (import.meta.prerender) {
// need to inject HTML if we have an SPA route
Expand Down
26 changes: 0 additions & 26 deletions src/runtime/server/routes/__robots__/nuxt-content-v2.ts

This file was deleted.

29 changes: 2 additions & 27 deletions src/runtime/server/routes/robots-txt.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import type { HookRobotsConfigContext, HookRobotsTxtContext, RobotsRouteRuleConfig } from '../../types'
import { asArray, generateRobotsTxt, isNoIndexRule, normaliseRobotsRouteRule } from '@nuxtjs/robots/util'
import { createError, defineEventHandler, serverFetch, useRuntimeConfig } from 'nuxt/server'
import { defineEventHandler, useRuntimeConfig } from 'nuxt/server'
import { useNitroApp } from '#nuxtseo/nitro'
import { withSiteUrl } from '#site-config/server'
import { getSiteRobotConfig } from '../composables/getSiteRobotConfig'
import { useRuntimeConfigNuxtRobots } from '../composables/useRuntimeConfigNuxtRobots'
import { logger } from '../logger'
import { resolveRobotsTxtContext } from '../util'

export default defineEventHandler(async (e) => {
const nitroApp = useNitroApp()
const { indexable, hints } = getSiteRobotConfig(e)
const { credits, isNuxtContentV2, cacheControl, robotsDisabledValue } = useRuntimeConfigNuxtRobots(e)
const { credits, cacheControl, robotsDisabledValue } = useRuntimeConfigNuxtRobots(e)
// move towards deprecating indexable
let robotsTxtCtx: Omit<HookRobotsConfigContext, 'context' | 'event'> = {
errors: [],
Expand All @@ -34,30 +33,6 @@ export default defineEventHandler(async (e) => {
// validate sitemaps are absolute
.map(s => !s.startsWith('http') ? withSiteUrl(e, s, { withBase: true, absolute: true }) : s),
)]
if (isNuxtContentV2) {
const contentResponse = await serverFetch(e, '/__robots__/nuxt-content.json', {
headers: {
Accept: 'application/json',
},
})
if (!contentResponse.ok)
throw createError({ status: contentResponse.status, statusText: contentResponse.statusText })
const contentWithRobotRules = await contentResponse.json() as string[]
// ensure it's valid json
if (String(contentWithRobotRules).trim().startsWith('<!DOCTYPE')) {
logger.error('Invalid HTML returned from /__robots__/nuxt-content.json, skipping.')
}
else {
// add to first '*' group
for (const group of robotsTxtCtx.groups) {
if (group.userAgent.includes('*')) {
group.disallow.push(...contentWithRobotRules)
// need to filter out empty strings since we now have some content
group.disallow = group.disallow.filter(Boolean)
}
}
}
}
}
let robotsTxt: string = generateRobotsTxt(robotsTxtCtx)
if (import.meta.dev && hints.length) {
Expand Down
1 change: 0 additions & 1 deletion src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ export interface RobotsContext {

export interface NuxtRobotsRuntimeConfig {
version: string
isNuxtContentV2: boolean
debug: boolean
credits: boolean
groups: RobotsGroupResolved[]
Expand Down
1 change: 0 additions & 1 deletion src/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ robotsProduction?: RobotsContext`,
nitroInterfaces: {
NitroApp: `_robots: {
ctx: HookRobotsConfigContext
nuxtContentUrls?: Set<string>
},
_robotsPatternMap?: Map<string, PatternMapValue>`,
},
Expand Down
Loading