ultimate-jekyll-manager 0.0.110 → 0.0.112

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/CLAUDE.md CHANGED
@@ -17,15 +17,55 @@ The "consuming" project has the following structure:
17
17
  ## Local Development
18
18
  When working with a consuming project, the local development server URL can be found in the `.temp/_config_browsersync.yml` file in the consuming project's root directory. You should read this file to determine the correct local URL for browsing and testing the site.
19
19
 
20
- Other Ultimate Jekyll Components:
20
+ ## Other Ultimate Jekyll Components:
21
21
  src/assets/css/ultimate-jekyll-manager.scss = Main stylesheet used by Ultimate Jekyll to style the site
22
22
  src/assets/css/global = Global styles that are used by Ultimate Jekyll
23
23
  src/assets/css/pages = Page-specific styles that are used by Ultimate Jekyll
24
24
  * If you are making a page, put the styles in this directory like so: `src/assets/css/pages/[page-name]/index.scss`
25
25
 
26
+ src/assets/css/main.scss
27
+ * This file runs on EVERY page and should be edited to contain site-wide CSS styles.
28
+
29
+
26
30
  src/assets/js/ultimate-jekyll-manager.js = Main JavaScript file used by Ultimate Jekyll to manage the site
27
31
  src/assets/js/pages = Page-specific JavaScript files that are used by Ultimate Jekyll
28
32
  * If you are making a page, put the JavaScript in this directory like so: `src/assets/js/pages/[page-name]/index.js`
33
+ * The page-specific JS and CSS files are automatically included in the page based on the page's canonical path.
34
+ * You need to use our standardized structure:
35
+ * Notice how how the helpers are outside the main export function.
36
+ ```js
37
+ /**
38
+ * XXX Page JavaScript
39
+ */
40
+
41
+ // Libraries
42
+ let webManager = null;
43
+
44
+ // Module
45
+ export default (Manager) => {
46
+ return new Promise(async function (resolve) {
47
+ // Shortcuts
48
+ webManager = Manager.webManager;
49
+
50
+ // Initialize when DOM is ready
51
+ await webManager.dom().ready();
52
+
53
+ // We just need to pause videos when switching tabs for better UX
54
+ helper1();
55
+
56
+ // Resolve after initialization
57
+ return resolve();
58
+ });
59
+ };
60
+
61
+ // Helper functions
62
+ function helper1() {
63
+ // ...
64
+ }
65
+ ```
66
+
67
+ /src/assets/js/main.js
68
+ * This file runs on EVERY page and should be edited to contain site-wide JavaScript functionality.
29
69
 
30
70
  src/assets/themes = Theme scss and js files that are can be picked and used by the consuming project.
31
71
 
@@ -41,47 +41,47 @@ async function migratePosts() {
41
41
  return;
42
42
  }
43
43
 
44
- // Check if target already exists
45
- const targetExists = jetpack.exists(targetPath);
44
+ logger.log(`Migrating _posts from root to src/...`);
46
45
 
