97eea3ee34
- quartz.config.default.yaml: all 44 plugins use @quartz-community/* npm specifiers - cli/templates/*.yaml: all 4 templates updated (default, blog, obsidian, ttrpg) - bootstrap-cli.mjs: updated help text - package.json: devDeps use npm semver ranges instead of github: specifiers - gitLoader.ts: regeneratePluginIndex scans npm packages from node_modules - install-plugins.ts: generates plugin index for npm packages - Removed quartz.lock.json (only relevant for git-installed plugins)
91 lines
3.1 KiB
JavaScript
91 lines
3.1 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "fs"
|
|
import path from "path"
|
|
import YAML from "yaml"
|
|
import { installPlugins, parsePluginSource, regeneratePluginIndex } from "./gitLoader.js"
|
|
import type { PluginSource, QuartzPluginsJson } from "./types.js"
|
|
|
|
function resolveConfigPath(): string {
|
|
const configYamlPath = path.join(process.cwd(), "quartz.config.yaml")
|
|
const defaultConfigYamlPath = path.join(process.cwd(), "quartz.config.default.yaml")
|
|
const legacyPluginsJsonPath = path.join(process.cwd(), "quartz.plugins.json")
|
|
const legacyDefaultPluginsJsonPath = path.join(process.cwd(), "quartz.plugins.default.json")
|
|
|
|
if (fs.existsSync(configYamlPath)) return configYamlPath
|
|
if (fs.existsSync(legacyPluginsJsonPath)) return legacyPluginsJsonPath
|
|
if (fs.existsSync(defaultConfigYamlPath)) return defaultConfigYamlPath
|
|
if (fs.existsSync(legacyDefaultPluginsJsonPath)) return legacyDefaultPluginsJsonPath
|
|
return configYamlPath
|
|
}
|
|
|
|
function readPluginsJson(): QuartzPluginsJson | null {
|
|
const configPath = resolveConfigPath()
|
|
if (!fs.existsSync(configPath)) return null
|
|
const raw = fs.readFileSync(configPath, "utf-8")
|
|
if (configPath.endsWith(".yaml") || configPath.endsWith(".yml")) {
|
|
return YAML.parse(raw)
|
|
}
|
|
return JSON.parse(raw)
|
|
}
|
|
|
|
async function getExternalPluginSources(): Promise<PluginSource[]> {
|
|
try {
|
|
const module = await import("../../../quartz.js")
|
|
const config = module.default ?? module
|
|
const externalPlugins = config.externalPlugins
|
|
if (Array.isArray(externalPlugins) && externalPlugins.length > 0) {
|
|
return externalPlugins as PluginSource[]
|
|
}
|
|
} catch {
|
|
// fall back to config yaml parsing
|
|
}
|
|
|
|
const pluginsJson = readPluginsJson()
|
|
const entries = pluginsJson?.plugins ?? []
|
|
return entries.filter((entry) => entry.enabled !== false).map((entry) => entry.source)
|
|
}
|
|
|
|
async function main() {
|
|
const externalPlugins = await getExternalPluginSources()
|
|
|
|
if (externalPlugins.length === 0) {
|
|
console.log("No external plugins to install.")
|
|
return
|
|
}
|
|
|
|
const specs = externalPlugins
|
|
.map((source: PluginSource) => parsePluginSource(source))
|
|
.filter((spec) => !spec.npmPackage)
|
|
|
|
const npmSpecs = externalPlugins
|
|
.map((source: PluginSource) => parsePluginSource(source))
|
|
.filter((spec) => spec.npmPackage)
|
|
|
|
if (specs.length === 0 && npmSpecs.length === 0) {
|
|
console.log("No external plugins to install.")
|
|
return
|
|
}
|
|
|
|
if (specs.length > 0) {
|
|
console.log(`Installing ${specs.length} plugin(s) from Git...`)
|
|
const installed = await installPlugins(specs, { verbose: true })
|
|
|
|
if (installed.size === specs.length) {
|
|
console.log("✓ All Git plugins installed successfully")
|
|
} else {
|
|
console.error(`✗ Only ${installed.size}/${specs.length} Git plugins installed`)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
if (npmSpecs.length > 0) {
|
|
console.log(`Found ${npmSpecs.length} npm plugin(s), regenerating plugin index...`)
|
|
await regeneratePluginIndex({ verbose: true, npmPackages: npmSpecs.map((s) => s.name) })
|
|
}
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error("Failed to install plugins:", err)
|
|
process.exit(1)
|
|
})
|