mirror of
https://github.com/monapdx/obsidian-skeletal.git
synced 2026-07-22 08:32:09 +00:00
Add local deployment workflow and docs: .env.local.example, scripts/deploy-local.mjs, deploy:local npm script, screenshots, and CHANGELOG.md. Update README with deployment, screenshots, usage, and development instructions. Update .gitignore to exclude local env, logs, and build outputs. Polish UI and layout: refactor TemplateBrowserModal structure and update styles.css for responsive modal/pane scrolling. Small metadata changes: manifest/package.json author/description and LICENSE copyright.
99 lines
2.8 KiB
JavaScript
99 lines
2.8 KiB
JavaScript
import { spawnSync } from "node:child_process";
|
|
import { copyFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const envPath = join(rootDir, ".env.local");
|
|
const pluginFiles = ["main.js", "manifest.json", "styles.css"];
|
|
|
|
function fail(message) {
|
|
console.error(`deploy:local failed: ${message}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
function loadEnvLocal(path) {
|
|
if (!existsSync(path)) {
|
|
fail(
|
|
`Missing .env.local. Copy .env.local.example to .env.local and set OBSIDIAN_VAULT_PATH to your vault root.`
|
|
);
|
|
}
|
|
|
|
const values = {};
|
|
const text = readFileSync(path, "utf8");
|
|
for (const rawLine of text.split(/\r?\n/)) {
|
|
const line = rawLine.trim();
|
|
if (!line || line.startsWith("#")) {
|
|
continue;
|
|
}
|
|
const eq = line.indexOf("=");
|
|
if (eq <= 0) {
|
|
continue;
|
|
}
|
|
const key = line.slice(0, eq).trim();
|
|
let value = line.slice(eq + 1).trim();
|
|
if (
|
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
(value.startsWith("'") && value.endsWith("'"))
|
|
) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
values[key] = value;
|
|
}
|
|
return values;
|
|
}
|
|
|
|
function resolveVaultPath(raw) {
|
|
if (!raw || !raw.trim()) {
|
|
fail("OBSIDIAN_VAULT_PATH is empty in .env.local.");
|
|
}
|
|
const trimmed = raw.trim();
|
|
if (trimmed.includes("[") || /PASTE|YOUR VAULT|example/i.test(trimmed)) {
|
|
fail(
|
|
"OBSIDIAN_VAULT_PATH still looks like a placeholder. Set it to your real vault folder path."
|
|
);
|
|
}
|
|
const vaultPath = isAbsolute(trimmed) ? trimmed : resolve(rootDir, trimmed);
|
|
if (!existsSync(vaultPath)) {
|
|
fail(`Vault path does not exist: ${vaultPath}`);
|
|
}
|
|
return vaultPath;
|
|
}
|
|
|
|
function runBuild() {
|
|
console.log("Building plugin…");
|
|
const result = spawnSync("npm", ["run", "build"], {
|
|
cwd: rootDir,
|
|
stdio: "inherit",
|
|
shell: true,
|
|
});
|
|
if (result.error) {
|
|
fail(result.error.message);
|
|
}
|
|
if (result.status !== 0) {
|
|
fail(`Production build exited with code ${result.status ?? "unknown"}.`);
|
|
}
|
|
}
|
|
|
|
function deploy(vaultPath) {
|
|
const destDir = join(vaultPath, ".obsidian", "plugins", "skeletal");
|
|
mkdirSync(destDir, { recursive: true });
|
|
|
|
for (const file of pluginFiles) {
|
|
const source = join(rootDir, file);
|
|
if (!existsSync(source)) {
|
|
fail(`Expected build output missing: ${file}`);
|
|
}
|
|
const dest = join(destDir, file);
|
|
copyFileSync(source, dest);
|
|
console.log(`Copied ${file} → ${dest}`);
|
|
}
|
|
|
|
console.log(`Deployed Skeletal to ${destDir}`);
|
|
console.log("Reload the plugin in Obsidian (or restart Obsidian) to pick up changes.");
|
|
}
|
|
|
|
const env = loadEnvLocal(envPath);
|
|
const vaultPath = resolveVaultPath(env.OBSIDIAN_VAULT_PATH ?? "");
|
|
runBuild();
|
|
deploy(vaultPath);
|