diff --git a/index.ts b/index.ts index 4147a53b..c816b3cd 100644 --- a/index.ts +++ b/index.ts @@ -4,8 +4,7 @@ import { UserConfigSchema, type UserConfig } from "./src/utils/UserConfigSchema" import { ghostSitemap, ghostRobots } from "./src/integrations"; import { loadEnv } from 'vite'; import { fromZodError } from "zod-validation-error"; -import sitemap from '@astrojs/sitemap'; -import robotsTxt from "astro-robots-txt"; +import { viteGhostCMS } from "./src/utils/virtual-imports"; // LOAD ENVIRONMENT VARIABLES const mode = 'all'; @@ -16,13 +15,10 @@ const env = loadEnv(mode, process.cwd(), prefixes); const pkg = '@matthiesenxyz/astro-ghostcms'; export default function GhostCMS(options: UserConfig): AstroIntegration { - let UserConfig:UserConfig return { name: pkg, hooks: { 'astro:config:setup': async ({ - command, - isRestart, injectRoute, config, updateConfig, @@ -49,6 +45,7 @@ export default function GhostCMS(options: UserConfig): AstroIntegration { throw validationError; } const entry = o.data.theme; + const uconf = o.data; // THEME SELECTOR if (entry === pkg) { @@ -109,7 +106,7 @@ export default function GhostCMS(options: UserConfig): AstroIntegration { logger.info("Checking for @astrojs/sitemap"); if (!int.find(({ name }) => name === '@astrojs/sitemap')) { logger.info("Injecting Integration: @astrojs/sitemap"); - int.push(sitemap()); + int.push(ghostSitemap(uconf)); } else { logger.info("Already Imported by User: @astrojs/sitemap"); } @@ -118,18 +115,22 @@ export default function GhostCMS(options: UserConfig): AstroIntegration { logger.info("Checking for astro-robots-txt"); if (!int.find(({ name }) => name === 'astro-robots-txt')) { logger.info("Injecting Integration: astro-robots-txt"); - int.push(robotsTxt()); + int.push(ghostRobots(uconf)); } else { logger.info("Already Imported by User: astro-robots-txt"); } - - try { - updateConfig({ - integrations: [sitemap(),robotsTxt()] - }) - } catch (e) { + try { updateConfig({ + integrations: [ + ghostSitemap(uconf), + ghostRobots(uconf) + ], + vite: { + plugins: [ + viteGhostCMS(uconf,config) + ] + } }) } catch (e) { logger.error(e as string) - throw e + throw e } }, diff --git a/package.json b/package.json index 02385a2d..289339bd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@matthiesenxyz/astro-ghostcms", "description": "Astro GhostCMS integration to allow easier importing of GhostCMS Content", - "version": "2.1.1", + "version": "2.1.2", "author": "MatthiesenXYZ (https://matthiesen.xyz)", "type": "module", "license": "MIT", diff --git a/src/integrations/robots-txt.ts b/src/integrations/robots-txt.ts index ea822374..fff20c9c 100644 --- a/src/integrations/robots-txt.ts +++ b/src/integrations/robots-txt.ts @@ -1,13 +1,27 @@ import robotsTxt, { type RobotsTxtOptions } from "astro-robots-txt"; +import { UserConfig } from "../utils/UserConfigSchema"; -export function getRobotsTxtConfig(): RobotsTxtOptions { +export function getRobotsTxtConfig(opts: UserConfig): RobotsTxtOptions { + const { robotstxt } = opts; const robotsConfig: RobotsTxtOptions = {}; + if (robotstxt?.host) { + robotsConfig.host = robotstxt.host; + } + if (robotstxt?.policy) { + robotsConfig.policy = robotstxt.policy; + } + if (robotstxt?.sitemap) { + robotsConfig.sitemap = robotstxt.sitemap; + } + if (robotstxt?.sitemapBaseFileName) { + robotsConfig.sitemapBaseFileName = robotstxt.sitemapBaseFileName; + } return robotsConfig; } /** * A wrapped version of the `astro-robots-txt` integration for GhostCMS. */ -export default function ghostRobots() { - return robotsTxt(getRobotsTxtConfig()); +export default function ghostRobots(opts: UserConfig) { + return robotsTxt(getRobotsTxtConfig(opts)); } \ No newline at end of file diff --git a/src/integrations/sitemap.ts b/src/integrations/sitemap.ts index db61c4c7..20697e62 100644 --- a/src/integrations/sitemap.ts +++ b/src/integrations/sitemap.ts @@ -1,13 +1,21 @@ import sitemap, { type SitemapOptions } from '@astrojs/sitemap'; +import { UserConfig } from '../utils/UserConfigSchema'; -export function getSitemapConfig(): SitemapOptions { +export function getSitemapConfig(opts: UserConfig): SitemapOptions { + const { sitemap } = opts const sitemapConfig: SitemapOptions = {}; + if (sitemap?.entryLimit){ + sitemapConfig.entryLimit = sitemap.entryLimit; + } + if (sitemap?.customPages){ + sitemapConfig.customPages = sitemap.customPages; + } return sitemapConfig; } /** * A wrapped version of the `@astrojs/sitemap` integration for GhostCMS. */ -export default function ghostSitemap() { - return sitemap(getSitemapConfig()); +export default function ghostSitemap(opts: UserConfig) { + return sitemap(getSitemapConfig(opts)); } \ No newline at end of file diff --git a/src/routes/rss.xml.js b/src/routes/rss.xml.js index 828f0293..cd3b48db 100644 --- a/src/routes/rss.xml.js +++ b/src/routes/rss.xml.js @@ -12,7 +12,6 @@ export async function GET(context) { title: title, description: description, site: context.site, - //stylesheet: '/rss/styles.xsl', items: posts.map((post) => ({ title: post.title, pubDate: post.published_at, diff --git a/src/styles/rss.xsl b/src/styles/rss.xsl deleted file mode 100644 index 7fdf8788..00000000 --- a/src/styles/rss.xsl +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - <xsl:value-of select="/rss/channel/title"/> Blog Feed - - - - - - - -
-
-

