mirror of
https://github.com/jackyzha0/quartz.git
synced 2026-03-21 21:45:42 -05:00
feat: add PageTypePluginEntry for cross-boundary type compatibility
Introduce PageTypePluginEntry with never[] parameter types to accept both internal and community PageType plugins in config arrays without casts, working around branded FullSlug contravariance mismatch.
This commit is contained in:
parent
68f3c3fadd
commit
fd36066fdf
@ -2,7 +2,7 @@ import {
|
|||||||
QuartzTransformerPluginInstance,
|
QuartzTransformerPluginInstance,
|
||||||
QuartzFilterPluginInstance,
|
QuartzFilterPluginInstance,
|
||||||
QuartzEmitterPluginInstance,
|
QuartzEmitterPluginInstance,
|
||||||
QuartzPageTypePluginInstance,
|
PageTypePluginEntry,
|
||||||
} from "./types"
|
} from "./types"
|
||||||
import { LoadedPlugin } from "./loader/types"
|
import { LoadedPlugin } from "./loader/types"
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ export interface PluginConfiguration {
|
|||||||
transformers: (QuartzTransformerPluginInstance | LoadedPlugin)[]
|
transformers: (QuartzTransformerPluginInstance | LoadedPlugin)[]
|
||||||
filters: (QuartzFilterPluginInstance | LoadedPlugin)[]
|
filters: (QuartzFilterPluginInstance | LoadedPlugin)[]
|
||||||
emitters: (QuartzEmitterPluginInstance | LoadedPlugin)[]
|
emitters: (QuartzEmitterPluginInstance | LoadedPlugin)[]
|
||||||
pageTypes?: (QuartzPageTypePluginInstance | LoadedPlugin)[]
|
pageTypes?: (PageTypePluginEntry | LoadedPlugin)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLoadedPlugin(plugin: unknown): plugin is LoadedPlugin {
|
export function isLoadedPlugin(plugin: unknown): plugin is LoadedPlugin {
|
||||||
@ -29,14 +29,14 @@ export function getPluginInstance<T extends object | undefined>(
|
|||||||
| QuartzTransformerPluginInstance
|
| QuartzTransformerPluginInstance
|
||||||
| QuartzFilterPluginInstance
|
| QuartzFilterPluginInstance
|
||||||
| QuartzEmitterPluginInstance
|
| QuartzEmitterPluginInstance
|
||||||
| QuartzPageTypePluginInstance
|
| PageTypePluginEntry
|
||||||
| LoadedPlugin,
|
| LoadedPlugin,
|
||||||
options?: T,
|
options?: T,
|
||||||
):
|
):
|
||||||
| QuartzTransformerPluginInstance
|
| QuartzTransformerPluginInstance
|
||||||
| QuartzFilterPluginInstance
|
| QuartzFilterPluginInstance
|
||||||
| QuartzEmitterPluginInstance
|
| QuartzEmitterPluginInstance
|
||||||
| QuartzPageTypePluginInstance {
|
| PageTypePluginEntry {
|
||||||
if (isLoadedPlugin(plugin)) {
|
if (isLoadedPlugin(plugin)) {
|
||||||
const factory = plugin.plugin as (
|
const factory = plugin.plugin as (
|
||||||
opts?: T,
|
opts?: T,
|
||||||
@ -44,7 +44,7 @@ export function getPluginInstance<T extends object | undefined>(
|
|||||||
| QuartzTransformerPluginInstance
|
| QuartzTransformerPluginInstance
|
||||||
| QuartzFilterPluginInstance
|
| QuartzFilterPluginInstance
|
||||||
| QuartzEmitterPluginInstance
|
| QuartzEmitterPluginInstance
|
||||||
| QuartzPageTypePluginInstance
|
| PageTypePluginEntry
|
||||||
return factory(options)
|
return factory(options)
|
||||||
}
|
}
|
||||||
return plugin
|
return plugin
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { PluggableList } from "unified"
|
|||||||
import { StaticResources } from "../util/resources"
|
import { StaticResources } from "../util/resources"
|
||||||
import { ProcessedContent, QuartzPluginData } from "./vfile"
|
import { ProcessedContent, QuartzPluginData } from "./vfile"
|
||||||
import { QuartzComponent, QuartzComponentConstructor } from "../components/types"
|
import { QuartzComponent, QuartzComponentConstructor } from "../components/types"
|
||||||
import { FilePath, FullSlug } from "../util/path"
|
import { FilePath } from "../util/path"
|
||||||
import { BuildCtx } from "../util/ctx"
|
import { BuildCtx } from "../util/ctx"
|
||||||
import { GlobalConfiguration } from "../cfg"
|
import { GlobalConfiguration } from "../cfg"
|
||||||
import { VFile } from "vfile"
|
import { VFile } from "vfile"
|
||||||
@ -11,7 +11,7 @@ export interface PluginTypes {
|
|||||||
transformers: QuartzTransformerPluginInstance[]
|
transformers: QuartzTransformerPluginInstance[]
|
||||||
filters: QuartzFilterPluginInstance[]
|
filters: QuartzFilterPluginInstance[]
|
||||||
emitters: QuartzEmitterPluginInstance[]
|
emitters: QuartzEmitterPluginInstance[]
|
||||||
pageTypes?: QuartzPageTypePluginInstance[]
|
pageTypes?: PageTypePluginEntry[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type OptionType = object | undefined
|
type OptionType = object | undefined
|
||||||
@ -70,62 +70,50 @@ export type QuartzEmitterPluginInstance = {
|
|||||||
// PageType Plugin Types
|
// PageType Plugin Types
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher function: determines if a source file belongs to a page type.
|
|
||||||
* Returns true if the page type should own this file.
|
|
||||||
*/
|
|
||||||
export type PageMatcher = (args: {
|
export type PageMatcher = (args: {
|
||||||
slug: FullSlug
|
slug: string
|
||||||
fileData: QuartzPluginData
|
fileData: QuartzPluginData
|
||||||
cfg: GlobalConfiguration
|
cfg: GlobalConfiguration
|
||||||
|
[key: string]: unknown
|
||||||
}) => boolean
|
}) => boolean
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual page descriptor for page types that generate pages
|
|
||||||
* from aggregated data (e.g., tag indexes, folder listings).
|
|
||||||
*/
|
|
||||||
export interface VirtualPage {
|
export interface VirtualPage {
|
||||||
slug: FullSlug
|
slug: string
|
||||||
title: string
|
title: string
|
||||||
data: Partial<QuartzPluginData>
|
data: Partial<QuartzPluginData> & Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generator function: produces virtual pages from all processed content.
|
|
||||||
* Used by page types that don't match source files but instead create
|
|
||||||
* synthetic pages (e.g., one page per tag, one page per folder).
|
|
||||||
*/
|
|
||||||
export type PageGenerator = (args: {
|
export type PageGenerator = (args: {
|
||||||
content: ProcessedContent[]
|
content: ProcessedContent[]
|
||||||
cfg: GlobalConfiguration
|
cfg: GlobalConfiguration
|
||||||
ctx: BuildCtx
|
ctx: BuildCtx
|
||||||
|
[key: string]: unknown
|
||||||
}) => VirtualPage[]
|
}) => VirtualPage[]
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function that creates a PageType plugin instance.
|
|
||||||
*/
|
|
||||||
export type QuartzPageTypePlugin<Options extends OptionType = undefined> = (
|
export type QuartzPageTypePlugin<Options extends OptionType = undefined> = (
|
||||||
opts?: Options,
|
opts?: Options,
|
||||||
) => QuartzPageTypePluginInstance
|
) => QuartzPageTypePluginInstance
|
||||||
|
|
||||||
/**
|
export interface QuartzPageTypePluginInstance {
|
||||||
* A PageType plugin instance.
|
|
||||||
*
|
|
||||||
* PageTypes are a declarative abstraction over page-rendering emitters.
|
|
||||||
* Each PageType declares which files it owns (via `match`), optionally
|
|
||||||
* generates virtual pages (via `generate`), and provides a body component
|
|
||||||
* and layout reference for rendering.
|
|
||||||
*/
|
|
||||||
export type QuartzPageTypePluginInstance = {
|
|
||||||
name: string
|
name: string
|
||||||
/** Higher priority wins when multiple page types match the same file. Default: 0. */
|
|
||||||
priority?: number
|
priority?: number
|
||||||
/** Determines which source files this page type owns. */
|
|
||||||
match: PageMatcher
|
match: PageMatcher
|
||||||
/** Produces virtual pages from aggregated content data. */
|
|
||||||
generate?: PageGenerator
|
generate?: PageGenerator
|
||||||
/** Layout key — references a key in `layout.byPageType`. */
|
|
||||||
layout: string
|
layout: string
|
||||||
/** The body component constructor for this page type. */
|
body: QuartzComponentConstructor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structural supertype accepted in plugin configuration arrays.
|
||||||
|
// Community plugins use a differently-branded FullSlug in their PageMatcher,
|
||||||
|
// making them incompatible with the internal PageMatcher under strict
|
||||||
|
// function-parameter contravariance. This wider entry type avoids forcing
|
||||||
|
// casts in quartz.config.ts while the dispatcher safely calls match/generate
|
||||||
|
// with the correct arguments at runtime.
|
||||||
|
export interface PageTypePluginEntry {
|
||||||
|
name: string
|
||||||
|
priority?: number
|
||||||
|
match: (...args: never[]) => boolean
|
||||||
|
generate?: (...args: never[]) => VirtualPage[]
|
||||||
|
layout: string
|
||||||
body: QuartzComponentConstructor
|
body: QuartzComponentConstructor
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user