obsidian-plugin-config 1.4.4 → 1.4.6

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.
@@ -1,12 +1,18 @@
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 fs from "fs";
9
- import { isValidPath, copyFilesToTargetDir, askQuestion, createReadlineInterface, removeMainCss } from "./utils.js";
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 fs from 'fs';
9
+ import {
10
+ isValidPath,
11
+ copyFilesToTargetDir,
12
+ askQuestion,
13
+ createReadlineInterface,
14
+ removeMainCss
15
+ } from './utils.js';
10
16
 
11
17
  // Determine the plugin directory (where the script is called from)
12
18
  const pluginDir = process.cwd();
@@ -15,104 +21,108 @@ const pluginDir = process.cwd();
15
21
  const rl = createReadlineInterface();
16
22
 
17
23
  async function promptForVaultPath(envKey: string): Promise<string> {
18
- const vaultType = envKey === "REAL_VAULT" ? "real" : "test";
19
- const usage = envKey === "REAL_VAULT"
20
- ? "for final plugin installation"
21
- : "for development and testing";
22
-
23
- console.log(`❓ ${envKey} path is required ${usage}`);
24
- const path = await askQuestion(`📝 Enter your ${vaultType} vault path (or Ctrl+C to cancel): `, rl);
25
-
26
- if (!path) {
27
- console.log('❌ No path provided, exiting...');
28
- process.exit(1);
29
- }
30
-
31
- return path;
24
+ const vaultType = envKey === 'REAL_VAULT' ? 'real' : 'test';
25
+ const usage =
26
+ envKey === 'REAL_VAULT'
27
+ ? 'for final plugin installation'
28
+ : 'for development and testing';
29
+
30
+ console.log(`❓ ${envKey} path is required ${usage}`);
31
+ const path = await askQuestion(
32
+ `📝 Enter your ${vaultType} vault path (or Ctrl+C to cancel): `,
33
+ rl
34
+ );
35
+
36
+ if (!path) {
37
+ console.log('❌ No path provided, exiting...');
38
+ process.exit(1);
39
+ }
40
+
41
+ return path;
32
42
  }
33
43
 
34
-
35
-
36
44
  async function updateEnvFile(envKey: string, vaultPath: string): Promise<void> {
37
- const envPath = path.join(pluginDir, '.env');
38
- let envContent = '';
39
-
40
- // Read existing .env if it exists
41
- try {
42
- envContent = readFileSync(envPath, 'utf8');
43
- } catch {
44
- // File doesn't exist, start with empty content
45
- }
46
-
47
- // Update or add the variable
48
- const regex = new RegExp(`^${envKey}=.*$`, 'm');
49
- const newLine = `${envKey}=${vaultPath}`;
50
-
51
- if (regex.test(envContent)) {
52
- envContent = envContent.replace(regex, newLine);
53
- } else {
54
- envContent += envContent.endsWith('\n') ? '' : '\n';
55
- envContent += newLine + '\n';
56
- }
57
-
58
- // Write back to .env
59
- await import('fs').then(fs => fs.writeFileSync(envPath, envContent));
60
- console.log(`✅ Updated ${envKey} in .env file`);
45
+ const envPath = path.join(pluginDir, '.env');
46
+ let envContent = '';
47
+
48
+ // Read existing .env if it exists
49
+ try {
50
+ envContent = readFileSync(envPath, 'utf8');
51
+ } catch {
52
+ // File doesn't exist, start with empty content
53
+ }
54
+
55
+ // Update or add the variable
56
+ const regex = new RegExp(`^${envKey}=.*$`, 'm');
57
+ const newLine = `${envKey}=${vaultPath}`;
58
+
59
+ if (regex.test(envContent)) {
60
+ envContent = envContent.replace(regex, newLine);
61
+ } else {
62
+ envContent += envContent.endsWith('\n') ? '' : '\n';
63
+ envContent += newLine + '\n';
64
+ }
65
+
66
+ // Write back to .env
67
+ await import('fs').then((fs) => fs.writeFileSync(envPath, envContent));
68
+ console.log(`✅ Updated ${envKey} in .env file`);
61
69
  }
62
70
 