- - -

-

- - - - - Visit Website → - -
-

Recent Blog Posts

- -
-

- - - - - - -

- - Published: - -

- -

-
-
-
- - -
-
\ No newline at end of file diff --git a/src/utils/UserConfigSchema.ts b/src/utils/UserConfigSchema.ts index bc920848..fe6fcdf2 100644 --- a/src/utils/UserConfigSchema.ts +++ b/src/utils/UserConfigSchema.ts @@ -1,8 +1,10 @@ import { z } from 'astro/zod'; +import * as S from './schemas'; export const UserConfigSchema = z.object({ theme: z.string().default('@matthiesenxyz/astro-ghostcms'), - rssStyle: z.string().optional() + sitemap: S.SitemapSchema.optional(), + robotstxt: S.RobotsTxtSchema.optional(), }); export type UserConfig = z.infer \ No newline at end of file diff --git a/src/utils/schemas.ts b/src/utils/schemas.ts new file mode 100644 index 00000000..d75dc5dc --- /dev/null +++ b/src/utils/schemas.ts @@ -0,0 +1,21 @@ +import { z } from 'astro/zod'; + +export const SitemapSchema = z.object({ + customPages: z.string().array().optional(), + entryLimit: z.number().optional() +}) + +const RobotsPolicySchema = z.object({ + userAgent: z.string(), + allow: z.string().optional(), + disallow: z.string().optional(), + cleanParam: z.string().optional(), + crawlDelay: z.number() +}) + +export const RobotsTxtSchema = z.object({ + host: z.string().optional(), + sitemap: z.string().optional(), + sitemapBaseFileName: z.string().optional(), + policy: RobotsPolicySchema.array().optional(), +}) diff --git a/src/utils/virtual-imports.ts b/src/utils/virtual-imports.ts new file mode 100644 index 00000000..ef3679bd --- /dev/null +++ b/src/utils/virtual-imports.ts @@ -0,0 +1,44 @@ +import type { AstroConfig, ViteUserConfig } from 'astro' +import { resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { UserConfig } from './UserConfigSchema' + +function resolveVirtualModuleId(id: T): `\0${T}` { + return `\0${id}` +} + +export function viteGhostCMS( + opts: UserConfig, + { + root, + }: Pick & { + build: Pick + } +): NonNullable[number] { + const resolveId = (id: string) => + JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(root), id) : id); + + const modules = { + 'virtual:@matthiesenxyz/astro-ghostcms/user-config': `export default ${ JSON.stringify(opts) }` + } satisfies Record + + /** Mapping names prefixed with `\0` to their original form. */ + const resolutionMap = Object.fromEntries( + (Object.keys(modules) as (keyof typeof modules)[]).map((key) => [ + resolveVirtualModuleId(key), + key, + ]) + ) + + return { + name: 'vite-plugin-matthiesenxyz-astro-ghostcms-user-config', + resolveId(id): string | void { + if (id in modules) return resolveVirtualModuleId(id) + }, + load(id): string | void { + const resolution = resolutionMap[id] + if (resolution) return modules[resolution] + }, + } +} \ No newline at end of file diff --git a/src/utils/virtual.d.ts b/src/utils/virtual.d.ts new file mode 100644 index 00000000..4e6aa013 --- /dev/null +++ b/src/utils/virtual.d.ts @@ -0,0 +1,4 @@ +declare module 'virtual:@matthiesenxyz/astro-ghostcms/user-config' { + const Config: import('./UserConfigSchema').UserConfig; + export default Config; +} \ No newline at end of file