47
- if (targetExists) {
48
- logger.warn(`Target directory ${targetPath} already exists!`);
49
- logger.log('Checking for conflicts...');
46
+ // Get all files recursively from source (not directories)
47
+ const sourceFiles = jetpack.find(sourcePath, { matching: '**/*', directories: false }) || [];
50
48
 
51
- // Get list of files in both directories
52
- const sourceFiles = jetpack.list(sourcePath) || [];
53
- const targetFiles = jetpack.list(targetPath) || [];
49
+ if (sourceFiles.length === 0) {
50
+ logger.log('No files found in _posts directory');
51
+ jetpack.remove(sourcePath);
52
+ return;
53
+ }
54
54
 
55
- // Find conflicts
56
- const conflicts = sourceFiles.filter((file) => targetFiles.includes(file));
55
+ let movedCount = 0;
56
+ let overwrittenCount = 0;
57
57
 
58
- if (conflicts.length > 0) {
59
- logger.warn(`Found ${conflicts.length} conflicting file(s):`);
60
- conflicts.forEach((file) => logger.warn(` - ${file}`));
61
- throw new Error('Cannot migrate _posts: conflicts detected. Please resolve manually.');
62
- }
63
- }
58
+ // Just move everything, overwrite if needed
59
+ sourceFiles.forEach((sourceFile) => {
60
+ const relativePath = path.relative(sourcePath, sourceFile);
61
+ const targetFile = path.join(targetPath, relativePath);
64
62
 
65
- // Log the migration
66
- logger.log(`Migrating _posts from root to src/...`);
67
- logger.log(` Source: ${sourcePath}`);
68
- logger.log(` Target: ${targetPath}`);
63
+ // Check if target exists
64
+ const targetExists = jetpack.exists(targetFile);
69
65
 
70
- // Ensure target directory exists
71
- jetpack.dir(path.dirname(targetPath));
66
+ // Ensure parent directory exists
67
+ jetpack.dir(path.dirname(targetFile));
72
68
 
73
- // Move the directory
74
- jetpack.move(sourcePath, targetPath);
69
+ // Move the file (this overwrites if target exists)
70
+ jetpack.move(sourceFile, targetFile, { overwrite: true });
75
71
 
76
- // Verify the move
77
- const moveSuccessful = jetpack.exists(targetPath)
78
- && !jetpack.exists(sourcePath);
72
+ if (targetExists) {
73
+ overwrittenCount++;
74
+ logger.log(` ✓ Overwrote: ${relativePath}`);
75
+ } else {
76
+ movedCount++;
77
+ logger.log(` ✓ Moved: ${relativePath}`);
78
+ }
79
+ });
79
80
 
80
- if (moveSuccessful) {
81
- logger.log(logger.format.green('✓ Successfully migrated _posts to src/_posts'));
82
- } else {
83
- throw new Error('Failed to migrate _posts directory');
84
- }
81
+ // Remove the source directory
82
+ jetpack.remove(sourcePath);
83
+
84
+ logger.log(logger.format.green(`✓ Successfully migrated _posts: ${movedCount} moved, ${overwrittenCount} overwritten`));
85
85
  }
86
86
 