63
71
  function validateVaultPath(vaultPath: string): boolean {
64
- // Check if the path contains .obsidian directory
65
- const obsidianPath = path.join(vaultPath, ".obsidian");
66
- const pluginsPath = path.join(vaultPath, ".obsidian", "plugins");
72
+ // Check if the path contains .obsidian directory
73
+ const obsidianPath = path.join(vaultPath, '.obsidian');
74
+ const pluginsPath = path.join(vaultPath, '.obsidian', 'plugins');
67
75
 
68
- return fs.existsSync(obsidianPath) && fs.existsSync(pluginsPath);
76
+ return fs.existsSync(obsidianPath) && fs.existsSync(pluginsPath);
69
77
  }
70
78
 
71
79
  function getVaultPath(vaultPath: string): string {
72
- // Validate that this is a proper vault path
73
- if (!validateVaultPath(vaultPath)) {
74
- console.error(`❌ Invalid vault path: ${vaultPath}`);
75
- console.error(` The path must contain a .obsidian/plugins directory`);
76
- console.error(` Please enter a valid Obsidian vault path`);
77
- process.exit(1);
78
- }
79
-
80
- // Check if the path already contains the plugins directory path
81
- const pluginsPath = path.join(".obsidian", "plugins");
82
- if (vaultPath.includes(pluginsPath)) {
83
- return path.join(vaultPath, manifest.id);
84
- } else {
85
- return path.join(vaultPath, ".obsidian", "plugins", manifest.id);
86
- }
80
+ // Validate that this is a proper vault path
81
+ if (!validateVaultPath(vaultPath)) {
82
+ console.error(`❌ Invalid vault path: ${vaultPath}`);
83
+ console.error(` The path must contain a .obsidian/plugins directory`);
84
+ console.error(` Please enter a valid Obsidian vault path`);
85
+ process.exit(1);
86
+ }
87
+
88
+ // Check if the path already contains the plugins directory path
89
+ const pluginsPath = path.join('.obsidian', 'plugins');
90
+ if (vaultPath.includes(pluginsPath)) {
91
+ return path.join(vaultPath, manifest.id);
92
+ } else {
93
+ return path.join(vaultPath, '.obsidian', 'plugins', manifest.id);
94
+ }
87
95
  }
88
- const manifestPath = path.join(pluginDir, "manifest.json");
96
+ const manifestPath = path.join(pluginDir, 'manifest.json');
89
97
 
90
98
  // Check if manifest exists (for plugin-config itself, it might not exist)
91
99
  if (!fs.existsSync(manifestPath)) {
92
- console.log("⚠️ No manifest.json found - this script is designed for Obsidian plugins");
93
- console.log(" If you're building plugin-config itself, use 'tsc' instead");
94
- process.exit(0);
100
+ console.log(
101
+ '⚠️ No manifest.json found - this script is designed for Obsidian plugins'
102
+ );
103
+ console.log(" If you're building plugin-config itself, use 'tsc' instead");
104
+ process.exit(0);
95
105
  }
96
106
 
97
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
107
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
98
108
 
99
109
  config();
100
110
 
101
111
  const EXTERNAL_DEPS = [
102
- "obsidian",
103
- "electron",
104
- "@codemirror/autocomplete",
105
- "@codemirror/collab",
106
- "@codemirror/commands",
107
- "@codemirror/language",
108
- "@codemirror/lint",
109
- "@codemirror/search",
110
- "@codemirror/state",
111
- "@codemirror/view",
112
- "@lezer/common",
113
- "@lezer/highlight",
114
- "@lezer/lr",
115
- ...builtins
112
+ 'obsidian',
113
+ 'electron',
114
+ '@codemirror/autocomplete',
115
+ '@codemirror/collab',
116
+ '@codemirror/commands',
117
+ '@codemirror/language',
118
+ '@codemirror/lint',
119
+ '@codemirror/search',
120
+ '@codemirror/state',
121
+ '@codemirror/view',
122
+ '@lezer/common',
123
+ '@lezer/highlight',
124
+ '@lezer/lr',
125
+ ...builtins
116
126
  ];
117
127
 
118
128
  const BANNER = `/*
@@ -121,159 +131,185 @@ if you want to view the source, please visit the github repository of this plugi
121
131
  */`;
