obsidian-plugin-config 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +4 -0
- package/README.md +45 -0
- package/bin/obsidian-inject.js +98 -0
- package/obsidian-plugin-config-1.0.2.tgz +0 -0
- package/package.json +88 -0
- package/scripts/acp.ts +71 -0
- package/scripts/build-npm.ts +137 -0
- package/scripts/esbuild.config.ts +311 -0
- package/scripts/help.ts +46 -0
- package/scripts/inject-path.ts +487 -0
- package/scripts/inject-prompt.ts +399 -0
- package/scripts/open-editor.mjs +18 -0
- package/scripts/release.ts +97 -0
- package/scripts/update-exports.js +91 -0
- package/scripts/update-version-config.ts +98 -0
- package/scripts/update-version.ts +102 -0
- package/scripts/utils.ts +117 -0
- package/src/index.ts +6 -0
- package/src/main_test.ts +106 -0
- package/src/modals/GenericConfirmModal.ts +67 -0
- package/src/modals/index.ts +3 -0
- package/src/test-centralized-utils.ts +23 -0
- package/src/tools/index.ts +9 -0
- package/src/utils/NoticeHelper.ts +102 -0
- package/src/utils/SettingsHelper.ts +180 -0
- package/src/utils/index.ts +3 -0
- package/templates/.vscode/settings.json +4 -0
- package/templates/eslint.config.ts +48 -0
- package/templates/help-plugin.ts +39 -0
- package/templates/package-versions.json +28 -0
- package/templates/tsconfig.json +37 -0
- package/test-plugin/manifest.json +10 -0
- package/test-plugin/package.json +38 -0
- package/test-plugin/scripts/acp.ts +71 -0
- package/test-plugin/scripts/esbuild.config.ts +165 -0
- package/test-plugin/scripts/help.ts +29 -0
- package/test-plugin/scripts/release.ts +97 -0
- package/test-plugin/scripts/update-version.ts +102 -0
- package/test-plugin/scripts/utils.ts +117 -0
- package/test-plugin/src/main.ts +11 -0
- package/test-plugin/yarn.lock +386 -0
- package/test-plugin-v2/main.js +5 -0
- package/test-plugin-v2/manifest.json +10 -0
- package/test-plugin-v2/package.json +40 -0
- package/test-plugin-v2/scripts/acp.ts +71 -0
- package/test-plugin-v2/scripts/esbuild.config.ts +165 -0
- package/test-plugin-v2/scripts/help.ts +29 -0
- package/test-plugin-v2/scripts/release.ts +97 -0
- package/test-plugin-v2/scripts/update-version.ts +102 -0
- package/test-plugin-v2/scripts/utils.ts +117 -0
- package/test-plugin-v2/src/main.ts +11 -0
- package/test-plugin-v2/tsconfig.json +31 -0
- package/test-plugin-v2/yarn.lock +1986 -0
- package/tsconfig.json +38 -0
- package/versions.json +5 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import esbuild from "esbuild";
|
|
2
|
+
import process from "process";
|
|
3
|
+
import builtins from "builtin-modules";
|
|
4
|
+
import { config } from "dotenv";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
import { rm } from "fs/promises";
|
|
8
|
+
import { isValidPath, copyFilesToTargetDir, askQuestion, createReadlineInterface } from "./utils.js";
|
|
9
|
+
|
|
10
|
+
// Determine the plugin directory (where the script is called from)
|
|
11
|
+
const pluginDir = process.cwd();
|
|
12
|
+
|
|
13
|
+
// Create readline interface for prompts
|
|
14
|
+
const rl = createReadlineInterface();
|
|
15
|
+
|
|
16
|
+
async function promptForVaultPath(envKey: string): Promise<string> {
|
|
17
|
+
const vaultType = envKey === "REAL_VAULT" ? "real" : "test";
|
|
18
|
+
const usage = envKey === "REAL_VAULT"
|
|
19
|
+
? "for final plugin installation"
|
|
20
|
+
: "for development and testing";
|
|
21
|
+
|
|
22
|
+
console.log(`❓ ${envKey} path is required ${usage}`);
|
|
23
|
+
const path = await askQuestion(`📝 Enter your ${vaultType} vault path (or Ctrl+C to cancel): `, rl);
|
|
24
|
+
|
|
25
|
+
if (!path) {
|
|
26
|
+
console.log('❌ No path provided, exiting...');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return path;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function promptForBothVaults(): Promise<void> {
|
|
34
|
+
console.log(`❓ Both vault paths are required for external development`);
|
|
35
|
+
console.log(` TEST_VAULT: for development and testing (yarn dev)`);
|
|
36
|
+
console.log(` REAL_VAULT: for final plugin installation (yarn real)`);
|
|
37
|
+
|
|
38
|
+
let confirmed = false;
|
|
39
|
+
while (!confirmed) {
|
|
40
|
+
const testPath = await askQuestion(`📝 Enter your test vault path: `, rl);
|
|
41
|
+
if (!testPath) {
|
|
42
|
+
console.log('❌ No test vault path provided, exiting...');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const realPath = await askQuestion(`📝 Enter your real vault path: `, rl);
|
|
47
|
+
if (!realPath) {
|
|
48
|
+
console.log('❌ No real vault path provided, exiting...');
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Show confirmation
|
|
53
|
+
console.log(`\n📋 Vault paths entered:`);
|
|
54
|
+
console.log(` TEST_VAULT: ${testPath}`);
|
|
55
|
+
console.log(` REAL_VAULT: ${realPath}`);
|
|
56
|
+
|
|
57
|
+
const confirm = await askQuestion(`✅ Are these paths correct? (y/n): `, rl);
|
|
58
|
+
if (confirm.toLowerCase() === 'y' || confirm.toLowerCase() === 'yes') {
|
|
59
|
+
await updateEnvFile("TEST_VAULT", testPath);
|
|
60
|
+
await updateEnvFile("REAL_VAULT", realPath);
|
|
61
|
+
confirmed = true;
|
|
62
|
+
} else {
|
|
63
|
+
console.log(`🔄 Let's try again...\n`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function updateEnvFile(envKey: string, vaultPath: string): Promise<void> {
|
|
69
|
+
const envPath = path.join(pluginDir, '.env');
|
|
70
|
+
let envContent = '';
|
|
71
|
+
|
|
72
|
+
// Read existing .env if it exists
|
|
73
|
+
try {
|
|
74
|
+
envContent = readFileSync(envPath, 'utf8');
|
|
75
|
+
} catch {
|
|
76
|
+
// File doesn't exist, start with empty content
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Update or add the variable
|
|
80
|
+
const regex = new RegExp(`^${envKey}=.*$`, 'm');
|
|
81
|
+
const newLine = `${envKey}=${vaultPath}`;
|
|
82
|
+
|
|
83
|
+
if (regex.test(envContent)) {
|
|
84
|
+
envContent = envContent.replace(regex, newLine);
|
|
85
|
+
} else {
|
|
86
|
+
envContent += envContent.endsWith('\n') ? '' : '\n';
|
|
87
|
+
envContent += newLine + '\n';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Write back to .env
|
|
91
|
+
await import('fs').then(fs => fs.writeFileSync(envPath, envContent));
|
|
92
|
+
console.log(`✅ Updated ${envKey} in .env file`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getVaultPath(vaultPath: string): string {
|
|
96
|
+
// Check if the path already contains the plugins directory path
|
|
97
|
+
const pluginsPath = path.join(".obsidian", "plugins");
|
|
98
|
+
if (vaultPath.includes(pluginsPath)) {
|
|
99
|
+
return path.join(vaultPath, manifest.id);
|
|
100
|
+
} else {
|
|
101
|
+
return path.join(vaultPath, ".obsidian", "plugins", manifest.id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const manifestPath = path.join(pluginDir, "manifest.json");
|
|
105
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
106
|
+
|
|
107
|
+
config();
|
|
108
|
+
|
|
109
|
+
const EXTERNAL_DEPS = [
|
|
110
|
+
"obsidian",
|
|
111
|
+
"electron",
|
|
112
|
+
"@codemirror/autocomplete",
|
|
113
|
+
"@codemirror/collab",
|
|
114
|
+
"@codemirror/commands",
|
|
115
|
+
"@codemirror/language",
|
|
116
|
+
"@codemirror/lint",
|
|
117
|
+
"@codemirror/search",
|
|
118
|
+
"@codemirror/state",
|
|
119
|
+
"@codemirror/view",
|
|
120
|
+
"@lezer/common",
|
|
121
|
+
"@lezer/highlight",
|
|
122
|
+
"@lezer/lr",
|
|
123
|
+
...builtins
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
const BANNER = `/*
|
|
127
|
+
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
128
|
+
if you want to view the source, please visit the github repository of this plugin
|
|
129
|
+
*/`;
|
|
130
|
+
|
|
131
|
+
async function validateEnvironment(): Promise<void> {
|
|
132
|
+
const srcMainPath = path.join(pluginDir, "src/main.ts");
|
|
133
|
+
if (!await isValidPath(srcMainPath)) {
|
|
134
|
+
throw new Error("Invalid path for src/main.ts. main.ts must be in the src directory");
|
|
135
|
+
}
|
|
136
|
+
if (!await isValidPath(manifestPath)) {
|
|
137
|
+
throw new Error("Invalid path for manifest.json");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function getBuildPath(isProd: boolean): Promise<string> {
|
|
142
|
+
// Check if we should use real vault (either -r flag or "real" argument)
|
|
143
|
+
const useRealVault = process.argv.includes("-r") || process.argv.includes("real");
|
|
144
|
+
|
|
145
|
+
// If production build without redirection, return plugin directory
|
|
146
|
+
if (isProd && !useRealVault) {
|
|
147
|
+
return pluginDir;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Determine which path to use
|
|
151
|
+
const envKey = useRealVault ? "REAL_VAULT" : "TEST_VAULT";
|
|
152
|
+
const vaultPath = process.env[envKey]?.trim();
|
|
153
|
+
|
|
154
|
+
// Handle empty vault paths with intelligent logic
|
|
155
|
+
if (!vaultPath) {
|
|
156
|
+
// Check if we're in Obsidian plugins folder
|
|
157
|
+
const currentPath = process.cwd();
|
|
158
|
+
const isInObsidianPlugins = currentPath.includes('.obsidian/plugins') ||
|
|
159
|
+
currentPath.includes('.obsidian\\plugins');
|
|
160
|
+
|
|
161
|
+
const testVault = process.env.TEST_VAULT?.trim();
|
|
162
|
+
const realVault = process.env.REAL_VAULT?.trim();
|
|
163
|
+
|
|
164
|
+
// YARN REAL logic
|
|
165
|
+
if (envKey === "REAL_VAULT") {
|
|
166
|
+
if (!isInObsidianPlugins) {
|
|
167
|
+
// External development: ask for both if missing
|
|
168
|
+
if (!testVault || !realVault) {
|
|
169
|
+
await promptForBothVaults();
|
|
170
|
+
config();
|
|
171
|
+
// After updating both, get the REAL_VAULT path directly
|
|
172
|
+
const updatedRealVault = process.env.REAL_VAULT?.trim();
|
|
173
|
+
if (updatedRealVault) {
|
|
174
|
+
return getVaultPath(updatedRealVault);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
const newPath = await promptForVaultPath(envKey);
|
|
178
|
+
await updateEnvFile(envKey, newPath);
|
|
179
|
+
config();
|
|
180
|
+
return getVaultPath(newPath);
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
// In obsidian/plugins: ask only for REAL_VAULT
|
|
184
|
+
const newPath = await promptForVaultPath(envKey);
|
|
185
|
+
await updateEnvFile(envKey, newPath);
|
|
186
|
+
return getVaultPath(newPath);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// YARN DEV/START logic
|
|
191
|
+
if (envKey === "TEST_VAULT") {
|
|
192
|
+
if (!isInObsidianPlugins) {
|
|
193
|
+
// External development: ask for both if missing
|
|
194
|
+
if (!testVault || !realVault) {
|
|
195
|
+
await promptForBothVaults();
|
|
196
|
+
config();
|
|
197
|
+
// After updating both, get the TEST_VAULT path directly
|
|
198
|
+
const updatedTestVault = process.env.TEST_VAULT?.trim();
|
|
199
|
+
if (updatedTestVault) {
|
|
200
|
+
return getVaultPath(updatedTestVault);
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
const newPath = await promptForVaultPath(envKey);
|
|
204
|
+
await updateEnvFile(envKey, newPath);
|
|
205
|
+
return getVaultPath(newPath);
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
// In obsidian/plugins: allow in-place development
|
|
209
|
+
console.log(`ℹ️ Building in Obsidian plugins folder (in-place development)`);
|
|
210
|
+
return pluginDir;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// If we reach here, use the vault path directly
|
|
216
|
+
return vaultPath ? getVaultPath(vaultPath) : pluginDir;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function createBuildContext(buildPath: string, isProd: boolean, entryPoints: string[]): Promise<esbuild.BuildContext> {
|
|
220
|
+
return await esbuild.context({
|
|
221
|
+
banner: { js: BANNER },
|
|
222
|
+
minify: isProd,
|
|
223
|
+
entryPoints,
|
|
224
|
+
bundle: true,
|
|
225
|
+
external: EXTERNAL_DEPS,
|
|
226
|
+
format: "cjs",
|
|
227
|
+
target: "esNext",
|
|
228
|
+
platform: "node",
|
|
229
|
+
logLevel: "info",
|
|
230
|
+
sourcemap: isProd ? false : "inline",
|
|
231
|
+
treeShaking: true,
|
|
232
|
+
outdir: buildPath,
|
|
233
|
+
outbase: path.join(pluginDir, "src"),
|
|
234
|
+
plugins: [
|
|
235
|
+
// Plugin pour gérer les alias de chemin
|
|
236
|
+
{
|
|
237
|
+
name: "path-alias",
|
|
238
|
+
setup: (build): void => {
|
|
239
|
+
build.onResolve({ filter: /^@config\// }, (args) => {
|
|
240
|
+
const relativePath = args.path.replace(/^@config\//, "");
|
|
241
|
+
return {
|
|
242
|
+
path: path.resolve("../obsidian-plugin-config/src", relativePath)
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
build.onResolve({ filter: /^@config-scripts\// }, (args) => {
|
|
247
|
+
const relativePath = args.path.replace(/^@config-scripts\//, "");
|
|
248
|
+
return {
|
|
249
|
+
path: path.resolve("../obsidian-plugin-config/scripts", relativePath)
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "copy-to-plugins-folder",
|
|
256
|
+
setup: (build): void => {
|
|
257
|
+
build.onEnd(async () => {
|
|
258
|
+
// if real or build
|
|
259
|
+
if (isProd) {
|
|
260
|
+
if (process.argv.includes("-r")) {
|
|
261
|
+
await copyFilesToTargetDir(buildPath);
|
|
262
|
+
console.log(`Successfully installed in ${buildPath}`);
|
|
263
|
+
} else {
|
|
264
|
+
const folderToRemove = path.join(buildPath, "_.._");
|
|
265
|
+
if (await isValidPath(folderToRemove)) {
|
|
266
|
+
await rm(folderToRemove, { recursive: true });
|
|
267
|
+
}
|
|
268
|
+
console.log("Built done in initial folder");
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// if watch (dev)
|
|
272
|
+
else {
|
|
273
|
+
await copyFilesToTargetDir(buildPath);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function main(): Promise<void> {
|
|
283
|
+
try {
|
|
284
|
+
await validateEnvironment();
|
|
285
|
+
const isProd = process.argv[2] === "production";
|
|
286
|
+
const buildPath = await getBuildPath(isProd);
|
|
287
|
+
console.log(buildPath === pluginDir
|
|
288
|
+
? "Building in initial folder"
|
|
289
|
+
: `Building in ${buildPath}`);
|
|
290
|
+
const srcStylesPath = path.join(pluginDir, "src/styles.css");
|
|
291
|
+
const rootStylesPath = path.join(pluginDir, "styles.css");
|
|
292
|
+
const stylePath = await isValidPath(srcStylesPath) ? srcStylesPath : await isValidPath(rootStylesPath) ? rootStylesPath : "";
|
|
293
|
+
const mainTsPath = path.join(pluginDir, "src/main.ts");
|
|
294
|
+
const entryPoints = stylePath ? [mainTsPath, stylePath] : [mainTsPath];
|
|
295
|
+
const context = await createBuildContext(buildPath, isProd, entryPoints);
|
|
296
|
+
|
|
297
|
+
if (isProd) {
|
|
298
|
+
await context.rebuild();
|
|
299
|
+
rl.close();
|
|
300
|
+
process.exit(0);
|
|
301
|
+
} else {
|
|
302
|
+
await context.watch();
|
|
303
|
+
}
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error("Build failed:", error);
|
|
306
|
+
rl.close();
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
main().catch(console.error);
|
package/scripts/help.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
console.log(`
|
|
4
|
+
Obsidian Plugin Config - Command Reference
|
|
5
|
+
Système d'injection pour plugins Obsidian autonomes
|
|
6
|
+
|
|
7
|
+
STRATÉGIE NPM GLOBAL:
|
|
8
|
+
npm install -g obsidian-plugin-config # Installation globale (une seule fois)
|
|
9
|
+
obsidian-inject # Injection depuis n'importe où
|
|
10
|
+
obsidian-inject /chemin/vers/plugin # Injection par chemin
|
|
11
|
+
|
|
12
|
+
INJECTION LOCALE (développement):
|
|
13
|
+
yarn inject-path <chemin> Injection par chemin depuis plugin-config
|
|
14
|
+
yarn inject <chemin> Alias pour inject-path
|
|
15
|
+
|
|
16
|
+
MIGRATION (développement):
|
|
17
|
+
yarn migrate, m <chemin> Migration plugin vers architecture centralisée
|
|
18
|
+
yarn migrate --dry-run Aperçu des changements sans appliquer
|
|
19
|
+
|
|
20
|
+
MAINTENANCE:
|
|
21
|
+
yarn acp Add, commit, and push changes
|
|
22
|
+
yarn update-version, v Update version
|
|
23
|
+
yarn help, h Afficher cette aide
|
|
24
|
+
|
|
25
|
+
EXEMPLES D'UTILISATION:
|
|
26
|
+
# Installation globale (recommandée)
|
|
27
|
+
npm install -g obsidian-plugin-config
|
|
28
|
+
cd mon-plugin && obsidian-inject
|
|
29
|
+
|
|
30
|
+
# Développement local
|
|
31
|
+
yarn inject-path "../mon-plugin"
|
|
32
|
+
yarn inject "C:\\Users\\dev\\plugins\\mon-plugin"
|
|
33
|
+
|
|
34
|
+
CE QUI EST INJECTÉ:
|
|
35
|
+
✅ Scripts locaux (esbuild.config.ts, acp.ts, utils.ts, etc.)
|
|
36
|
+
✅ Configuration package.json (scripts, dépendances)
|
|
37
|
+
✅ Protection yarn obligatoire
|
|
38
|
+
✅ Installation automatique des dépendances
|
|
39
|
+
|
|
40
|
+
ARCHITECTURE:
|
|
41
|
+
- Plugin devient AUTONOME avec scripts locaux
|
|
42
|
+
- Aucune dépendance externe requise après injection
|
|
43
|
+
- Mise à jour possible via re-injection
|
|
44
|
+
|
|
45
|
+
COMPTE NPM: 3c0d (connecté)
|
|
46
|
+
`);
|