87
87
  async function migrateAssets() {
@@ -100,47 +100,101 @@ async function migrateAssets() {
100
100
  const targetExists = jetpack.exists(targetPath);
101
101
 
102
102
  if (targetExists) {
103
- logger.warn(`Target directory ${targetPath} already exists!`);
104
- logger.log('Merging assets directories...');
105
-
106
- // Get list of files in both directories (recursively)
107
- const sourceFiles = jetpack.find(sourcePath, { matching: '**/*' }) || [];
108
- const targetFiles = jetpack.find(targetPath, { matching: '**/*' }) || [];
109
-
110
- // Convert to relative paths for comparison
111
- const sourceRelative = sourceFiles.map((f) => path.relative(sourcePath, f));
112
- const targetRelative = targetFiles.map((f) => path.relative(targetPath, f));
113
-
114
- // Find conflicts
115
- const conflicts = sourceRelative.filter((file) => targetRelative.includes(file));
103
+ logger.log(`Target directory ${targetPath} already exists - will merge contents...`);
104
+
105
+ // Get all files recursively from source (not directories)
106
+ const sourceFiles = jetpack.find(sourcePath, { matching: '**/*', directories: false }) || [];
107
+
108
+ let movedCount = 0;
109
+ let identicalCount = 0;
110
+ const conflicts = [];
111
+
112
+ // First pass: check for conflicts
113
+ sourceFiles.forEach((sourceFile) => {
114
+ const relativePath = path.relative(sourcePath, sourceFile);
115
+ const targetFile = path.join(targetPath, relativePath);
116
+
117
+ // Only care about file conflicts, not directory existence
118
+ if (jetpack.exists(targetFile) === 'file') {
119
+ // Check if files are identical
120
+ const sourceStats = jetpack.inspect(sourceFile);
121
+ const targetStats = jetpack.inspect(targetFile);
122
+
123
+ // Compare file sizes first (faster than reading content)
124
+ if (sourceStats.size !== targetStats.size) {
125
+ // Different sizes, definitely a conflict
126
+ conflicts.push(relativePath);
127
+ } else {
128
+ // Same size, need to compare content for small files
129
+ if (sourceStats.size < 1024 * 1024) { // Less than 1MB
130
+ const sourceContent = jetpack.read(sourceFile, 'buffer');
131
+ const targetContent = jetpack.read(targetFile, 'buffer');
132
+
133
+ if (Buffer.compare(sourceContent, targetContent) !== 0) {
134
+ // Files differ - this is a real conflict
135
+ conflicts.push(relativePath);
136
+ }
137
+ }
138
+ // For large files with same size, we assume they're identical
139
+ }
140
+ }
141
+ });
116
142
 
143
+ // If we have actual file conflicts, throw error
117
144
  if (conflicts.length > 0) {
118
- logger.warn(`Found ${conflicts.length} conflicting file(s):`);
119
- conflicts.slice(0, 10).forEach((file) => logger.warn(` - ${file}`));
145
+ logger.error(`Found ${conflicts.length} conflicting file(s) with different content:`);
146
+ conflicts.slice(0, 10).forEach((file) => logger.error(` - ${file}`));
120
147
  if (conflicts.length > 10) {
121
- logger.warn(` ... and ${conflicts.length - 10} more`);
148
+ logger.error(` ... and ${conflicts.length - 10} more`);
122
149
  }
123
- throw new Error('Cannot migrate assets: conflicts detected. Please resolve manually.');
150
+ throw new Error('Cannot migrate assets: duplicate files with different content detected. Please resolve manually.');
124
151
  }
125
152
 
126
- // Move all files from source to target
127
- logger.log('Moving files...');
128
- sourceRelative.forEach((file) => {
129
- const src = path.join(sourcePath, file);
130
- const dest = path.join(targetPath, file);
131
-
132
- // Only move files, not directories
133
- if (jetpack.exists(src) === 'file') {
134
- jetpack.move(src, dest);
153
+ // No conflicts, proceed with migration
154
+ sourceFiles.forEach((sourceFile) => {
155
+ const relativePath = path.relative(sourcePath, sourceFile);
156
+ const targetFile = path.join(targetPath, relativePath);
157
+
158
+ if (jetpack.exists(targetFile) === 'file') {
159
+ // Files are identical (we checked above), just remove source
160
+ jetpack.remove(sourceFile);
161
+ identicalCount++;
162
+ logger.log(` ✓ Skipped identical file: ${relativePath}`);
163
+ } else {
164
+ // No file conflict, move it (directory will be created if needed)
165
+ jetpack.dir(path.dirname(targetFile));
166
+ jetpack.move(sourceFile, targetFile);
167
+ movedCount++;
168
+ logger.log(` ✓ Moved: ${relativePath}`);
135
169
  }
136
170
  });
137
171
 
138
- // Remove the old assets directory
139
- jetpack.remove(sourcePath);
172
+ // Clean up empty directories in source
173
+ const remainingItems = jetpack.list(sourcePath) || [];
174
+ if (remainingItems.length === 0) {
175
+ jetpack.remove(sourcePath);
176
+ logger.log(` ✓ Removed empty source directory`);
177
+ } else {
178
+ // Try to clean up empty subdirectories
179
+ const remainingDirs = jetpack.find(sourcePath, { matching: '*/', directories: true, files: false }) || [];
180
+ remainingDirs.reverse().forEach((dir) => {
181
+ const contents = jetpack.list(dir) || [];
182
+ if (contents.length === 0) {
183
+ jetpack.remove(dir);
184
+ }
185
+ });
186
+
187
+ // Check again if root is empty
188
+ const finalCheck = jetpack.list(sourcePath) || [];
189
+ if (finalCheck.length === 0) {
190
+ jetpack.remove(sourcePath);
191
+ logger.log(` ✓ Removed empty source directory after cleanup`);
192
+ }
193
+ }
140
194
 
141
- logger.log(logger.format.green('✓ Successfully merged assets into src/assets'));
195
+ logger.log(logger.format.green(`✓ Successfully merged assets: ${movedCount} moved, ${identicalCount} identical files skipped`));
142
196
  } else {
143
- // Log the migration
197
+ // Simple move when target doesn't exist
144
198
  logger.log(`Migrating assets from root to src/...`);
145
199
  logger.log(` Source: ${sourcePath}`);
146
200
  logger.log(` Target: ${targetPath}`);
@@ -152,8 +206,7 @@ async function migrateAssets() {
152
206
  jetpack.move(sourcePath, targetPath);
153
207
 
154
208
  // Verify the move
155
- const moveSuccessful = jetpack.exists(targetPath)
156
- && !jetpack.exists(sourcePath);
209
+ const moveSuccessful = jetpack.exists(targetPath) && !jetpack.exists(sourcePath);
157
210
 
158
211
  if (moveSuccessful) {
159
212
  logger.log(logger.format.green('✓ Successfully migrated assets to src/assets'));
@@ -349,16 +402,16 @@ async function cleanupOldDirectories() {
349
402
  return;
350
403
  }
351
404
 
352
- // Check if directory is empty
353
- const contents = jetpack.list(dirPath) || [];
405
+ // Check if directory has any FILES (not just subdirectories)
406
+ const files = jetpack.find(dirPath, { matching: '**/*', directories: false }) || [];
354
407
 
355
- if (contents.length === 0) {
356
- // Directory is empty, delete it
408
+ if (files.length === 0) {
409
+ // Directory has no files (might have empty subdirectories), delete it
357
410
  jetpack.remove(dirPath);
358
411
  logger.log(` ✓ Deleted empty ${name} directory`);
359
412
  deletedCount++;
360
413
  } else {
361
- logger.warn(` ⚠ ${name} directory still exists and is not empty (${contents.length} item(s))`);
414
+ logger.warn(` ⚠ ${name} directory still exists with ${files.length} file(s)`);
362
415
  logger.warn(` Please manually review: ${dirPath}`);
363
416
  }
364
417
  });
@@ -412,6 +412,9 @@ async function fetchFirebaseAuth() {
412
412
  r = file.replace(r);
413
413
  }
414
414
 
415
+ // Log success for this file
416
+ logger.log(`Fetched: ${file.remote}`);
417
+
415
418
  // Write to file
416
419
  jetpack.write(finalPath,
417
420
  '---\n'
@@ -421,14 +424,43 @@ async function fetchFirebaseAuth() {
421
424
  + r
422
425
  )
423
426
  })
427
+ .catch((error) => {
428
+ // Only log the filename that failed, not the error content
429
+ logger.error(`❌ Failed to fetch: ${file.remote}`);
430
+ logger.error(` URL: ${url}`);
431
+
432
+ // Check if it's a specific type of error (not HTML response)
433
+ // Use regex to check case-insensitive for HTML content
434
+ const htmlPattern = /<!doctype|<html|<head|<body/i;
435
+ if (error.message && !htmlPattern.test(error.message)) {
436
+ logger.error(` Error: ${error.message}`);
437
+ }
438
+
439
+ // Re-throw to make Promise.all fail
440
+ throw new Error(`Failed to fetch Firebase auth file: ${file.remote}`);
441
+ })
424
442
  );
425
443
  });
426
444
 
427
- // Await all promises
428
- await Promise.all(promises);
429
-
430
445
  // Log
431
- logger.log('Fetched firebase-auth files');
446
+ logger.log('Fetching firebase-auth files...');
447
+
448
+ try {
449
+ // Await all promises
450
+ await Promise.all(promises);
451
+
452
+ // Log success
453
+ logger.log('✅ Fetched firebase-auth files');
454
+ } catch (error) {
455
+ // Check if we should skip Firebase auth errors
456
+ if (process.env.UJ_SKIP_FIREBASE_AUTH_ERRORS === 'true') {
457
+ logger.warn('⚠️ Failed to fetch some Firebase auth files, but continuing due to UJ_SKIP_FIREBASE_AUTH_ERRORS=true');
458
+ return;
459
+ }
460
+
461
+ // Error already logged above, just throw to stop execution
462
+ throw new Error('Failed to fetch one or more Firebase auth files. Please check your Firebase project configuration.');
463
+ }
432
464
  }
433
465
 
434
466
  function logVersionCheck(name, installedVersion, latestVersion, isUpToDate) {
@@ -86,11 +86,11 @@ web_manager:
86
86
  config:
87
87
  palette:
88
88
  popup:
89
- background: "#fd5631"
89
+ background: "#237afc"
90
90
  text: "#fff"
91
91
  button:
92
92
  background: "#fff"
93
- text: "#fd5631"
93
+ text: "#237afc"
94
94
  chatsy:
95
95
  enabled: true
96
96
  config:
@@ -98,7 +98,7 @@ web_manager:
98
98
  chatId: ""
99
99
  settings:
100
100
  openChatButton:
101
- background: "#fd5631"
101
+ background: "#237afc"
102
102
  text: "#fff"
103
103
  sentry:
104
104
  enabled: true
@@ -2,7 +2,7 @@
2
2
  logo: {
3
3
  href: '/',
4
4
  class: 'filter-adaptive',
5
- description: '{{ site.brand.description }}',
5
+ description: '{{ site.meta.description }}',
6
6
  },
7
7
  links: [
8
8
  {
package/dist/index.js CHANGED
@@ -62,7 +62,10 @@ class Manager {
62
62
  );
63
63
 
64
64
  /* @dev-only:start */
65
- console.log(`Page module loading (${pageModulePathFull})`);
65
+ {
66
+ console.log(`Page-specific module loading: #main/${pageModulePathFull}`);
67
+ console.log(`Page-specific module loading: #project/${pageModulePathFull}`);
68
+ }
66
69
  /* @dev-only:end */
67
70
 
68
71
  // Load page-specific scripts
@@ -74,9 +77,9 @@ class Manager {
74
77
  })
75
78
  .catch(e => {
76
79
  if (this.isNotFound(e, pageModulePath)) {
77
- console.warn(`Page module #main not found (${pageModulePathFull})`);
80
+ console.warn(`Page-specific module missing: #main/${pageModulePathFull}`);
78
81
  } else {
79
- console.error(`Page module #main error (${pageModulePathFull})`, e);
82
+ console.error(`Page-specific module error: #main/${pageModulePathFull}`, e);
80
83
  }
81
84
  })
82
85
  );
@@ -89,9 +92,9 @@ class Manager {
89
92
  })
90
93
  .catch(e => {
91
94
  if (this.isNotFound(e, pageModulePath)) {
92
- console.warn(`Project module #project not found (${pageModulePathFull})`);
95
+ console.warn(`Page-specific module missing: #project/${pageModulePathFull}`);
93
96
  } else {
94
- console.error(`Project module #project error (${pageModulePathFull})`, e);
97
+ console.error(`Page-specific module error: #project/${pageModulePathFull}`, e);
95
98
  }
96
99
  })
97
100
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-jekyll-manager",
3
- "version": "0.0.110",
3
+ "version": "0.0.112",
4
4
  "description": "Ultimate Jekyll dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -1,7 +0,0 @@
1
- ---
2
- ### ALL PAGES ###
3
- layout: blueprint/about
4
- permalink: /about
5
-
6
- ### REGULAR PAGES ###
7
- ---
@@ -1,7 +0,0 @@
1
- ---
2
- ### ALL PAGES ###
3
- layout: blueprint/pricing
4
- permalink: /pricing
5
-
6
- ### REGULAR PAGES ###
7
- ---