122
132
 
123
133
  async function validateEnvironment(): Promise<void> {
124
- const srcMainPath = path.join(pluginDir, "src/main.ts");
125
- if (!await isValidPath(srcMainPath)) {
126
- throw new Error("Invalid path for src/main.ts. main.ts must be in the src directory");
127
- }
128
- if (!await isValidPath(manifestPath)) {
129
- throw new Error("Invalid path for manifest.json");
130
- }
134
+ const srcMainPath = path.join(pluginDir, 'src/main.ts');
135
+ if (!(await isValidPath(srcMainPath))) {
136
+ throw new Error(
137
+ 'Invalid path for src/main.ts. main.ts must be in the src directory'
138
+ );
139
+ }
140
+ if (!(await isValidPath(manifestPath))) {
141
+ throw new Error('Invalid path for manifest.json');
142
+ }
131
143
  }
132
144
 
133
145
  async function getBuildPath(isProd: boolean): Promise<string> {
134
- // Check if we should use real vault (either -r flag or "real" argument)
135
- const useRealVault = process.argv.includes("-r") || process.argv.includes("real");
136
-
137
- // If production build without redirection, return plugin directory
138
- if (isProd && !useRealVault) {
139
- return pluginDir;
140
- }
141
-
142
- // Determine which path to use
143
- const envKey = useRealVault ? "REAL_VAULT" : "TEST_VAULT";
144
- const vaultPath = process.env[envKey]?.trim();
145
-
146
- // If empty or undefined, we're already in the plugin folder
147
- if (!vaultPath) {
148
- // Check if we're in Obsidian plugins folder
149
- const currentPath = process.cwd();
150
- const isInObsidianPlugins = currentPath.includes('.obsidian/plugins') ||
151
- currentPath.includes('.obsidian\\plugins');
152
-
153
- if (isInObsidianPlugins) {
154
- // In obsidian/plugins: allow in-place development
155
- console.log(`ℹ️ Building in Obsidian plugins folder (in-place development)`);
156
- return pluginDir;
157
- } else {
158
- // External development: prompt for missing vault path
159
- const newPath = await promptForVaultPath(envKey);
160
- await updateEnvFile(envKey, newPath);
161
- config();
162
- return getVaultPath(newPath);
163
- }
164
- }
165
-
166
- // If we reach here, use the vault path directly
167
- return getVaultPath(vaultPath);
146
+ // Check if we should use real vault (either -r flag or "real" argument)
147
+ const useRealVault = process.argv.includes('-r') || process.argv.includes('real');
148
+
149
+ // If production build without redirection, return plugin directory
150
+ if (isProd && !useRealVault) {
151
+ return pluginDir;
152
+ }
153
+
154
+ // Determine which path to use
155
+ const envKey = useRealVault ? 'REAL_VAULT' : 'TEST_VAULT';
156
+ const vaultPath = process.env[envKey]?.trim();
157
+
158
+ // If empty or undefined, we're already in the plugin folder
159
+ if (!vaultPath) {
160
+ // Check if we're in Obsidian plugins folder
161
+ const currentPath = process.cwd();
162
+ const isInObsidianPlugins =
163
+ currentPath.includes('.obsidian/plugins') ||
164
+ currentPath.includes('.obsidian\\plugins');
165
+
166
+ if (isInObsidianPlugins) {
167
+ // In obsidian/plugins: allow in-place development
168
+ console.log(`ℹ️ Building in Obsidian plugins folder (in-place development)`);
169
+ return pluginDir;
170
+ } else {
171
+ // External development: prompt for missing vault path
172
+ const newPath = await promptForVaultPath(envKey);
173
+ await updateEnvFile(envKey, newPath);
174
+ config();
175
+ return getVaultPath(newPath);
176
+ }
177
+ }
178
+
179
+ // If we reach here, use the vault path directly
180
+ return getVaultPath(vaultPath);
168
181
  }
169
182
 
