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 +41 -1
- package/dist/commands/migrate.js +122 -69
- package/dist/commands/setup.js +36 -4
- package/dist/defaults/src/_config.yml +3 -3
- package/dist/defaults/src/_includes/frontend/sections/footer.json +1 -1
- package/dist/index.js +8 -5
- package/package.json +1 -1
- package/dist/defaults/src/pages/about.md +0 -7
- package/dist/defaults/src/pages/pricing.md +0 -7
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
|
|
package/dist/commands/migrate.js
CHANGED
|
@@ -41,47 +41,47 @@ async function migratePosts() {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
const targetExists = jetpack.exists(targetPath);
|
|
44
|
+
logger.log(`Migrating _posts from root to src/...`);
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
if (sourceFiles.length === 0) {
|
|
50
|
+
logger.log('No files found in _posts directory');
|
|
51
|
+
jetpack.remove(sourcePath);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
let movedCount = 0;
|
|
56
|
+
let overwrittenCount = 0;
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
logger.log(` Source: ${sourcePath}`);
|
|
68
|
-
logger.log(` Target: ${targetPath}`);
|
|
63
|
+
// Check if target exists
|
|
64
|
+
const targetExists = jetpack.exists(targetFile);
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
// Ensure parent directory exists
|
|
67
|
+
jetpack.dir(path.dirname(targetFile));
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
// Move the file (this overwrites if target exists)
|
|
70
|
+
jetpack.move(sourceFile, targetFile, { overwrite: true });
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
if (targetExists) {
|
|
73
|
+
overwrittenCount++;
|
|
74
|
+
logger.log(` ✓ Overwrote: ${relativePath}`);
|
|
75
|
+
} else {
|
|
76
|
+
movedCount++;
|
|
77
|
+
logger.log(` ✓ Moved: ${relativePath}`);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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.
|
|
119
|
-
conflicts.slice(0, 10).forEach((file) => logger.
|
|
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.
|
|
148
|
+
logger.error(` ... and ${conflicts.length - 10} more`);
|
|
122
149
|
}
|
|
123
|
-
throw new Error('Cannot migrate assets:
|
|
150
|
+
throw new Error('Cannot migrate assets: duplicate files with different content detected. Please resolve manually.');
|
|
124
151
|
}
|
|
125
152
|
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
//
|
|
139
|
-
jetpack.
|
|
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(
|
|
195
|
+
logger.log(logger.format.green(`✓ Successfully merged assets: ${movedCount} moved, ${identicalCount} identical files skipped`));
|
|
142
196
|
} else {
|
|
143
|
-
//
|
|
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
|
|
353
|
-
const
|
|
405
|
+
// Check if directory has any FILES (not just subdirectories)
|
|
406
|
+
const files = jetpack.find(dirPath, { matching: '**/*', directories: false }) || [];
|
|
354
407
|
|
|
355
|
-
if (
|
|
356
|
-
// Directory
|
|
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
|
|
414
|
+
logger.warn(` ⚠ ${name} directory still exists with ${files.length} file(s)`);
|
|
362
415
|
logger.warn(` Please manually review: ${dirPath}`);
|
|
363
416
|
}
|
|
364
417
|
});
|
package/dist/commands/setup.js
CHANGED
|
@@ -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('
|
|
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: "#
|
|
89
|
+
background: "#237afc"
|
|
90
90
|
text: "#fff"
|
|
91
91
|
button:
|
|
92
92
|
background: "#fff"
|
|
93
|
-
text: "#
|
|
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: "#
|
|
101
|
+
background: "#237afc"
|
|
102
102
|
text: "#fff"
|
|
103
103
|
sentry:
|
|
104
104
|
enabled: true
|
package/dist/index.js
CHANGED
|
@@ -62,7 +62,10 @@ class Manager {
|
|
|
62
62
|
);
|
|
63
63
|
|
|
64
64
|
/* @dev-only:start */
|
|
65
|
-
|
|
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
|
|
80
|
+
console.warn(`Page-specific module missing: #main/${pageModulePathFull}`);
|
|
78
81
|
} else {
|
|
79
|
-
console.error(`Page module #main
|
|
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(`
|
|
95
|
+
console.warn(`Page-specific module missing: #project/${pageModulePathFull}`);
|
|
93
96
|
} else {
|
|
94
|
-
console.error(`
|
|
97
|
+
console.error(`Page-specific module error: #project/${pageModulePathFull}`, e);
|
|
95
98
|
}
|
|
96
99
|
})
|
|
97
100
|
);
|
package/package.json
CHANGED