feat: migrate to npm specifiers with type-safe plugin index
- Default config and all 4 templates use @quartz-community/* npm specifiers - config-loader: npm packages imported directly (not via .quartz/plugins/ paths) - gitLoader: regeneratePluginIndex cross-references .d.ts with .js to correctly classify type-only exports, preventing runtime 'does not provide export' errors - All 44 default plugins added as dependencies - Locally tested: 111 docs files → 374 output files, zero errors
This commit is contained in:
@@ -433,14 +433,20 @@ export async function loadQuartzConfig(
|
||||
const instances = []
|
||||
for (const { entry, manifest } of items) {
|
||||
try {
|
||||
const gitSpec = parsePluginSource(entry.source)
|
||||
const entryPoint = getPluginEntryPoint(gitSpec.name)
|
||||
const module = await import(toFileUrl(entryPoint))
|
||||
const spec = parsePluginSource(entry.source)
|
||||
let module
|
||||
if (spec.npmPackage) {
|
||||
module = await import(spec.name)
|
||||
} else {
|
||||
const entryPoint = getPluginEntryPoint(spec.name)
|
||||
module = await import(toFileUrl(entryPoint))
|
||||
}
|
||||
const pluginName = spec.npmPackage ? spec.name : spec.name
|
||||
if (manifest?.components && Object.keys(manifest.components).length > 0) {
|
||||
await loadComponentsFromPackage(gitSpec.name, manifest)
|
||||
await loadComponentsFromPackage(pluginName, manifest)
|
||||
}
|
||||
if (manifest?.frames && Object.keys(manifest.frames).length > 0) {
|
||||
await loadFramesFromPackage(gitSpec.name, manifest)
|
||||
await loadFramesFromPackage(pluginName, manifest)
|
||||
}
|
||||
|
||||
const factory = findFactory(module, expectedCategory)
|
||||
@@ -452,7 +458,7 @@ export async function loadQuartzConfig(
|
||||
)
|
||||
continue
|
||||
}
|
||||
const pluginOverrides = componentRegistry.getOptionOverrides(gitSpec.name)
|
||||
const pluginOverrides = componentRegistry.getOptionOverrides(spec.name)
|
||||
const options = { ...manifest?.defaultOptions, ...entry.options, ...pluginOverrides }
|
||||
const instance = factory(Object.keys(options).length > 0 ? options : undefined)
|
||||
if (!instance || typeof instance !== "object") {
|
||||
|
||||
@@ -951,8 +951,29 @@ export async function regeneratePluginIndex(
|
||||
|
||||
const dtsContent = fs.readFileSync(distIndex, "utf-8")
|
||||
const exportedNames = parseExportsFromDts(dtsContent)
|
||||
const named = exportedNames.filter((e) => !e.startsWith("type "))
|
||||
const types = exportedNames.filter((e) => e.startsWith("type ")).map((e) => e.slice(5))
|
||||
const dtsTypes = exportedNames.filter((e) => e.startsWith("type ")).map((e) => e.slice(5))
|
||||
const dtsNamed = exportedNames.filter((e) => !e.startsWith("type "))
|
||||
|
||||
const jsIndex = path.join(pluginDir, "dist", "index.js")
|
||||
let jsExports = new Set<string>()
|
||||
if (fs.existsSync(jsIndex)) {
|
||||
const jsContent = fs.readFileSync(jsIndex, "utf-8")
|
||||
const jsExportMatches = jsContent.matchAll(/export\s*{\s*([^}]+)\s*}/g)
|
||||
for (const m of jsExportMatches) {
|
||||
for (const n of m[1].split(",")) {
|
||||
const clean = n
|
||||
.trim()
|
||||
.split(/\s+as\s+/)
|
||||
.pop()
|
||||
?.trim()
|
||||
if (clean) jsExports.add(clean)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const named = jsExports.size > 0 ? dtsNamed.filter((n) => jsExports.has(n)) : dtsNamed
|
||||
const extraTypes = jsExports.size > 0 ? dtsNamed.filter((n) => !jsExports.has(n)) : []
|
||||
const types = [...dtsTypes, ...extraTypes]
|
||||
|
||||
const overridable = named.filter((n) => isOverridableExport(n, dtsContent))
|
||||
const passthrough = named.filter((n) => !isOverridableExport(n, dtsContent))
|
||||
@@ -988,8 +1009,29 @@ export async function regeneratePluginIndex(
|
||||
|
||||
const dtsContent = fs.readFileSync(distIndex, "utf-8")
|
||||
const exportedNames = parseExportsFromDts(dtsContent)
|
||||
const named = exportedNames.filter((e) => !e.startsWith("type "))
|
||||
const types = exportedNames.filter((e) => e.startsWith("type ")).map((e) => e.slice(5))
|
||||
const dtsTypes = exportedNames.filter((e) => e.startsWith("type ")).map((e) => e.slice(5))
|
||||
const dtsNamed = exportedNames.filter((e) => !e.startsWith("type "))
|
||||
|
||||
const jsIndex = path.join(path.dirname(distIndex), "index.js")
|
||||
let jsExports = new Set<string>()
|
||||
if (fs.existsSync(jsIndex)) {
|
||||
const jsContent = fs.readFileSync(jsIndex, "utf-8")
|
||||
const jsExportMatches = jsContent.matchAll(/export\s*{\s*([^}]+)\s*}/g)
|
||||
for (const m of jsExportMatches) {
|
||||
for (const n of m[1].split(",")) {
|
||||
const clean = n
|
||||
.trim()
|
||||
.split(/\s+as\s+/)
|
||||
.pop()
|
||||
?.trim()
|
||||
if (clean) jsExports.add(clean)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const named = jsExports.size > 0 ? dtsNamed.filter((n) => jsExports.has(n)) : dtsNamed
|
||||
const extraTypes = jsExports.size > 0 ? dtsNamed.filter((n) => !jsExports.has(n)) : []
|
||||
const types = [...dtsTypes, ...extraTypes]
|
||||
|
||||
const overridable = named.filter((n) => isOverridableExport(n, dtsContent))
|
||||
const passthrough = named.filter((n) => !isOverridableExport(n, dtsContent))
|
||||
|
||||
Reference in New Issue
Block a user