170
- async function createBuildContext(buildPath: string, isProd: boolean, entryPoints: string[], hasSass: boolean): Promise<esbuild.BuildContext> {
171
- const plugins = [
172
- // Add SASS plugin if SCSS files are detected
173
- ...(hasSass ? [
174
- await (async () => {
175
- try {
176
- // @ts-expect-error - esbuild-sass-plugin is installed during injection
177
- const { sassPlugin } = await import('esbuild-sass-plugin');
178
- return sassPlugin({
179
- syntax: 'scss',
180
- style: 'expanded',
181
- });
182
- } catch (error) {
183
- console.warn('⚠️ esbuild-sass-plugin not found. Install it with: yarn add -D esbuild-sass-plugin');
184
- throw error;
185
- }
186
- })(),
187
- {
188
- name: 'remove-main-css',
189
- setup(build: esbuild.PluginBuild): void {
190
- build.onEnd(async (result) => {
191
- if (result.errors.length === 0) {
192
- await removeMainCss(buildPath);
193
- }
194
- });
195
- },
196
- }
197
- ] : []),
198
- {
199
- name: "copy-to-plugins-folder",
200
- setup: (build: esbuild.PluginBuild): void => {
201
- build.onEnd(async () => {
202
- // if real or build
203
- if (isProd) {
204
- if (process.argv.includes("-r") || process.argv.includes("real")) {
205
- await copyFilesToTargetDir(buildPath);
206
- console.log(`Successfully installed in ${buildPath}`);
207
- } else {
208
- const folderToRemove = path.join(buildPath, "_.._");
209
- if (await isValidPath(folderToRemove)) {
210
- await rm(folderToRemove, { recursive: true });
211
- }
212
- console.log("Built done in initial folder");
213
- }
214
- }
215
- // if watch (dev)
216
- else {
217
- await copyFilesToTargetDir(buildPath);
218
- }
219
- });
220
- }
221
- }
222
- ];
223
-
224
- return await esbuild.context({
225
- banner: { js: BANNER },
226
- minify: isProd,
227
- entryPoints,
228
- bundle: true,
229
- external: EXTERNAL_DEPS,
230
- format: "cjs",
231
- target: "esNext",
232
- platform: "node",
233
- logLevel: "info",
234
- sourcemap: isProd ? false : "inline",
235
- treeShaking: true,
236
- outdir: buildPath,
237
- outbase: path.join(pluginDir, "src"),
238
- plugins
239
- });
183
+ async function createBuildContext(
184
+ buildPath: string,
185
+ isProd: boolean,
186
+ entryPoints: string[],
187
+ hasSass: boolean
188
+ ): Promise<esbuild.BuildContext> {
189
+ const plugins = [
190
+ // Add SASS plugin if SCSS files are detected
191
+ ...(hasSass
192
+ ? [
193
+ await (async () => {
194
+ try {
195
+ // @ts-expect-error - esbuild-sass-plugin is installed during injection
196
+ const { sassPlugin } = await import('esbuild-sass-plugin');
197
+ return sassPlugin({
198
+ syntax: 'scss',
199
+ style: 'expanded'
200
+ });
201
+ } catch (error) {
202
+ console.warn(
203
+ '⚠️ esbuild-sass-plugin not found. Install it with: yarn add -D esbuild-sass-plugin'
204
+ );
205
+ throw error;
206
+ }
207
+ })(),
208
+ {
209
+ name: 'remove-main-css',
210
+ setup(build: esbuild.PluginBuild): void {
211
+ build.onEnd(async (result) => {
212
+ if (result.errors.length === 0) {
213
+ await removeMainCss(buildPath);
214
+ }
215
+ });
216
+ }
217
+ }
218
+ ]
219
+ : []),
220
+ {
221
+ name: 'copy-to-plugins-folder',
222
+ setup: (build: esbuild.PluginBuild): void => {
223
+ build.onEnd(async () => {
224
+ // if real or build
225
+ if (isProd) {
226
+ if (
227
+ process.argv.includes('-r') ||
228
+ process.argv.includes('real')
229
+ ) {
230
+ await copyFilesToTargetDir(buildPath);
231
+ console.log(`Successfully installed in ${buildPath}`);
232
+ } else {
233
+ const folderToRemove = path.join(buildPath, '_.._');
234
+ if (await isValidPath(folderToRemove)) {
235
+ await rm(folderToRemove, { recursive: true });
236
+ }
237
+ console.log('Built done in initial folder');
238
+ }
239
+ }
240
+ // if watch (dev)
241
+ else {
242
+ await copyFilesToTargetDir(buildPath);
243
+ }
244
+ });
245
+ }
246
+ }
247
+ ];
248
+
249
+ return await esbuild.context({
250
+ banner: { js: BANNER },
251
+ minify: isProd,
252
+ entryPoints,
253
+ bundle: true,
254
+ external: EXTERNAL_DEPS,
255
+ format: 'cjs',
256
+ target: 'esNext',
257
+ platform: 'node',
258
+ logLevel: 'info',
259
+ sourcemap: isProd ? false : 'inline',
260
+ treeShaking: true,
261
+ outdir: buildPath,
262
+ outbase: path.join(pluginDir, 'src'),
263
+ plugins
264
+ });
240
265
  }
241
266
 
242
267
  async function main(): Promise<void> {
243
- try {
244
- await validateEnvironment();
245
- const isProd = process.argv[2] === "production";
246
- const buildPath = await getBuildPath(isProd);
247
- console.log(buildPath === pluginDir
248
- ? "Building in initial folder"
249
- : `Building in ${buildPath}`);
250
-
251
- // Check for SCSS first, then CSS in src, then in root
252
- const srcStylesScssPath = path.join(pluginDir, "src/styles.scss");
253
- const srcStylesPath = path.join(pluginDir, "src/styles.css");
254
- const rootStylesPath = path.join(pluginDir, "styles.css");
255
-
256
- const scssExists = await isValidPath(srcStylesScssPath);
257
- const stylePath = scssExists ? srcStylesScssPath :
258
- await isValidPath(srcStylesPath) ? srcStylesPath :
259
- await isValidPath(rootStylesPath) ? rootStylesPath : "";
260
-
261
- const mainTsPath = path.join(pluginDir, "src/main.ts");
262
- const entryPoints = stylePath ? [mainTsPath, stylePath] : [mainTsPath];
263
- const context = await createBuildContext(buildPath, isProd, entryPoints, scssExists);
264
-
265
- if (isProd) {
266
- await context.rebuild();
267
- rl.close();
268
- process.exit(0);
269
- } else {
270
- await context.watch();
271
- }
272
- } catch (error) {
273
- console.error("Build failed:", error);
274
- rl.close();
275
- process.exit(1);
276
- }
268
+ try {
269
+ await validateEnvironment();
270
+ const isProd = process.argv[2] === 'production';
271
+ const buildPath = await getBuildPath(isProd);
272
+ console.log(
273
+ buildPath === pluginDir
274
+ ? 'Building in initial folder'
275
+ : `Building in ${buildPath}`
276
+ );
277
+
278
+ // Check for SCSS first, then CSS in src, then in root
279
+ const srcStylesScssPath = path.join(pluginDir, 'src/styles.scss');
280
+ const srcStylesPath = path.join(pluginDir, 'src/styles.css');
281
+ const rootStylesPath = path.join(pluginDir, 'styles.css');
282
+
283
+ const scssExists = await isValidPath(srcStylesScssPath);
284
+ const stylePath = scssExists
285
+ ? srcStylesScssPath
286
+ : (await isValidPath(srcStylesPath))
287
+ ? srcStylesPath
288
+ : (await isValidPath(rootStylesPath))
289
+ ? rootStylesPath
290
+ : '';
291
+
292
+ const mainTsPath = path.join(pluginDir, 'src/main.ts');
293
+ const entryPoints = stylePath ? [mainTsPath, stylePath] : [mainTsPath];
294
+ const context = await createBuildContext(
295
+ buildPath,
296
+ isProd,
297
+ entryPoints,
298
+ scssExists
299
+ );
300
+
301
+ if (isProd) {
302
+ await context.rebuild();
303
+ rl.close();
304
+ process.exit(0);
305
+ } else {
306
+ await context.watch();
307
+ }
308
+ } catch (error) {
309
+ console.error('Build failed:', error);
310
+ rl.close();
311
+ process.exit(1);
312
+ }
277
313
  }
278
314
 
279
315
  main().catch(console.error);