bunki 0.16.2 → 0.17.0
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/README.md +141 -15
- package/dist/cli/commands/templates/archive-njk.d.ts +4 -0
- package/dist/cli/commands/templates/base-njk.d.ts +4 -0
- package/dist/cli/commands/templates/default-css.d.ts +4 -0
- package/dist/cli/commands/templates/index-njk.d.ts +4 -0
- package/dist/cli/commands/templates/index.d.ts +14 -0
- package/dist/cli/commands/templates/post-njk.d.ts +4 -0
- package/dist/cli/commands/templates/sample-post.d.ts +4 -0
- package/dist/cli/commands/templates/tag-njk.d.ts +4 -0
- package/dist/cli/commands/templates/tags-njk.d.ts +4 -0
- package/dist/cli/commands/validate.d.ts +0 -3
- package/dist/cli.js +1636 -1530
- package/dist/generators/assets.d.ts +16 -0
- package/dist/generators/feeds.d.ts +32 -0
- package/dist/generators/pages.d.ts +48 -0
- package/dist/index.js +913 -830
- package/dist/site-generator.d.ts +22 -22
- package/dist/utils/build-metrics.d.ts +52 -0
- package/dist/utils/css-processor.d.ts +10 -1
- package/dist/utils/markdown/constants.d.ts +16 -0
- package/dist/utils/markdown/parser.d.ts +32 -0
- package/dist/utils/markdown/validators.d.ts +31 -0
- package/dist/utils/markdown-utils.d.ts +16 -11
- package/dist/utils/pagination.d.ts +38 -0
- package/dist/utils/xml-builder.d.ts +42 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2133,11 +2133,11 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
2133
2133
|
function lookupEscape(ch) {
|
|
2134
2134
|
return escapeMap[ch];
|
|
2135
2135
|
}
|
|
2136
|
-
function _prettifyError(
|
|
2136
|
+
function _prettifyError(path5, withInternals, err) {
|
|
2137
2137
|
if (!err.Update) {
|
|
2138
2138
|
err = new _exports.TemplateError(err);
|
|
2139
2139
|
}
|
|
2140
|
-
err.Update(
|
|
2140
|
+
err.Update(path5);
|
|
2141
2141
|
if (!withInternals) {
|
|
2142
2142
|
var old = err;
|
|
2143
2143
|
err = new Error(old.message);
|
|
@@ -2198,8 +2198,8 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
2198
2198
|
err.lineno = lineno;
|
|
2199
2199
|
err.colno = colno;
|
|
2200
2200
|
err.firstUpdate = true;
|
|
2201
|
-
err.Update = function Update(
|
|
2202
|
-
var msg = "(" + (
|
|
2201
|
+
err.Update = function Update(path5) {
|
|
2202
|
+
var msg = "(" + (path5 || "unknown path") + ")";
|
|
2203
2203
|
if (this.firstUpdate) {
|
|
2204
2204
|
if (this.lineno && this.colno) {
|
|
2205
2205
|
msg += " [Line " + this.lineno + ", Column " + this.colno + "]";
|
|
@@ -6396,7 +6396,7 @@ var require_loader = __commonJS((exports, module) => {
|
|
|
6396
6396
|
};
|
|
6397
6397
|
return _setPrototypeOf(o, p);
|
|
6398
6398
|
}
|
|
6399
|
-
var
|
|
6399
|
+
var path5 = __require("path");
|
|
6400
6400
|
var _require = require_object();
|
|
6401
6401
|
var EmitterObj = _require.EmitterObj;
|
|
6402
6402
|
module.exports = /* @__PURE__ */ function(_EmitterObj) {
|
|
@@ -6406,7 +6406,7 @@ var require_loader = __commonJS((exports, module) => {
|
|
|
6406
6406
|
}
|
|
6407
6407
|
var _proto = Loader.prototype;
|
|
6408
6408
|
_proto.resolve = function resolve(from, to) {
|
|
6409
|
-
return
|
|
6409
|
+
return path5.resolve(path5.dirname(from), to);
|
|
6410
6410
|
};
|
|
6411
6411
|
_proto.isRelative = function isRelative(filename) {
|
|
6412
6412
|
return filename.indexOf("./") === 0 || filename.indexOf("../") === 0;
|
|
@@ -6460,7 +6460,7 @@ var require_precompiled_loader = __commonJS((exports, module) => {
|
|
|
6460
6460
|
|
|
6461
6461
|
// node_modules/picomatch/lib/constants.js
|
|
6462
6462
|
var require_constants = __commonJS((exports, module) => {
|
|
6463
|
-
var
|
|
6463
|
+
var path5 = __require("path");
|
|
6464
6464
|
var WIN_SLASH = "\\\\/";
|
|
6465
6465
|
var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
6466
6466
|
var DOT_LITERAL = "\\.";
|
|
@@ -6582,7 +6582,7 @@ var require_constants = __commonJS((exports, module) => {
|
|
|
6582
6582
|
CHAR_UNDERSCORE: 95,
|
|
6583
6583
|
CHAR_VERTICAL_LINE: 124,
|
|
6584
6584
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
|
|
6585
|
-
SEP:
|
|
6585
|
+
SEP: path5.sep,
|
|
6586
6586
|
extglobChars(chars) {
|
|
6587
6587
|
return {
|
|
6588
6588
|
"!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` },
|
|
@@ -6600,7 +6600,7 @@ var require_constants = __commonJS((exports, module) => {
|
|
|
6600
6600
|
|
|
6601
6601
|
// node_modules/picomatch/lib/utils.js
|
|
6602
6602
|
var require_utils = __commonJS((exports) => {
|
|
6603
|
-
var
|
|
6603
|
+
var path5 = __require("path");
|
|
6604
6604
|
var win32 = process.platform === "win32";
|
|
6605
6605
|
var {
|
|
6606
6606
|
REGEX_BACKSLASH,
|
|
@@ -6629,7 +6629,7 @@ var require_utils = __commonJS((exports) => {
|
|
|
6629
6629
|
if (options2 && typeof options2.windows === "boolean") {
|
|
6630
6630
|
return options2.windows;
|
|
6631
6631
|
}
|
|
6632
|
-
return win32 === true ||
|
|
6632
|
+
return win32 === true || path5.sep === "\\";
|
|
6633
6633
|
};
|
|
6634
6634
|
exports.escapeLast = (input, char, lastIdx) => {
|
|
6635
6635
|
const idx = input.lastIndexOf(char, lastIdx);
|
|
@@ -7753,7 +7753,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
7753
7753
|
|
|
7754
7754
|
// node_modules/picomatch/lib/picomatch.js
|
|
7755
7755
|
var require_picomatch = __commonJS((exports, module) => {
|
|
7756
|
-
var
|
|
7756
|
+
var path5 = __require("path");
|
|
7757
7757
|
var scan = require_scan();
|
|
7758
7758
|
var parse2 = require_parse();
|
|
7759
7759
|
var utils = require_utils();
|
|
@@ -7839,7 +7839,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
7839
7839
|
};
|
|
7840
7840
|
picomatch.matchBase = (input, glob, options2, posix = utils.isWindows(options2)) => {
|
|
7841
7841
|
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options2);
|
|
7842
|
-
return regex.test(
|
|
7842
|
+
return regex.test(path5.basename(input));
|
|
7843
7843
|
};
|
|
7844
7844
|
picomatch.isMatch = (str2, patterns, options2) => picomatch(patterns, options2)(str2);
|
|
7845
7845
|
picomatch.parse = (pattern, options2) => {
|
|
@@ -7948,8 +7948,8 @@ var require_readdirp = __commonJS((exports, module) => {
|
|
|
7948
7948
|
static get defaultOptions() {
|
|
7949
7949
|
return {
|
|
7950
7950
|
root: ".",
|
|
7951
|
-
fileFilter: (
|
|
7952
|
-
directoryFilter: (
|
|
7951
|
+
fileFilter: (path5) => true,
|
|
7952
|
+
directoryFilter: (path5) => true,
|
|
7953
7953
|
type: FILE_TYPE,
|
|
7954
7954
|
lstat: false,
|
|
7955
7955
|
depth: 2147483648,
|
|
@@ -7968,7 +7968,7 @@ var require_readdirp = __commonJS((exports, module) => {
|
|
|
7968
7968
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
7969
7969
|
const statMethod = opts.lstat ? lstat : stat;
|
|
7970
7970
|
if (wantBigintFsStats) {
|
|
7971
|
-
this._stat = (
|
|
7971
|
+
this._stat = (path5) => statMethod(path5, { bigint: true });
|
|
7972
7972
|
} else {
|
|
7973
7973
|
this._stat = statMethod;
|
|
7974
7974
|
}
|
|
@@ -7990,9 +7990,9 @@ var require_readdirp = __commonJS((exports, module) => {
|
|
|
7990
7990
|
this.reading = true;
|
|
7991
7991
|
try {
|
|
7992
7992
|
while (!this.destroyed && batch > 0) {
|
|
7993
|
-
const { path:
|
|
7993
|
+
const { path: path5, depth, files = [] } = this.parent || {};
|
|
7994
7994
|
if (files.length > 0) {
|
|
7995
|
-
const slice = files.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
7995
|
+
const slice = files.splice(0, batch).map((dirent) => this._formatEntry(dirent, path5));
|
|
7996
7996
|
for (const entry of await Promise.all(slice)) {
|
|
7997
7997
|
if (this.destroyed)
|
|
7998
7998
|
return;
|
|
@@ -8029,20 +8029,20 @@ var require_readdirp = __commonJS((exports, module) => {
|
|
|
8029
8029
|
this.reading = false;
|
|
8030
8030
|
}
|
|
8031
8031
|
}
|
|
8032
|
-
async _exploreDir(
|
|
8032
|
+
async _exploreDir(path5, depth) {
|
|
8033
8033
|
let files;
|
|
8034
8034
|
try {
|
|
8035
|
-
files = await readdir(
|
|
8035
|
+
files = await readdir(path5, this._rdOptions);
|
|
8036
8036
|
} catch (error) {
|
|
8037
8037
|
this._onError(error);
|
|
8038
8038
|
}
|
|
8039
|
-
return { files, depth, path:
|
|
8039
|
+
return { files, depth, path: path5 };
|
|
8040
8040
|
}
|
|
8041
|
-
async _formatEntry(dirent,
|
|
8041
|
+
async _formatEntry(dirent, path5) {
|
|
8042
8042
|
let entry;
|
|
8043
8043
|
try {
|
|
8044
8044
|
const basename = this._isDirent ? dirent.name : dirent;
|
|
8045
|
-
const fullPath = sysPath.resolve(sysPath.join(
|
|
8045
|
+
const fullPath = sysPath.resolve(sysPath.join(path5, basename));
|
|
8046
8046
|
entry = { path: sysPath.relative(this._root, fullPath), fullPath, basename };
|
|
8047
8047
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
8048
8048
|
} catch (err) {
|
|
@@ -8131,24 +8131,24 @@ var require_normalize_path = __commonJS((exports, module) => {
|
|
|
8131
8131
|
* Copyright (c) 2014-2018, Jon Schlinkert.
|
|
8132
8132
|
* Released under the MIT License.
|
|
8133
8133
|
*/
|
|
8134
|
-
module.exports = function(
|
|
8135
|
-
if (typeof
|
|
8134
|
+
module.exports = function(path5, stripTrailing) {
|
|
8135
|
+
if (typeof path5 !== "string") {
|
|
8136
8136
|
throw new TypeError("expected path to be a string");
|
|
8137
8137
|
}
|
|
8138
|
-
if (
|
|
8138
|
+
if (path5 === "\\" || path5 === "/")
|
|
8139
8139
|
return "/";
|
|
8140
|
-
var len =
|
|
8140
|
+
var len = path5.length;
|
|
8141
8141
|
if (len <= 1)
|
|
8142
|
-
return
|
|
8142
|
+
return path5;
|
|
8143
8143
|
var prefix = "";
|
|
8144
|
-
if (len > 4 &&
|
|
8145
|
-
var ch =
|
|
8146
|
-
if ((ch === "?" || ch === ".") &&
|
|
8147
|
-
|
|
8144
|
+
if (len > 4 && path5[3] === "\\") {
|
|
8145
|
+
var ch = path5[2];
|
|
8146
|
+
if ((ch === "?" || ch === ".") && path5.slice(0, 2) === "\\\\") {
|
|
8147
|
+
path5 = path5.slice(2);
|
|
8148
8148
|
prefix = "//";
|
|
8149
8149
|
}
|
|
8150
8150
|
}
|
|
8151
|
-
var segs =
|
|
8151
|
+
var segs = path5.split(/[/\\]+/);
|
|
8152
8152
|
if (stripTrailing !== false && segs[segs.length - 1] === "") {
|
|
8153
8153
|
segs.pop();
|
|
8154
8154
|
}
|
|
@@ -8183,17 +8183,17 @@ var require_anymatch = __commonJS((exports, module) => {
|
|
|
8183
8183
|
if (!isList && typeof _path !== "string") {
|
|
8184
8184
|
throw new TypeError("anymatch: second argument must be a string: got " + Object.prototype.toString.call(_path));
|
|
8185
8185
|
}
|
|
8186
|
-
const
|
|
8186
|
+
const path5 = normalizePath(_path, false);
|
|
8187
8187
|
for (let index = 0;index < negPatterns.length; index++) {
|
|
8188
8188
|
const nglob = negPatterns[index];
|
|
8189
|
-
if (nglob(
|
|
8189
|
+
if (nglob(path5)) {
|
|
8190
8190
|
return returnIndex ? -1 : false;
|
|
8191
8191
|
}
|
|
8192
8192
|
}
|
|
8193
|
-
const applied = isList && [
|
|
8193
|
+
const applied = isList && [path5].concat(args.slice(1));
|
|
8194
8194
|
for (let index = 0;index < patterns.length; index++) {
|
|
8195
8195
|
const pattern = patterns[index];
|
|
8196
|
-
if (isList ? pattern(...applied) : pattern(
|
|
8196
|
+
if (isList ? pattern(...applied) : pattern(path5)) {
|
|
8197
8197
|
return returnIndex ? index : true;
|
|
8198
8198
|
}
|
|
8199
8199
|
}
|
|
@@ -9712,10 +9712,10 @@ var require_binary_extensions = __commonJS((exports, module) => {
|
|
|
9712
9712
|
|
|
9713
9713
|
// node_modules/is-binary-path/index.js
|
|
9714
9714
|
var require_is_binary_path = __commonJS((exports, module) => {
|
|
9715
|
-
var
|
|
9715
|
+
var path5 = __require("path");
|
|
9716
9716
|
var binaryExtensions = require_binary_extensions();
|
|
9717
9717
|
var extensions = new Set(binaryExtensions);
|
|
9718
|
-
module.exports = (filePath) => extensions.has(
|
|
9718
|
+
module.exports = (filePath) => extensions.has(path5.extname(filePath).slice(1).toLowerCase());
|
|
9719
9719
|
});
|
|
9720
9720
|
|
|
9721
9721
|
// node_modules/chokidar/lib/constants.js
|
|
@@ -9841,16 +9841,16 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9841
9841
|
};
|
|
9842
9842
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
9843
9843
|
var FsWatchInstances = new Map;
|
|
9844
|
-
function createFsWatchInstance(
|
|
9844
|
+
function createFsWatchInstance(path5, options2, listener, errHandler, emitRaw) {
|
|
9845
9845
|
const handleEvent = (rawEvent, evPath) => {
|
|
9846
|
-
listener(
|
|
9847
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
9848
|
-
if (evPath &&
|
|
9849
|
-
fsWatchBroadcast(sysPath.resolve(
|
|
9846
|
+
listener(path5);
|
|
9847
|
+
emitRaw(rawEvent, evPath, { watchedPath: path5 });
|
|
9848
|
+
if (evPath && path5 !== evPath) {
|
|
9849
|
+
fsWatchBroadcast(sysPath.resolve(path5, evPath), KEY_LISTENERS, sysPath.join(path5, evPath));
|
|
9850
9850
|
}
|
|
9851
9851
|
};
|
|
9852
9852
|
try {
|
|
9853
|
-
return fs2.watch(
|
|
9853
|
+
return fs2.watch(path5, options2, handleEvent);
|
|
9854
9854
|
} catch (error) {
|
|
9855
9855
|
errHandler(error);
|
|
9856
9856
|
}
|
|
@@ -9863,12 +9863,12 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9863
9863
|
listener(val1, val2, val3);
|
|
9864
9864
|
});
|
|
9865
9865
|
};
|
|
9866
|
-
var setFsWatchListener = (
|
|
9866
|
+
var setFsWatchListener = (path5, fullPath, options2, handlers) => {
|
|
9867
9867
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
9868
9868
|
let cont = FsWatchInstances.get(fullPath);
|
|
9869
9869
|
let watcher;
|
|
9870
9870
|
if (!options2.persistent) {
|
|
9871
|
-
watcher = createFsWatchInstance(
|
|
9871
|
+
watcher = createFsWatchInstance(path5, options2, listener, errHandler, rawEmitter);
|
|
9872
9872
|
return watcher.close.bind(watcher);
|
|
9873
9873
|
}
|
|
9874
9874
|
if (cont) {
|
|
@@ -9876,7 +9876,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9876
9876
|
addAndConvert(cont, KEY_ERR, errHandler);
|
|
9877
9877
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
9878
9878
|
} else {
|
|
9879
|
-
watcher = createFsWatchInstance(
|
|
9879
|
+
watcher = createFsWatchInstance(path5, options2, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
|
|
9880
9880
|
if (!watcher)
|
|
9881
9881
|
return;
|
|
9882
9882
|
watcher.on(EV_ERROR, async (error) => {
|
|
@@ -9884,7 +9884,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9884
9884
|
cont.watcherUnusable = true;
|
|
9885
9885
|
if (isWindows && error.code === "EPERM") {
|
|
9886
9886
|
try {
|
|
9887
|
-
const fd = await open(
|
|
9887
|
+
const fd = await open(path5, "r");
|
|
9888
9888
|
await close(fd);
|
|
9889
9889
|
broadcastErr(error);
|
|
9890
9890
|
} catch (err) {}
|
|
@@ -9914,7 +9914,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9914
9914
|
};
|
|
9915
9915
|
};
|
|
9916
9916
|
var FsWatchFileInstances = new Map;
|
|
9917
|
-
var setFsWatchFileListener = (
|
|
9917
|
+
var setFsWatchFileListener = (path5, fullPath, options2, handlers) => {
|
|
9918
9918
|
const { listener, rawEmitter } = handlers;
|
|
9919
9919
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
9920
9920
|
let listeners = new Set;
|
|
@@ -9940,7 +9940,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9940
9940
|
});
|
|
9941
9941
|
const currmtime = curr.mtimeMs;
|
|
9942
9942
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
9943
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
9943
|
+
foreach(cont.listeners, (listener2) => listener2(path5, curr));
|
|
9944
9944
|
}
|
|
9945
9945
|
})
|
|
9946
9946
|
};
|
|
@@ -9963,25 +9963,25 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9963
9963
|
this.fsw = fsW;
|
|
9964
9964
|
this._boundHandleError = (error) => fsW._handleError(error);
|
|
9965
9965
|
}
|
|
9966
|
-
_watchWithNodeFs(
|
|
9966
|
+
_watchWithNodeFs(path5, listener) {
|
|
9967
9967
|
const opts = this.fsw.options;
|
|
9968
|
-
const directory = sysPath.dirname(
|
|
9969
|
-
const basename = sysPath.basename(
|
|
9968
|
+
const directory = sysPath.dirname(path5);
|
|
9969
|
+
const basename = sysPath.basename(path5);
|
|
9970
9970
|
const parent = this.fsw._getWatchedDir(directory);
|
|
9971
9971
|
parent.add(basename);
|
|
9972
|
-
const absolutePath = sysPath.resolve(
|
|
9972
|
+
const absolutePath = sysPath.resolve(path5);
|
|
9973
9973
|
const options2 = { persistent: opts.persistent };
|
|
9974
9974
|
if (!listener)
|
|
9975
9975
|
listener = EMPTY_FN;
|
|
9976
9976
|
let closer;
|
|
9977
9977
|
if (opts.usePolling) {
|
|
9978
9978
|
options2.interval = opts.enableBinaryInterval && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
|
|
9979
|
-
closer = setFsWatchFileListener(
|
|
9979
|
+
closer = setFsWatchFileListener(path5, absolutePath, options2, {
|
|
9980
9980
|
listener,
|
|
9981
9981
|
rawEmitter: this.fsw._emitRaw
|
|
9982
9982
|
});
|
|
9983
9983
|
} else {
|
|
9984
|
-
closer = setFsWatchListener(
|
|
9984
|
+
closer = setFsWatchListener(path5, absolutePath, options2, {
|
|
9985
9985
|
listener,
|
|
9986
9986
|
errHandler: this._boundHandleError,
|
|
9987
9987
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -9999,7 +9999,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
9999
9999
|
let prevStats = stats;
|
|
10000
10000
|
if (parent.has(basename))
|
|
10001
10001
|
return;
|
|
10002
|
-
const listener = async (
|
|
10002
|
+
const listener = async (path5, newStats) => {
|
|
10003
10003
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
10004
10004
|
return;
|
|
10005
10005
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -10013,9 +10013,9 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10013
10013
|
this.fsw._emit(EV_CHANGE, file, newStats2);
|
|
10014
10014
|
}
|
|
10015
10015
|
if (isLinux && prevStats.ino !== newStats2.ino) {
|
|
10016
|
-
this.fsw._closeFile(
|
|
10016
|
+
this.fsw._closeFile(path5);
|
|
10017
10017
|
prevStats = newStats2;
|
|
10018
|
-
this.fsw._addPathCloser(
|
|
10018
|
+
this.fsw._addPathCloser(path5, this._watchWithNodeFs(file, listener));
|
|
10019
10019
|
} else {
|
|
10020
10020
|
prevStats = newStats2;
|
|
10021
10021
|
}
|
|
@@ -10039,7 +10039,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10039
10039
|
}
|
|
10040
10040
|
return closer;
|
|
10041
10041
|
}
|
|
10042
|
-
async _handleSymlink(entry, directory,
|
|
10042
|
+
async _handleSymlink(entry, directory, path5, item) {
|
|
10043
10043
|
if (this.fsw.closed) {
|
|
10044
10044
|
return;
|
|
10045
10045
|
}
|
|
@@ -10049,7 +10049,7 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10049
10049
|
this.fsw._incrReadyCount();
|
|
10050
10050
|
let linkPath;
|
|
10051
10051
|
try {
|
|
10052
|
-
linkPath = await fsrealpath(
|
|
10052
|
+
linkPath = await fsrealpath(path5);
|
|
10053
10053
|
} catch (e) {
|
|
10054
10054
|
this.fsw._emitReady();
|
|
10055
10055
|
return true;
|
|
@@ -10059,12 +10059,12 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10059
10059
|
if (dir.has(item)) {
|
|
10060
10060
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
10061
10061
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10062
|
-
this.fsw._emit(EV_CHANGE,
|
|
10062
|
+
this.fsw._emit(EV_CHANGE, path5, entry.stats);
|
|
10063
10063
|
}
|
|
10064
10064
|
} else {
|
|
10065
10065
|
dir.add(item);
|
|
10066
10066
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10067
|
-
this.fsw._emit(EV_ADD,
|
|
10067
|
+
this.fsw._emit(EV_ADD, path5, entry.stats);
|
|
10068
10068
|
}
|
|
10069
10069
|
this.fsw._emitReady();
|
|
10070
10070
|
return true;
|
|
@@ -10093,9 +10093,9 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10093
10093
|
return;
|
|
10094
10094
|
}
|
|
10095
10095
|
const item = entry.path;
|
|
10096
|
-
let
|
|
10096
|
+
let path5 = sysPath.join(directory, item);
|
|
10097
10097
|
current.add(item);
|
|
10098
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
10098
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path5, item)) {
|
|
10099
10099
|
return;
|
|
10100
10100
|
}
|
|
10101
10101
|
if (this.fsw.closed) {
|
|
@@ -10104,8 +10104,8 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10104
10104
|
}
|
|
10105
10105
|
if (item === target || !target && !previous.has(item)) {
|
|
10106
10106
|
this.fsw._incrReadyCount();
|
|
10107
|
-
|
|
10108
|
-
this._addToNodeFs(
|
|
10107
|
+
path5 = sysPath.join(dir, sysPath.relative(dir, path5));
|
|
10108
|
+
this._addToNodeFs(path5, initialAdd, wh, depth + 1);
|
|
10109
10109
|
}
|
|
10110
10110
|
}).on(EV_ERROR, this._boundHandleError);
|
|
10111
10111
|
return new Promise((resolve) => stream.once(STR_END, () => {
|
|
@@ -10153,13 +10153,13 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10153
10153
|
}
|
|
10154
10154
|
return closer;
|
|
10155
10155
|
}
|
|
10156
|
-
async _addToNodeFs(
|
|
10156
|
+
async _addToNodeFs(path5, initialAdd, priorWh, depth, target) {
|
|
10157
10157
|
const ready = this.fsw._emitReady;
|
|
10158
|
-
if (this.fsw._isIgnored(
|
|
10158
|
+
if (this.fsw._isIgnored(path5) || this.fsw.closed) {
|
|
10159
10159
|
ready();
|
|
10160
10160
|
return false;
|
|
10161
10161
|
}
|
|
10162
|
-
const wh = this.fsw._getWatchHelpers(
|
|
10162
|
+
const wh = this.fsw._getWatchHelpers(path5, depth);
|
|
10163
10163
|
if (!wh.hasGlob && priorWh) {
|
|
10164
10164
|
wh.hasGlob = priorWh.hasGlob;
|
|
10165
10165
|
wh.globFilter = priorWh.globFilter;
|
|
@@ -10174,11 +10174,11 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10174
10174
|
ready();
|
|
10175
10175
|
return false;
|
|
10176
10176
|
}
|
|
10177
|
-
const follow = this.fsw.options.followSymlinks && !
|
|
10177
|
+
const follow = this.fsw.options.followSymlinks && !path5.includes(STAR) && !path5.includes(BRACE_START);
|
|
10178
10178
|
let closer;
|
|
10179
10179
|
if (stats.isDirectory()) {
|
|
10180
|
-
const absPath = sysPath.resolve(
|
|
10181
|
-
const targetPath = follow ? await fsrealpath(
|
|
10180
|
+
const absPath = sysPath.resolve(path5);
|
|
10181
|
+
const targetPath = follow ? await fsrealpath(path5) : path5;
|
|
10182
10182
|
if (this.fsw.closed)
|
|
10183
10183
|
return;
|
|
10184
10184
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -10188,28 +10188,28 @@ var require_nodefs_handler = __commonJS((exports, module) => {
|
|
|
10188
10188
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
10189
10189
|
}
|
|
10190
10190
|
} else if (stats.isSymbolicLink()) {
|
|
10191
|
-
const targetPath = follow ? await fsrealpath(
|
|
10191
|
+
const targetPath = follow ? await fsrealpath(path5) : path5;
|
|
10192
10192
|
if (this.fsw.closed)
|
|
10193
10193
|
return;
|
|
10194
10194
|
const parent = sysPath.dirname(wh.watchPath);
|
|
10195
10195
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
10196
10196
|
this.fsw._emit(EV_ADD, wh.watchPath, stats);
|
|
10197
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
10197
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path5, wh, targetPath);
|
|
10198
10198
|
if (this.fsw.closed)
|
|
10199
10199
|
return;
|
|
10200
10200
|
if (targetPath !== undefined) {
|
|
10201
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(
|
|
10201
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path5), targetPath);
|
|
10202
10202
|
}
|
|
10203
10203
|
} else {
|
|
10204
10204
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
10205
10205
|
}
|
|
10206
10206
|
ready();
|
|
10207
|
-
this.fsw._addPathCloser(
|
|
10207
|
+
this.fsw._addPathCloser(path5, closer);
|
|
10208
10208
|
return false;
|
|
10209
10209
|
} catch (error) {
|
|
10210
10210
|
if (this.fsw._handleError(error)) {
|
|
10211
10211
|
ready();
|
|
10212
|
-
return
|
|
10212
|
+
return path5;
|
|
10213
10213
|
}
|
|
10214
10214
|
}
|
|
10215
10215
|
}
|
|
@@ -10229,9 +10229,9 @@ var require_fsevents2 = __commonJS((exports) => {
|
|
|
10229
10229
|
}
|
|
10230
10230
|
var Native = require_fsevents();
|
|
10231
10231
|
var events = Native.constants;
|
|
10232
|
-
function watch(
|
|
10233
|
-
if (typeof
|
|
10234
|
-
throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof
|
|
10232
|
+
function watch(path5, since, handler) {
|
|
10233
|
+
if (typeof path5 !== "string") {
|
|
10234
|
+
throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path5}`);
|
|
10235
10235
|
}
|
|
10236
10236
|
if (typeof since === "function" && typeof handler === "undefined") {
|
|
10237
10237
|
handler = since;
|
|
@@ -10243,18 +10243,18 @@ var require_fsevents2 = __commonJS((exports) => {
|
|
|
10243
10243
|
if (typeof handler !== "function") {
|
|
10244
10244
|
throw new TypeError(`fsevents argument 3 must be a function and not a ${typeof handler}`);
|
|
10245
10245
|
}
|
|
10246
|
-
let instance = Native.start(Native.global,
|
|
10246
|
+
let instance = Native.start(Native.global, path5, since, handler);
|
|
10247
10247
|
if (!instance)
|
|
10248
|
-
throw new Error(`could not watch: ${
|
|
10248
|
+
throw new Error(`could not watch: ${path5}`);
|
|
10249
10249
|
return () => {
|
|
10250
10250
|
const result = instance ? Promise.resolve(instance).then(Native.stop) : Promise.resolve(undefined);
|
|
10251
10251
|
instance = undefined;
|
|
10252
10252
|
return result;
|
|
10253
10253
|
};
|
|
10254
10254
|
}
|
|
10255
|
-
function getInfo(
|
|
10255
|
+
function getInfo(path5, flags) {
|
|
10256
10256
|
return {
|
|
10257
|
-
path:
|
|
10257
|
+
path: path5,
|
|
10258
10258
|
flags,
|
|
10259
10259
|
event: getEventType(flags),
|
|
10260
10260
|
type: getFileType(flags),
|
|
@@ -10371,18 +10371,18 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10371
10371
|
131840,
|
|
10372
10372
|
262912
|
|
10373
10373
|
]);
|
|
10374
|
-
var createFSEventsInstance = (
|
|
10375
|
-
const stop = fsevents.watch(
|
|
10374
|
+
var createFSEventsInstance = (path5, callback) => {
|
|
10375
|
+
const stop = fsevents.watch(path5, callback);
|
|
10376
10376
|
return { stop };
|
|
10377
10377
|
};
|
|
10378
|
-
function setFSEventsListener(
|
|
10378
|
+
function setFSEventsListener(path5, realPath, listener, rawEmitter) {
|
|
10379
10379
|
let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath;
|
|
10380
10380
|
const parentPath = sysPath.dirname(watchPath);
|
|
10381
10381
|
let cont = FSEventsWatchers.get(watchPath);
|
|
10382
10382
|
if (couldConsolidate(parentPath)) {
|
|
10383
10383
|
watchPath = parentPath;
|
|
10384
10384
|
}
|
|
10385
|
-
const resolvedPath = sysPath.resolve(
|
|
10385
|
+
const resolvedPath = sysPath.resolve(path5);
|
|
10386
10386
|
const hasSymlink = resolvedPath !== realPath;
|
|
10387
10387
|
const filteredListener = (fullPath, flags, info) => {
|
|
10388
10388
|
if (hasSymlink)
|
|
@@ -10432,10 +10432,10 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10432
10432
|
}
|
|
10433
10433
|
};
|
|
10434
10434
|
}
|
|
10435
|
-
var couldConsolidate = (
|
|
10435
|
+
var couldConsolidate = (path5) => {
|
|
10436
10436
|
let count = 0;
|
|
10437
10437
|
for (const watchPath of FSEventsWatchers.keys()) {
|
|
10438
|
-
if (watchPath.indexOf(
|
|
10438
|
+
if (watchPath.indexOf(path5) === 0) {
|
|
10439
10439
|
count++;
|
|
10440
10440
|
if (count >= consolidateThreshhold) {
|
|
10441
10441
|
return true;
|
|
@@ -10445,9 +10445,9 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10445
10445
|
return false;
|
|
10446
10446
|
};
|
|
10447
10447
|
var canUse = () => fsevents && FSEventsWatchers.size < 128;
|
|
10448
|
-
var calcDepth = (
|
|
10448
|
+
var calcDepth = (path5, root) => {
|
|
10449
10449
|
let i = 0;
|
|
10450
|
-
while (!
|
|
10450
|
+
while (!path5.indexOf(root) && (path5 = sysPath.dirname(path5)) !== root)
|
|
10451
10451
|
i++;
|
|
10452
10452
|
return i;
|
|
10453
10453
|
};
|
|
@@ -10457,62 +10457,62 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10457
10457
|
constructor(fsw) {
|
|
10458
10458
|
this.fsw = fsw;
|
|
10459
10459
|
}
|
|
10460
|
-
checkIgnored(
|
|
10460
|
+
checkIgnored(path5, stats) {
|
|
10461
10461
|
const ipaths = this.fsw._ignoredPaths;
|
|
10462
|
-
if (this.fsw._isIgnored(
|
|
10463
|
-
ipaths.add(
|
|
10462
|
+
if (this.fsw._isIgnored(path5, stats)) {
|
|
10463
|
+
ipaths.add(path5);
|
|
10464
10464
|
if (stats && stats.isDirectory()) {
|
|
10465
|
-
ipaths.add(
|
|
10465
|
+
ipaths.add(path5 + ROOT_GLOBSTAR);
|
|
10466
10466
|
}
|
|
10467
10467
|
return true;
|
|
10468
10468
|
}
|
|
10469
|
-
ipaths.delete(
|
|
10470
|
-
ipaths.delete(
|
|
10469
|
+
ipaths.delete(path5);
|
|
10470
|
+
ipaths.delete(path5 + ROOT_GLOBSTAR);
|
|
10471
10471
|
}
|
|
10472
|
-
addOrChange(
|
|
10472
|
+
addOrChange(path5, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
|
10473
10473
|
const event = watchedDir.has(item) ? EV_CHANGE : EV_ADD;
|
|
10474
|
-
this.handleEvent(event,
|
|
10474
|
+
this.handleEvent(event, path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10475
10475
|
}
|
|
10476
|
-
async checkExists(
|
|
10476
|
+
async checkExists(path5, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
|
10477
10477
|
try {
|
|
10478
|
-
const stats = await stat(
|
|
10478
|
+
const stats = await stat(path5);
|
|
10479
10479
|
if (this.fsw.closed)
|
|
10480
10480
|
return;
|
|
10481
10481
|
if (sameTypes(info, stats)) {
|
|
10482
|
-
this.addOrChange(
|
|
10482
|
+
this.addOrChange(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10483
10483
|
} else {
|
|
10484
|
-
this.handleEvent(EV_UNLINK,
|
|
10484
|
+
this.handleEvent(EV_UNLINK, path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10485
10485
|
}
|
|
10486
10486
|
} catch (error) {
|
|
10487
10487
|
if (error.code === "EACCES") {
|
|
10488
|
-
this.addOrChange(
|
|
10488
|
+
this.addOrChange(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10489
10489
|
} else {
|
|
10490
|
-
this.handleEvent(EV_UNLINK,
|
|
10490
|
+
this.handleEvent(EV_UNLINK, path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10491
10491
|
}
|
|
10492
10492
|
}
|
|
10493
10493
|
}
|
|
10494
|
-
handleEvent(event,
|
|
10495
|
-
if (this.fsw.closed || this.checkIgnored(
|
|
10494
|
+
handleEvent(event, path5, fullPath, realPath, parent, watchedDir, item, info, opts) {
|
|
10495
|
+
if (this.fsw.closed || this.checkIgnored(path5))
|
|
10496
10496
|
return;
|
|
10497
10497
|
if (event === EV_UNLINK) {
|
|
10498
|
-
const
|
|
10499
|
-
if (
|
|
10500
|
-
this.fsw._remove(parent, item,
|
|
10498
|
+
const isDirectory2 = info.type === FSEVENT_TYPE_DIRECTORY;
|
|
10499
|
+
if (isDirectory2 || watchedDir.has(item)) {
|
|
10500
|
+
this.fsw._remove(parent, item, isDirectory2);
|
|
10501
10501
|
}
|
|
10502
10502
|
} else {
|
|
10503
10503
|
if (event === EV_ADD) {
|
|
10504
10504
|
if (info.type === FSEVENT_TYPE_DIRECTORY)
|
|
10505
|
-
this.fsw._getWatchedDir(
|
|
10505
|
+
this.fsw._getWatchedDir(path5);
|
|
10506
10506
|
if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
|
|
10507
10507
|
const curDepth = opts.depth === undefined ? undefined : calcDepth(fullPath, realPath) + 1;
|
|
10508
|
-
return this._addToFsEvents(
|
|
10508
|
+
return this._addToFsEvents(path5, false, true, curDepth);
|
|
10509
10509
|
}
|
|
10510
10510
|
this.fsw._getWatchedDir(parent).add(item);
|
|
10511
10511
|
}
|
|
10512
10512
|
const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
|
|
10513
|
-
this.fsw._emit(eventName,
|
|
10513
|
+
this.fsw._emit(eventName, path5);
|
|
10514
10514
|
if (eventName === EV_ADD_DIR)
|
|
10515
|
-
this._addToFsEvents(
|
|
10515
|
+
this._addToFsEvents(path5, false, true);
|
|
10516
10516
|
}
|
|
10517
10517
|
}
|
|
10518
10518
|
_watchWithFsEvents(watchPath, realPath, transform, globFilter) {
|
|
@@ -10524,38 +10524,38 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10524
10524
|
return;
|
|
10525
10525
|
if (opts.depth !== undefined && calcDepth(fullPath, realPath) > opts.depth)
|
|
10526
10526
|
return;
|
|
10527
|
-
const
|
|
10528
|
-
if (globFilter && !globFilter(
|
|
10527
|
+
const path5 = transform(sysPath.join(watchPath, sysPath.relative(watchPath, fullPath)));
|
|
10528
|
+
if (globFilter && !globFilter(path5))
|
|
10529
10529
|
return;
|
|
10530
|
-
const parent = sysPath.dirname(
|
|
10531
|
-
const item = sysPath.basename(
|
|
10532
|
-
const watchedDir = this.fsw._getWatchedDir(info.type === FSEVENT_TYPE_DIRECTORY ?
|
|
10530
|
+
const parent = sysPath.dirname(path5);
|
|
10531
|
+
const item = sysPath.basename(path5);
|
|
10532
|
+
const watchedDir = this.fsw._getWatchedDir(info.type === FSEVENT_TYPE_DIRECTORY ? path5 : parent);
|
|
10533
10533
|
if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
|
|
10534
10534
|
if (typeof opts.ignored === FUNCTION_TYPE) {
|
|
10535
10535
|
let stats;
|
|
10536
10536
|
try {
|
|
10537
|
-
stats = await stat(
|
|
10537
|
+
stats = await stat(path5);
|
|
10538
10538
|
} catch (error) {}
|
|
10539
10539
|
if (this.fsw.closed)
|
|
10540
10540
|
return;
|
|
10541
|
-
if (this.checkIgnored(
|
|
10541
|
+
if (this.checkIgnored(path5, stats))
|
|
10542
10542
|
return;
|
|
10543
10543
|
if (sameTypes(info, stats)) {
|
|
10544
|
-
this.addOrChange(
|
|
10544
|
+
this.addOrChange(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10545
10545
|
} else {
|
|
10546
|
-
this.handleEvent(EV_UNLINK,
|
|
10546
|
+
this.handleEvent(EV_UNLINK, path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10547
10547
|
}
|
|
10548
10548
|
} else {
|
|
10549
|
-
this.checkExists(
|
|
10549
|
+
this.checkExists(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10550
10550
|
}
|
|
10551
10551
|
} else {
|
|
10552
10552
|
switch (info.event) {
|
|
10553
10553
|
case FSEVENT_CREATED:
|
|
10554
10554
|
case FSEVENT_MODIFIED:
|
|
10555
|
-
return this.addOrChange(
|
|
10555
|
+
return this.addOrChange(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10556
10556
|
case FSEVENT_DELETED:
|
|
10557
10557
|
case FSEVENT_MOVED:
|
|
10558
|
-
return this.checkExists(
|
|
10558
|
+
return this.checkExists(path5, fullPath, realPath, parent, watchedDir, item, info, opts);
|
|
10559
10559
|
}
|
|
10560
10560
|
}
|
|
10561
10561
|
};
|
|
@@ -10576,12 +10576,12 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10576
10576
|
return this.fsw._emitReady();
|
|
10577
10577
|
}
|
|
10578
10578
|
this.fsw._incrReadyCount();
|
|
10579
|
-
this._addToFsEvents(linkTarget || linkPath, (
|
|
10579
|
+
this._addToFsEvents(linkTarget || linkPath, (path5) => {
|
|
10580
10580
|
let aliasedPath = linkPath;
|
|
10581
10581
|
if (linkTarget && linkTarget !== DOT_SLASH) {
|
|
10582
|
-
aliasedPath =
|
|
10583
|
-
} else if (
|
|
10584
|
-
aliasedPath = sysPath.join(linkPath,
|
|
10582
|
+
aliasedPath = path5.replace(linkTarget, linkPath);
|
|
10583
|
+
} else if (path5 !== DOT_SLASH) {
|
|
10584
|
+
aliasedPath = sysPath.join(linkPath, path5);
|
|
10585
10585
|
}
|
|
10586
10586
|
return transform(aliasedPath);
|
|
10587
10587
|
}, false, curDepth);
|
|
@@ -10605,19 +10605,19 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10605
10605
|
this.fsw._emit(isDir ? EV_ADD_DIR : EV_ADD, pp, stats);
|
|
10606
10606
|
}
|
|
10607
10607
|
}
|
|
10608
|
-
initWatch(realPath,
|
|
10608
|
+
initWatch(realPath, path5, wh, processPath) {
|
|
10609
10609
|
if (this.fsw.closed)
|
|
10610
10610
|
return;
|
|
10611
10611
|
const closer = this._watchWithFsEvents(wh.watchPath, sysPath.resolve(realPath || wh.watchPath), processPath, wh.globFilter);
|
|
10612
|
-
this.fsw._addPathCloser(
|
|
10612
|
+
this.fsw._addPathCloser(path5, closer);
|
|
10613
10613
|
}
|
|
10614
|
-
async _addToFsEvents(
|
|
10614
|
+
async _addToFsEvents(path5, transform, forceAdd, priorDepth) {
|
|
10615
10615
|
if (this.fsw.closed) {
|
|
10616
10616
|
return;
|
|
10617
10617
|
}
|
|
10618
10618
|
const opts = this.fsw.options;
|
|
10619
10619
|
const processPath = typeof transform === FUNCTION_TYPE ? transform : IDENTITY_FN;
|
|
10620
|
-
const wh = this.fsw._getWatchHelpers(
|
|
10620
|
+
const wh = this.fsw._getWatchHelpers(path5);
|
|
10621
10621
|
try {
|
|
10622
10622
|
const stats = await statMethods[wh.statMethod](wh.watchPath);
|
|
10623
10623
|
if (this.fsw.closed)
|
|
@@ -10627,7 +10627,7 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10627
10627
|
}
|
|
10628
10628
|
if (stats.isDirectory()) {
|
|
10629
10629
|
if (!wh.globFilter)
|
|
10630
|
-
this.emitAdd(processPath(
|
|
10630
|
+
this.emitAdd(processPath(path5), stats, processPath, opts, forceAdd);
|
|
10631
10631
|
if (priorDepth && priorDepth > opts.depth)
|
|
10632
10632
|
return;
|
|
10633
10633
|
this.fsw._readdirp(wh.watchPath, {
|
|
@@ -10663,13 +10663,13 @@ var require_fsevents_handler = __commonJS((exports, module) => {
|
|
|
10663
10663
|
}
|
|
10664
10664
|
if (opts.persistent && forceAdd !== true) {
|
|
10665
10665
|
if (typeof transform === FUNCTION_TYPE) {
|
|
10666
|
-
this.initWatch(undefined,
|
|
10666
|
+
this.initWatch(undefined, path5, wh, processPath);
|
|
10667
10667
|
} else {
|
|
10668
10668
|
let realPath;
|
|
10669
10669
|
try {
|
|
10670
10670
|
realPath = await realpath(wh.watchPath);
|
|
10671
10671
|
} catch (e) {}
|
|
10672
|
-
this.initWatch(realPath,
|
|
10672
|
+
this.initWatch(realPath, path5, wh, processPath);
|
|
10673
10673
|
}
|
|
10674
10674
|
}
|
|
10675
10675
|
}
|
|
@@ -10760,20 +10760,20 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
10760
10760
|
}
|
|
10761
10761
|
return str2;
|
|
10762
10762
|
};
|
|
10763
|
-
var normalizePathToUnix = (
|
|
10764
|
-
var normalizeIgnored = (cwd = EMPTY_STR) => (
|
|
10765
|
-
if (typeof
|
|
10766
|
-
return
|
|
10767
|
-
return normalizePathToUnix(sysPath.isAbsolute(
|
|
10763
|
+
var normalizePathToUnix = (path5) => toUnix(sysPath.normalize(toUnix(path5)));
|
|
10764
|
+
var normalizeIgnored = (cwd = EMPTY_STR) => (path5) => {
|
|
10765
|
+
if (typeof path5 !== STRING_TYPE)
|
|
10766
|
+
return path5;
|
|
10767
|
+
return normalizePathToUnix(sysPath.isAbsolute(path5) ? path5 : sysPath.join(cwd, path5));
|
|
10768
10768
|
};
|
|
10769
|
-
var getAbsolutePath = (
|
|
10770
|
-
if (sysPath.isAbsolute(
|
|
10771
|
-
return
|
|
10769
|
+
var getAbsolutePath = (path5, cwd) => {
|
|
10770
|
+
if (sysPath.isAbsolute(path5)) {
|
|
10771
|
+
return path5;
|
|
10772
10772
|
}
|
|
10773
|
-
if (
|
|
10774
|
-
return BANG + sysPath.join(cwd,
|
|
10773
|
+
if (path5.startsWith(BANG)) {
|
|
10774
|
+
return BANG + sysPath.join(cwd, path5.slice(1));
|
|
10775
10775
|
}
|
|
10776
|
-
return sysPath.join(cwd,
|
|
10776
|
+
return sysPath.join(cwd, path5);
|
|
10777
10777
|
};
|
|
10778
10778
|
var undef = (opts, key) => opts[key] === undefined;
|
|
10779
10779
|
|
|
@@ -10830,17 +10830,17 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
10830
10830
|
var STAT_METHOD_L = "lstat";
|
|
10831
10831
|
|
|
10832
10832
|
class WatchHelper {
|
|
10833
|
-
constructor(
|
|
10833
|
+
constructor(path5, watchPath, follow, fsw) {
|
|
10834
10834
|
this.fsw = fsw;
|
|
10835
|
-
this.path =
|
|
10835
|
+
this.path = path5 = path5.replace(REPLACER_RE, EMPTY_STR);
|
|
10836
10836
|
this.watchPath = watchPath;
|
|
10837
10837
|
this.fullWatchPath = sysPath.resolve(watchPath);
|
|
10838
|
-
this.hasGlob = watchPath !==
|
|
10839
|
-
if (
|
|
10838
|
+
this.hasGlob = watchPath !== path5;
|
|
10839
|
+
if (path5 === EMPTY_STR)
|
|
10840
10840
|
this.hasGlob = false;
|
|
10841
10841
|
this.globSymlink = this.hasGlob && follow ? undefined : false;
|
|
10842
|
-
this.globFilter = this.hasGlob ? anymatch(
|
|
10843
|
-
this.dirParts = this.getDirParts(
|
|
10842
|
+
this.globFilter = this.hasGlob ? anymatch(path5, undefined, ANYMATCH_OPTS) : false;
|
|
10843
|
+
this.dirParts = this.getDirParts(path5);
|
|
10844
10844
|
this.dirParts.forEach((parts) => {
|
|
10845
10845
|
if (parts.length > 1)
|
|
10846
10846
|
parts.pop();
|
|
@@ -10868,13 +10868,13 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
10868
10868
|
const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ? this.globFilter(resolvedPath) : true;
|
|
10869
10869
|
return matchesGlob && this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
|
|
10870
10870
|
}
|
|
10871
|
-
getDirParts(
|
|
10871
|
+
getDirParts(path5) {
|
|
10872
10872
|
if (!this.hasGlob)
|
|
10873
10873
|
return [];
|
|
10874
10874
|
const parts = [];
|
|
10875
|
-
const expandedPath =
|
|
10876
|
-
expandedPath.forEach((
|
|
10877
|
-
parts.push(sysPath.relative(this.watchPath,
|
|
10875
|
+
const expandedPath = path5.includes(BRACE_START) ? braces.expand(path5) : [path5];
|
|
10876
|
+
expandedPath.forEach((path6) => {
|
|
10877
|
+
parts.push(sysPath.relative(this.watchPath, path6).split(SLASH_OR_BACK_SLASH_RE));
|
|
10878
10878
|
});
|
|
10879
10879
|
return parts;
|
|
10880
10880
|
}
|
|
@@ -10990,21 +10990,21 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
10990
10990
|
this.closed = false;
|
|
10991
10991
|
let paths = unifyPaths(paths_);
|
|
10992
10992
|
if (cwd) {
|
|
10993
|
-
paths = paths.map((
|
|
10994
|
-
const absPath = getAbsolutePath(
|
|
10995
|
-
if (disableGlobbing || !isGlob(
|
|
10993
|
+
paths = paths.map((path5) => {
|
|
10994
|
+
const absPath = getAbsolutePath(path5, cwd);
|
|
10995
|
+
if (disableGlobbing || !isGlob(path5)) {
|
|
10996
10996
|
return absPath;
|
|
10997
10997
|
}
|
|
10998
10998
|
return normalizePath(absPath);
|
|
10999
10999
|
});
|
|
11000
11000
|
}
|
|
11001
|
-
paths = paths.filter((
|
|
11002
|
-
if (
|
|
11003
|
-
this._ignoredPaths.add(
|
|
11001
|
+
paths = paths.filter((path5) => {
|
|
11002
|
+
if (path5.startsWith(BANG)) {
|
|
11003
|
+
this._ignoredPaths.add(path5.slice(1));
|
|
11004
11004
|
return false;
|
|
11005
11005
|
}
|
|
11006
|
-
this._ignoredPaths.delete(
|
|
11007
|
-
this._ignoredPaths.delete(
|
|
11006
|
+
this._ignoredPaths.delete(path5);
|
|
11007
|
+
this._ignoredPaths.delete(path5 + SLASH_GLOBSTAR);
|
|
11008
11008
|
this._userIgnored = undefined;
|
|
11009
11009
|
return true;
|
|
11010
11010
|
});
|
|
@@ -11013,13 +11013,13 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11013
11013
|
this._readyCount = paths.length;
|
|
11014
11014
|
if (this.options.persistent)
|
|
11015
11015
|
this._readyCount += paths.length;
|
|
11016
|
-
paths.forEach((
|
|
11016
|
+
paths.forEach((path5) => this._fsEventsHandler._addToFsEvents(path5));
|
|
11017
11017
|
} else {
|
|
11018
11018
|
if (!this._readyCount)
|
|
11019
11019
|
this._readyCount = 0;
|
|
11020
11020
|
this._readyCount += paths.length;
|
|
11021
|
-
Promise.all(paths.map(async (
|
|
11022
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
11021
|
+
Promise.all(paths.map(async (path5) => {
|
|
11022
|
+
const res = await this._nodeFsHandler._addToNodeFs(path5, !_internal, 0, 0, _origAdd);
|
|
11023
11023
|
if (res)
|
|
11024
11024
|
this._emitReady();
|
|
11025
11025
|
return res;
|
|
@@ -11038,16 +11038,16 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11038
11038
|
return this;
|
|
11039
11039
|
const paths = unifyPaths(paths_);
|
|
11040
11040
|
const { cwd } = this.options;
|
|
11041
|
-
paths.forEach((
|
|
11042
|
-
if (!sysPath.isAbsolute(
|
|
11041
|
+
paths.forEach((path5) => {
|
|
11042
|
+
if (!sysPath.isAbsolute(path5) && !this._closers.has(path5)) {
|
|
11043
11043
|
if (cwd)
|
|
11044
|
-
|
|
11045
|
-
|
|
11044
|
+
path5 = sysPath.join(cwd, path5);
|
|
11045
|
+
path5 = sysPath.resolve(path5);
|
|
11046
11046
|
}
|
|
11047
|
-
this._closePath(
|
|
11048
|
-
this._ignoredPaths.add(
|
|
11049
|
-
if (this._watched.has(
|
|
11050
|
-
this._ignoredPaths.add(
|
|
11047
|
+
this._closePath(path5);
|
|
11048
|
+
this._ignoredPaths.add(path5);
|
|
11049
|
+
if (this._watched.has(path5)) {
|
|
11050
|
+
this._ignoredPaths.add(path5 + SLASH_GLOBSTAR);
|
|
11051
11051
|
}
|
|
11052
11052
|
this._userIgnored = undefined;
|
|
11053
11053
|
});
|
|
@@ -11090,15 +11090,15 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11090
11090
|
if (event !== EV_ERROR)
|
|
11091
11091
|
this.emit(EV_ALL, ...args);
|
|
11092
11092
|
}
|
|
11093
|
-
async _emit(event,
|
|
11093
|
+
async _emit(event, path5, val1, val2, val3) {
|
|
11094
11094
|
if (this.closed)
|
|
11095
11095
|
return;
|
|
11096
11096
|
const opts = this.options;
|
|
11097
11097
|
if (isWindows)
|
|
11098
|
-
|
|
11098
|
+
path5 = sysPath.normalize(path5);
|
|
11099
11099
|
if (opts.cwd)
|
|
11100
|
-
|
|
11101
|
-
const args = [event,
|
|
11100
|
+
path5 = sysPath.relative(opts.cwd, path5);
|
|
11101
|
+
const args = [event, path5];
|
|
11102
11102
|
if (val3 !== undefined)
|
|
11103
11103
|
args.push(val1, val2, val3);
|
|
11104
11104
|
else if (val2 !== undefined)
|
|
@@ -11107,25 +11107,25 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11107
11107
|
args.push(val1);
|
|
11108
11108
|
const awf = opts.awaitWriteFinish;
|
|
11109
11109
|
let pw;
|
|
11110
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
11110
|
+
if (awf && (pw = this._pendingWrites.get(path5))) {
|
|
11111
11111
|
pw.lastChange = new Date;
|
|
11112
11112
|
return this;
|
|
11113
11113
|
}
|
|
11114
11114
|
if (opts.atomic) {
|
|
11115
11115
|
if (event === EV_UNLINK) {
|
|
11116
|
-
this._pendingUnlinks.set(
|
|
11116
|
+
this._pendingUnlinks.set(path5, args);
|
|
11117
11117
|
setTimeout(() => {
|
|
11118
|
-
this._pendingUnlinks.forEach((entry,
|
|
11118
|
+
this._pendingUnlinks.forEach((entry, path6) => {
|
|
11119
11119
|
this.emit(...entry);
|
|
11120
11120
|
this.emit(EV_ALL, ...entry);
|
|
11121
|
-
this._pendingUnlinks.delete(
|
|
11121
|
+
this._pendingUnlinks.delete(path6);
|
|
11122
11122
|
});
|
|
11123
11123
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
11124
11124
|
return this;
|
|
11125
11125
|
}
|
|
11126
|
-
if (event === EV_ADD && this._pendingUnlinks.has(
|
|
11126
|
+
if (event === EV_ADD && this._pendingUnlinks.has(path5)) {
|
|
11127
11127
|
event = args[0] = EV_CHANGE;
|
|
11128
|
-
this._pendingUnlinks.delete(
|
|
11128
|
+
this._pendingUnlinks.delete(path5);
|
|
11129
11129
|
}
|
|
11130
11130
|
}
|
|
11131
11131
|
if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) {
|
|
@@ -11143,16 +11143,16 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11143
11143
|
this.emitWithAll(event, args);
|
|
11144
11144
|
}
|
|
11145
11145
|
};
|
|
11146
|
-
this._awaitWriteFinish(
|
|
11146
|
+
this._awaitWriteFinish(path5, awf.stabilityThreshold, event, awfEmit);
|
|
11147
11147
|
return this;
|
|
11148
11148
|
}
|
|
11149
11149
|
if (event === EV_CHANGE) {
|
|
11150
|
-
const isThrottled = !this._throttle(EV_CHANGE,
|
|
11150
|
+
const isThrottled = !this._throttle(EV_CHANGE, path5, 50);
|
|
11151
11151
|
if (isThrottled)
|
|
11152
11152
|
return this;
|
|
11153
11153
|
}
|
|
11154
11154
|
if (opts.alwaysStat && val1 === undefined && (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE)) {
|
|
11155
|
-
const fullPath = opts.cwd ? sysPath.join(opts.cwd,
|
|
11155
|
+
const fullPath = opts.cwd ? sysPath.join(opts.cwd, path5) : path5;
|
|
11156
11156
|
let stats;
|
|
11157
11157
|
try {
|
|
11158
11158
|
stats = await stat(fullPath);
|
|
@@ -11171,21 +11171,21 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11171
11171
|
}
|
|
11172
11172
|
return error || this.closed;
|
|
11173
11173
|
}
|
|
11174
|
-
_throttle(actionType,
|
|
11174
|
+
_throttle(actionType, path5, timeout) {
|
|
11175
11175
|
if (!this._throttled.has(actionType)) {
|
|
11176
11176
|
this._throttled.set(actionType, new Map);
|
|
11177
11177
|
}
|
|
11178
11178
|
const action = this._throttled.get(actionType);
|
|
11179
|
-
const actionPath = action.get(
|
|
11179
|
+
const actionPath = action.get(path5);
|
|
11180
11180
|
if (actionPath) {
|
|
11181
11181
|
actionPath.count++;
|
|
11182
11182
|
return false;
|
|
11183
11183
|
}
|
|
11184
11184
|
let timeoutObject;
|
|
11185
11185
|
const clear = () => {
|
|
11186
|
-
const item = action.get(
|
|
11186
|
+
const item = action.get(path5);
|
|
11187
11187
|
const count = item ? item.count : 0;
|
|
11188
|
-
action.delete(
|
|
11188
|
+
action.delete(path5);
|
|
11189
11189
|
clearTimeout(timeoutObject);
|
|
11190
11190
|
if (item)
|
|
11191
11191
|
clearTimeout(item.timeoutObject);
|
|
@@ -11193,45 +11193,45 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11193
11193
|
};
|
|
11194
11194
|
timeoutObject = setTimeout(clear, timeout);
|
|
11195
11195
|
const thr = { timeoutObject, clear, count: 0 };
|
|
11196
|
-
action.set(
|
|
11196
|
+
action.set(path5, thr);
|
|
11197
11197
|
return thr;
|
|
11198
11198
|
}
|
|
11199
11199
|
_incrReadyCount() {
|
|
11200
11200
|
return this._readyCount++;
|
|
11201
11201
|
}
|
|
11202
|
-
_awaitWriteFinish(
|
|
11202
|
+
_awaitWriteFinish(path5, threshold, event, awfEmit) {
|
|
11203
11203
|
let timeoutHandler;
|
|
11204
|
-
let fullPath =
|
|
11205
|
-
if (this.options.cwd && !sysPath.isAbsolute(
|
|
11206
|
-
fullPath = sysPath.join(this.options.cwd,
|
|
11204
|
+
let fullPath = path5;
|
|
11205
|
+
if (this.options.cwd && !sysPath.isAbsolute(path5)) {
|
|
11206
|
+
fullPath = sysPath.join(this.options.cwd, path5);
|
|
11207
11207
|
}
|
|
11208
11208
|
const now = new Date;
|
|
11209
11209
|
const awaitWriteFinish = (prevStat) => {
|
|
11210
11210
|
fs2.stat(fullPath, (err, curStat) => {
|
|
11211
|
-
if (err || !this._pendingWrites.has(
|
|
11211
|
+
if (err || !this._pendingWrites.has(path5)) {
|
|
11212
11212
|
if (err && err.code !== "ENOENT")
|
|
11213
11213
|
awfEmit(err);
|
|
11214
11214
|
return;
|
|
11215
11215
|
}
|
|
11216
11216
|
const now2 = Number(new Date);
|
|
11217
11217
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
11218
|
-
this._pendingWrites.get(
|
|
11218
|
+
this._pendingWrites.get(path5).lastChange = now2;
|
|
11219
11219
|
}
|
|
11220
|
-
const pw = this._pendingWrites.get(
|
|
11220
|
+
const pw = this._pendingWrites.get(path5);
|
|
11221
11221
|
const df = now2 - pw.lastChange;
|
|
11222
11222
|
if (df >= threshold) {
|
|
11223
|
-
this._pendingWrites.delete(
|
|
11223
|
+
this._pendingWrites.delete(path5);
|
|
11224
11224
|
awfEmit(undefined, curStat);
|
|
11225
11225
|
} else {
|
|
11226
11226
|
timeoutHandler = setTimeout(awaitWriteFinish, this.options.awaitWriteFinish.pollInterval, curStat);
|
|
11227
11227
|
}
|
|
11228
11228
|
});
|
|
11229
11229
|
};
|
|
11230
|
-
if (!this._pendingWrites.has(
|
|
11231
|
-
this._pendingWrites.set(
|
|
11230
|
+
if (!this._pendingWrites.has(path5)) {
|
|
11231
|
+
this._pendingWrites.set(path5, {
|
|
11232
11232
|
lastChange: now,
|
|
11233
11233
|
cancelWait: () => {
|
|
11234
|
-
this._pendingWrites.delete(
|
|
11234
|
+
this._pendingWrites.delete(path5);
|
|
11235
11235
|
clearTimeout(timeoutHandler);
|
|
11236
11236
|
return event;
|
|
11237
11237
|
}
|
|
@@ -11242,26 +11242,26 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11242
11242
|
_getGlobIgnored() {
|
|
11243
11243
|
return [...this._ignoredPaths.values()];
|
|
11244
11244
|
}
|
|
11245
|
-
_isIgnored(
|
|
11246
|
-
if (this.options.atomic && DOT_RE.test(
|
|
11245
|
+
_isIgnored(path5, stats) {
|
|
11246
|
+
if (this.options.atomic && DOT_RE.test(path5))
|
|
11247
11247
|
return true;
|
|
11248
11248
|
if (!this._userIgnored) {
|
|
11249
11249
|
const { cwd } = this.options;
|
|
11250
11250
|
const ign = this.options.ignored;
|
|
11251
11251
|
const ignored = ign && ign.map(normalizeIgnored(cwd));
|
|
11252
|
-
const paths = arrify(ignored).filter((
|
|
11252
|
+
const paths = arrify(ignored).filter((path6) => typeof path6 === STRING_TYPE && !isGlob(path6)).map((path6) => path6 + SLASH_GLOBSTAR);
|
|
11253
11253
|
const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
|
|
11254
11254
|
this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
|
|
11255
11255
|
}
|
|
11256
|
-
return this._userIgnored([
|
|
11256
|
+
return this._userIgnored([path5, stats]);
|
|
11257
11257
|
}
|
|
11258
|
-
_isntIgnored(
|
|
11259
|
-
return !this._isIgnored(
|
|
11258
|
+
_isntIgnored(path5, stat2) {
|
|
11259
|
+
return !this._isIgnored(path5, stat2);
|
|
11260
11260
|
}
|
|
11261
|
-
_getWatchHelpers(
|
|
11262
|
-
const watchPath = depth || this.options.disableGlobbing || !isGlob(
|
|
11261
|
+
_getWatchHelpers(path5, depth) {
|
|
11262
|
+
const watchPath = depth || this.options.disableGlobbing || !isGlob(path5) ? path5 : globParent(path5);
|
|
11263
11263
|
const follow = this.options.followSymlinks;
|
|
11264
|
-
return new WatchHelper(
|
|
11264
|
+
return new WatchHelper(path5, watchPath, follow, this);
|
|
11265
11265
|
}
|
|
11266
11266
|
_getWatchedDir(directory) {
|
|
11267
11267
|
if (!this._boundRemove)
|
|
@@ -11279,60 +11279,60 @@ var require_chokidar = __commonJS((exports) => {
|
|
|
11279
11279
|
const it = Number.parseInt(st.toString(8)[0], 10);
|
|
11280
11280
|
return Boolean(4 & it);
|
|
11281
11281
|
}
|
|
11282
|
-
_remove(directory, item,
|
|
11283
|
-
const
|
|
11284
|
-
const fullPath = sysPath.resolve(
|
|
11285
|
-
|
|
11286
|
-
if (!this._throttle("remove",
|
|
11282
|
+
_remove(directory, item, isDirectory2) {
|
|
11283
|
+
const path5 = sysPath.join(directory, item);
|
|
11284
|
+
const fullPath = sysPath.resolve(path5);
|
|
11285
|
+
isDirectory2 = isDirectory2 != null ? isDirectory2 : this._watched.has(path5) || this._watched.has(fullPath);
|
|
11286
|
+
if (!this._throttle("remove", path5, 100))
|
|
11287
11287
|
return;
|
|
11288
|
-
if (!
|
|
11288
|
+
if (!isDirectory2 && !this.options.useFsEvents && this._watched.size === 1) {
|
|
11289
11289
|
this.add(directory, item, true);
|
|
11290
11290
|
}
|
|
11291
|
-
const wp = this._getWatchedDir(
|
|
11291
|
+
const wp = this._getWatchedDir(path5);
|
|
11292
11292
|
const nestedDirectoryChildren = wp.getChildren();
|
|
11293
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
11293
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path5, nested));
|
|
11294
11294
|
const parent = this._getWatchedDir(directory);
|
|
11295
11295
|
const wasTracked = parent.has(item);
|
|
11296
11296
|
parent.remove(item);
|
|
11297
11297
|
if (this._symlinkPaths.has(fullPath)) {
|
|
11298
11298
|
this._symlinkPaths.delete(fullPath);
|
|
11299
11299
|
}
|
|
11300
|
-
let relPath =
|
|
11300
|
+
let relPath = path5;
|
|
11301
11301
|
if (this.options.cwd)
|
|
11302
|
-
relPath = sysPath.relative(this.options.cwd,
|
|
11302
|
+
relPath = sysPath.relative(this.options.cwd, path5);
|
|
11303
11303
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
11304
11304
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
11305
11305
|
if (event === EV_ADD)
|
|
11306
11306
|
return;
|
|
11307
11307
|
}
|
|
11308
|
-
this._watched.delete(
|
|
11308
|
+
this._watched.delete(path5);
|
|
11309
11309
|
this._watched.delete(fullPath);
|
|
11310
|
-
const eventName =
|
|
11311
|
-
if (wasTracked && !this._isIgnored(
|
|
11312
|
-
this._emit(eventName,
|
|
11310
|
+
const eventName = isDirectory2 ? EV_UNLINK_DIR : EV_UNLINK;
|
|
11311
|
+
if (wasTracked && !this._isIgnored(path5))
|
|
11312
|
+
this._emit(eventName, path5);
|
|
11313
11313
|
if (!this.options.useFsEvents) {
|
|
11314
|
-
this._closePath(
|
|
11314
|
+
this._closePath(path5);
|
|
11315
11315
|
}
|
|
11316
11316
|
}
|
|
11317
|
-
_closePath(
|
|
11318
|
-
this._closeFile(
|
|
11319
|
-
const dir = sysPath.dirname(
|
|
11320
|
-
this._getWatchedDir(dir).remove(sysPath.basename(
|
|
11317
|
+
_closePath(path5) {
|
|
11318
|
+
this._closeFile(path5);
|
|
11319
|
+
const dir = sysPath.dirname(path5);
|
|
11320
|
+
this._getWatchedDir(dir).remove(sysPath.basename(path5));
|
|
11321
11321
|
}
|
|
11322
|
-
_closeFile(
|
|
11323
|
-
const closers = this._closers.get(
|
|
11322
|
+
_closeFile(path5) {
|
|
11323
|
+
const closers = this._closers.get(path5);
|
|
11324
11324
|
if (!closers)
|
|
11325
11325
|
return;
|
|
11326
11326
|
closers.forEach((closer) => closer());
|
|
11327
|
-
this._closers.delete(
|
|
11327
|
+
this._closers.delete(path5);
|
|
11328
11328
|
}
|
|
11329
|
-
_addPathCloser(
|
|
11329
|
+
_addPathCloser(path5, closer) {
|
|
11330
11330
|
if (!closer)
|
|
11331
11331
|
return;
|
|
11332
|
-
let list = this._closers.get(
|
|
11332
|
+
let list = this._closers.get(path5);
|
|
11333
11333
|
if (!list) {
|
|
11334
11334
|
list = [];
|
|
11335
|
-
this._closers.set(
|
|
11335
|
+
this._closers.set(path5, list);
|
|
11336
11336
|
}
|
|
11337
11337
|
list.push(closer);
|
|
11338
11338
|
}
|
|
@@ -11378,7 +11378,7 @@ var require_node_loaders = __commonJS((exports, module) => {
|
|
|
11378
11378
|
return _setPrototypeOf(o, p);
|
|
11379
11379
|
}
|
|
11380
11380
|
var fs2 = __require("fs");
|
|
11381
|
-
var
|
|
11381
|
+
var path5 = __require("path");
|
|
11382
11382
|
var Loader = require_loader();
|
|
11383
11383
|
var _require = require_precompiled_loader();
|
|
11384
11384
|
var PrecompiledLoader = _require.PrecompiledLoader;
|
|
@@ -11396,7 +11396,7 @@ var require_node_loaders = __commonJS((exports, module) => {
|
|
|
11396
11396
|
_this.noCache = !!opts.noCache;
|
|
11397
11397
|
if (searchPaths) {
|
|
11398
11398
|
searchPaths = Array.isArray(searchPaths) ? searchPaths : [searchPaths];
|
|
11399
|
-
_this.searchPaths = searchPaths.map(
|
|
11399
|
+
_this.searchPaths = searchPaths.map(path5.normalize);
|
|
11400
11400
|
} else {
|
|
11401
11401
|
_this.searchPaths = ["."];
|
|
11402
11402
|
}
|
|
@@ -11409,7 +11409,7 @@ var require_node_loaders = __commonJS((exports, module) => {
|
|
|
11409
11409
|
var paths = _this.searchPaths.filter(fs2.existsSync);
|
|
11410
11410
|
var watcher = chokidar.watch(paths);
|
|
11411
11411
|
watcher.on("all", function(event, fullname) {
|
|
11412
|
-
fullname =
|
|
11412
|
+
fullname = path5.resolve(fullname);
|
|
11413
11413
|
if (event === "change" && fullname in _this.pathsToNames) {
|
|
11414
11414
|
_this.emit("update", _this.pathsToNames[fullname], fullname);
|
|
11415
11415
|
}
|
|
@@ -11425,8 +11425,8 @@ var require_node_loaders = __commonJS((exports, module) => {
|
|
|
11425
11425
|
var fullpath = null;
|
|
11426
11426
|
var paths = this.searchPaths;
|
|
11427
11427
|
for (var i = 0;i < paths.length; i++) {
|
|
11428
|
-
var basePath =
|
|
11429
|
-
var p =
|
|
11428
|
+
var basePath = path5.resolve(paths[i]);
|
|
11429
|
+
var p = path5.resolve(paths[i], name);
|
|
11430
11430
|
if (p.indexOf(basePath) === 0 && fs2.existsSync(p)) {
|
|
11431
11431
|
fullpath = p;
|
|
11432
11432
|
break;
|
|
@@ -11675,13 +11675,13 @@ var require_globals = __commonJS((exports, module) => {
|
|
|
11675
11675
|
|
|
11676
11676
|
// node_modules/nunjucks/src/express-app.js
|
|
11677
11677
|
var require_express_app = __commonJS((exports, module) => {
|
|
11678
|
-
var
|
|
11678
|
+
var path5 = __require("path");
|
|
11679
11679
|
module.exports = function express(env, app) {
|
|
11680
11680
|
function NunjucksView(name, opts) {
|
|
11681
11681
|
this.name = name;
|
|
11682
11682
|
this.path = name;
|
|
11683
11683
|
this.defaultEngine = opts.defaultEngine;
|
|
11684
|
-
this.ext =
|
|
11684
|
+
this.ext = path5.extname(name);
|
|
11685
11685
|
if (!this.ext && !this.defaultEngine) {
|
|
11686
11686
|
throw new Error("No default engine was specified and no extension was provided.");
|
|
11687
11687
|
}
|
|
@@ -12058,7 +12058,7 @@ var require_environment = __commonJS((exports, module) => {
|
|
|
12058
12058
|
return _Obj2.apply(this, arguments) || this;
|
|
12059
12059
|
}
|
|
12060
12060
|
var _proto3 = Template2.prototype;
|
|
12061
|
-
_proto3.init = function init(src, env,
|
|
12061
|
+
_proto3.init = function init(src, env, path5, eagerCompile) {
|
|
12062
12062
|
this.env = env || new Environment;
|
|
12063
12063
|
if (lib.isObject(src)) {
|
|
12064
12064
|
switch (src.type) {
|
|
@@ -12076,7 +12076,7 @@ var require_environment = __commonJS((exports, module) => {
|
|
|
12076
12076
|
} else {
|
|
12077
12077
|
throw new Error("src must be a string or an object describing the source");
|
|
12078
12078
|
}
|
|
12079
|
-
this.path =
|
|
12079
|
+
this.path = path5;
|
|
12080
12080
|
if (eagerCompile) {
|
|
12081
12081
|
try {
|
|
12082
12082
|
this._compile();
|
|
@@ -12226,7 +12226,7 @@ var require_precompile_global = __commonJS((exports, module) => {
|
|
|
12226
12226
|
// node_modules/nunjucks/src/precompile.js
|
|
12227
12227
|
var require_precompile = __commonJS((exports, module) => {
|
|
12228
12228
|
var fs2 = __require("fs");
|
|
12229
|
-
var
|
|
12229
|
+
var path5 = __require("path");
|
|
12230
12230
|
var _require = require_lib();
|
|
12231
12231
|
var _prettifyError = _require._prettifyError;
|
|
12232
12232
|
var compiler = require_compiler();
|
|
@@ -12263,8 +12263,8 @@ var require_precompile = __commonJS((exports, module) => {
|
|
|
12263
12263
|
var templates = [];
|
|
12264
12264
|
function addTemplates(dir) {
|
|
12265
12265
|
fs2.readdirSync(dir).forEach(function(file) {
|
|
12266
|
-
var filepath =
|
|
12267
|
-
var subpath = filepath.substr(
|
|
12266
|
+
var filepath = path5.join(dir, file);
|
|
12267
|
+
var subpath = filepath.substr(path5.join(input, "/").length);
|
|
12268
12268
|
var stat = fs2.statSync(filepath);
|
|
12269
12269
|
if (stat && stat.isDirectory()) {
|
|
12270
12270
|
subpath += "/";
|
|
@@ -12281,7 +12281,7 @@ var require_precompile = __commonJS((exports, module) => {
|
|
|
12281
12281
|
} else if (pathStats.isDirectory()) {
|
|
12282
12282
|
addTemplates(input);
|
|
12283
12283
|
for (var i = 0;i < templates.length; i++) {
|
|
12284
|
-
var name = templates[i].replace(
|
|
12284
|
+
var name = templates[i].replace(path5.join(input, "/"), "");
|
|
12285
12285
|
try {
|
|
12286
12286
|
precompiled.push(_precompile(fs2.readFileSync(templates[i], "utf-8"), name, env));
|
|
12287
12287
|
} catch (e) {
|
|
@@ -12653,11 +12653,11 @@ var require_nunjucks = __commonJS((exports, module) => {
|
|
|
12653
12653
|
reset: function reset() {
|
|
12654
12654
|
e = undefined;
|
|
12655
12655
|
},
|
|
12656
|
-
compile: function compile(src, env,
|
|
12656
|
+
compile: function compile(src, env, path5, eagerCompile) {
|
|
12657
12657
|
if (!e) {
|
|
12658
12658
|
configure();
|
|
12659
12659
|
}
|
|
12660
|
-
return new Template(src, env,
|
|
12660
|
+
return new Template(src, env, path5, eagerCompile);
|
|
12661
12661
|
},
|
|
12662
12662
|
render: function render(name, ctx, cb) {
|
|
12663
12663
|
if (!e) {
|
|
@@ -28109,7 +28109,7 @@ var {
|
|
|
28109
28109
|
} = import__.default;
|
|
28110
28110
|
|
|
28111
28111
|
// src/cli/commands/css.ts
|
|
28112
|
-
import
|
|
28112
|
+
import path4 from "path";
|
|
28113
28113
|
|
|
28114
28114
|
// src/config.ts
|
|
28115
28115
|
import path from "path";
|
|
@@ -28225,33 +28225,141 @@ export default function(): SiteConfig {
|
|
|
28225
28225
|
|
|
28226
28226
|
// src/utils/css-processor.ts
|
|
28227
28227
|
import { spawn } from "child_process";
|
|
28228
|
+
var {hash } = globalThis.Bun;
|
|
28228
28229
|
import fs from "fs";
|
|
28230
|
+
import path3 from "path";
|
|
28231
|
+
|
|
28232
|
+
// src/utils/file-utils.ts
|
|
28233
|
+
var {Glob } = globalThis.Bun;
|
|
28229
28234
|
import path2 from "path";
|
|
28235
|
+
import { mkdir } from "fs/promises";
|
|
28236
|
+
async function findFilesByPattern(pattern, directory, absolute = true) {
|
|
28237
|
+
const glob = new Glob(pattern);
|
|
28238
|
+
const files = [];
|
|
28239
|
+
for await (const file of glob.scan({
|
|
28240
|
+
cwd: directory,
|
|
28241
|
+
absolute
|
|
28242
|
+
})) {
|
|
28243
|
+
files.push(file);
|
|
28244
|
+
}
|
|
28245
|
+
return files;
|
|
28246
|
+
}
|
|
28247
|
+
async function fileExists(filePath) {
|
|
28248
|
+
try {
|
|
28249
|
+
const file = Bun.file(filePath);
|
|
28250
|
+
return await file.exists();
|
|
28251
|
+
} catch {
|
|
28252
|
+
return false;
|
|
28253
|
+
}
|
|
28254
|
+
}
|
|
28255
|
+
async function isDirectory(dirPath) {
|
|
28256
|
+
try {
|
|
28257
|
+
const stat = await Bun.file(dirPath).stat();
|
|
28258
|
+
return stat?.isDirectory() ?? false;
|
|
28259
|
+
} catch {
|
|
28260
|
+
return false;
|
|
28261
|
+
}
|
|
28262
|
+
}
|
|
28263
|
+
async function readFileAsText(filePath) {
|
|
28264
|
+
try {
|
|
28265
|
+
const file = Bun.file(filePath);
|
|
28266
|
+
if (!await file.exists()) {
|
|
28267
|
+
return null;
|
|
28268
|
+
}
|
|
28269
|
+
return await file.text();
|
|
28270
|
+
} catch (error) {
|
|
28271
|
+
console.error(`Error reading file ${filePath}:`, error);
|
|
28272
|
+
return null;
|
|
28273
|
+
}
|
|
28274
|
+
}
|
|
28275
|
+
function getBaseFilename(filePath, extension = ".md") {
|
|
28276
|
+
const basename = path2.basename(filePath, extension);
|
|
28277
|
+
if (basename.toLowerCase() === "readme") {
|
|
28278
|
+
const dir = path2.dirname(filePath);
|
|
28279
|
+
return path2.basename(dir);
|
|
28280
|
+
}
|
|
28281
|
+
return basename;
|
|
28282
|
+
}
|
|
28283
|
+
async function createDir(dirPath) {
|
|
28284
|
+
try {
|
|
28285
|
+
await mkdir(dirPath, { recursive: true });
|
|
28286
|
+
} catch (error) {
|
|
28287
|
+
if (await isDirectory(dirPath)) {
|
|
28288
|
+
return;
|
|
28289
|
+
}
|
|
28290
|
+
if (await fileExists(dirPath)) {
|
|
28291
|
+
throw new Error(`Path exists but is not a directory: ${dirPath}`);
|
|
28292
|
+
}
|
|
28293
|
+
console.error(`Error creating directory ${dirPath}:`, error);
|
|
28294
|
+
throw error;
|
|
28295
|
+
}
|
|
28296
|
+
}
|
|
28297
|
+
async function ensureDir(dirPath) {
|
|
28298
|
+
return createDir(dirPath);
|
|
28299
|
+
}
|
|
28300
|
+
async function copyFile(sourcePath, targetPath) {
|
|
28301
|
+
try {
|
|
28302
|
+
const sourceFile = Bun.file(sourcePath);
|
|
28303
|
+
if (!await sourceFile.exists()) {
|
|
28304
|
+
throw new Error(`Source file does not exist: ${sourcePath}`);
|
|
28305
|
+
}
|
|
28306
|
+
await Bun.write(targetPath, sourceFile);
|
|
28307
|
+
} catch (error) {
|
|
28308
|
+
console.error(`Error copying file from ${sourcePath} to ${targetPath}:`, error);
|
|
28309
|
+
throw error;
|
|
28310
|
+
}
|
|
28311
|
+
}
|
|
28312
|
+
|
|
28313
|
+
// src/utils/css-processor.ts
|
|
28230
28314
|
async function processCSS(options2) {
|
|
28231
|
-
const {
|
|
28315
|
+
const {
|
|
28316
|
+
css,
|
|
28317
|
+
projectRoot,
|
|
28318
|
+
outputDir,
|
|
28319
|
+
verbose = false,
|
|
28320
|
+
enableHashing = false
|
|
28321
|
+
} = options2;
|
|
28232
28322
|
if (!css.enabled) {
|
|
28233
28323
|
if (verbose) {
|
|
28234
28324
|
console.log("CSS processing is disabled");
|
|
28235
28325
|
}
|
|
28236
|
-
return;
|
|
28326
|
+
return { outputPath: "" };
|
|
28237
28327
|
}
|
|
28238
|
-
const inputPath =
|
|
28239
|
-
const
|
|
28240
|
-
const postcssConfigPath = css.postcssConfig ?
|
|
28241
|
-
|
|
28242
|
-
|
|
28243
|
-
} catch (error) {
|
|
28328
|
+
const inputPath = path3.resolve(projectRoot, css.input);
|
|
28329
|
+
const tempOutputPath = path3.resolve(outputDir, css.output);
|
|
28330
|
+
const postcssConfigPath = css.postcssConfig ? path3.resolve(projectRoot, css.postcssConfig) : path3.resolve(projectRoot, "postcss.config.js");
|
|
28331
|
+
const inputFile = Bun.file(inputPath);
|
|
28332
|
+
if (!await inputFile.exists()) {
|
|
28244
28333
|
throw new Error(`CSS input file not found: ${inputPath}`);
|
|
28245
28334
|
}
|
|
28246
|
-
const outputDirPath =
|
|
28247
|
-
await
|
|
28335
|
+
const outputDirPath = path3.dirname(tempOutputPath);
|
|
28336
|
+
await ensureDir(outputDirPath);
|
|
28248
28337
|
if (verbose) {
|
|
28249
28338
|
console.log("\uD83C\uDFA8 Building CSS with PostCSS...");
|
|
28250
28339
|
console.log(`Input: ${inputPath}`);
|
|
28251
|
-
console.log(`Output: ${
|
|
28340
|
+
console.log(`Output: ${tempOutputPath}`);
|
|
28252
28341
|
console.log(`Config: ${postcssConfigPath}`);
|
|
28253
28342
|
}
|
|
28254
|
-
await runPostCSS(inputPath,
|
|
28343
|
+
await runPostCSS(inputPath, tempOutputPath, postcssConfigPath, projectRoot, verbose);
|
|
28344
|
+
if (enableHashing) {
|
|
28345
|
+
const cssFile = Bun.file(tempOutputPath);
|
|
28346
|
+
const cssContent = await cssFile.arrayBuffer();
|
|
28347
|
+
const contentHash = hash(cssContent).toString(36).slice(0, 8);
|
|
28348
|
+
const ext = path3.extname(tempOutputPath);
|
|
28349
|
+
const basename = path3.basename(tempOutputPath, ext);
|
|
28350
|
+
const dir = path3.dirname(tempOutputPath);
|
|
28351
|
+
const hashedFilename = `${basename}.${contentHash}${ext}`;
|
|
28352
|
+
const hashedOutputPath = path3.join(dir, hashedFilename);
|
|
28353
|
+
await Bun.write(hashedOutputPath, cssFile);
|
|
28354
|
+
if (verbose) {
|
|
28355
|
+
console.log(`\u2705 CSS hashed: ${hashedFilename}`);
|
|
28356
|
+
}
|
|
28357
|
+
return {
|
|
28358
|
+
outputPath: hashedOutputPath,
|
|
28359
|
+
hash: contentHash
|
|
28360
|
+
};
|
|
28361
|
+
}
|
|
28362
|
+
return { outputPath: tempOutputPath };
|
|
28255
28363
|
}
|
|
28256
28364
|
function runPostCSS(inputPath, outputPath, configPath, projectRoot, verbose) {
|
|
28257
28365
|
return new Promise((resolve, reject) => {
|
|
@@ -28291,8 +28399,8 @@ async function watchCSS(options2) {
|
|
|
28291
28399
|
if (!css.enabled || !css.watch) {
|
|
28292
28400
|
return;
|
|
28293
28401
|
}
|
|
28294
|
-
const inputPath =
|
|
28295
|
-
const watchDir =
|
|
28402
|
+
const inputPath = path3.resolve(projectRoot, css.input);
|
|
28403
|
+
const watchDir = path3.dirname(inputPath);
|
|
28296
28404
|
if (verbose) {
|
|
28297
28405
|
console.log(`\uD83D\uDC40 Watching CSS files in ${watchDir}...`);
|
|
28298
28406
|
}
|
|
@@ -28336,8 +28444,8 @@ var defaultDeps = {
|
|
|
28336
28444
|
};
|
|
28337
28445
|
async function handleCssCommand(options2, deps = defaultDeps) {
|
|
28338
28446
|
try {
|
|
28339
|
-
const configPath =
|
|
28340
|
-
const outputDir =
|
|
28447
|
+
const configPath = path4.resolve(options2.config);
|
|
28448
|
+
const outputDir = path4.resolve(options2.output);
|
|
28341
28449
|
const config = await deps.loadConfig(configPath);
|
|
28342
28450
|
const cssConfig = config.css || deps.getDefaultCSSConfig();
|
|
28343
28451
|
if (!cssConfig.enabled) {
|
|
@@ -28370,102 +28478,29 @@ function registerCssCommand(program2) {
|
|
|
28370
28478
|
}
|
|
28371
28479
|
|
|
28372
28480
|
// src/cli/commands/generate.ts
|
|
28373
|
-
import
|
|
28481
|
+
import path9 from "path";
|
|
28374
28482
|
|
|
28375
28483
|
// src/site-generator.ts
|
|
28376
|
-
var
|
|
28484
|
+
var import_nunjucks2 = __toESM(require_nunjucks(), 1);
|
|
28377
28485
|
var import_slugify = __toESM(require_slugify(), 1);
|
|
28378
|
-
|
|
28379
|
-
import fs2 from "fs";
|
|
28380
|
-
import path6 from "path";
|
|
28486
|
+
import path8 from "path";
|
|
28381
28487
|
|
|
28382
28488
|
// src/parser.ts
|
|
28383
28489
|
import path5 from "path";
|
|
28384
28490
|
|
|
28385
|
-
// src/utils/file-utils.ts
|
|
28386
|
-
var {Glob } = globalThis.Bun;
|
|
28387
|
-
import path4 from "path";
|
|
28388
|
-
import { mkdir } from "fs/promises";
|
|
28389
|
-
async function findFilesByPattern(pattern, directory, absolute = true) {
|
|
28390
|
-
const glob = new Glob(pattern);
|
|
28391
|
-
const files = [];
|
|
28392
|
-
for await (const file of glob.scan({
|
|
28393
|
-
cwd: directory,
|
|
28394
|
-
absolute
|
|
28395
|
-
})) {
|
|
28396
|
-
files.push(file);
|
|
28397
|
-
}
|
|
28398
|
-
return files;
|
|
28399
|
-
}
|
|
28400
|
-
async function fileExists(filePath) {
|
|
28401
|
-
try {
|
|
28402
|
-
const file = Bun.file(filePath);
|
|
28403
|
-
return await file.exists();
|
|
28404
|
-
} catch {
|
|
28405
|
-
return false;
|
|
28406
|
-
}
|
|
28407
|
-
}
|
|
28408
|
-
async function isDirectory(dirPath) {
|
|
28409
|
-
try {
|
|
28410
|
-
const stat = await Bun.file(dirPath).stat();
|
|
28411
|
-
return stat?.isDirectory() ?? false;
|
|
28412
|
-
} catch {
|
|
28413
|
-
return false;
|
|
28414
|
-
}
|
|
28415
|
-
}
|
|
28416
|
-
async function readFileAsText(filePath) {
|
|
28417
|
-
try {
|
|
28418
|
-
const file = Bun.file(filePath);
|
|
28419
|
-
if (!await file.exists()) {
|
|
28420
|
-
return null;
|
|
28421
|
-
}
|
|
28422
|
-
return await file.text();
|
|
28423
|
-
} catch (error) {
|
|
28424
|
-
console.error(`Error reading file ${filePath}:`, error);
|
|
28425
|
-
return null;
|
|
28426
|
-
}
|
|
28427
|
-
}
|
|
28428
|
-
function getBaseFilename(filePath, extension = ".md") {
|
|
28429
|
-
const basename = path4.basename(filePath, extension);
|
|
28430
|
-
if (basename.toLowerCase() === "readme") {
|
|
28431
|
-
const dir = path4.dirname(filePath);
|
|
28432
|
-
return path4.basename(dir);
|
|
28433
|
-
}
|
|
28434
|
-
return basename;
|
|
28435
|
-
}
|
|
28436
|
-
async function createDir(dirPath) {
|
|
28437
|
-
try {
|
|
28438
|
-
await mkdir(dirPath, { recursive: true });
|
|
28439
|
-
} catch (error) {
|
|
28440
|
-
if (await isDirectory(dirPath)) {
|
|
28441
|
-
return;
|
|
28442
|
-
}
|
|
28443
|
-
if (await fileExists(dirPath)) {
|
|
28444
|
-
throw new Error(`Path exists but is not a directory: ${dirPath}`);
|
|
28445
|
-
}
|
|
28446
|
-
console.error(`Error creating directory ${dirPath}:`, error);
|
|
28447
|
-
throw error;
|
|
28448
|
-
}
|
|
28449
|
-
}
|
|
28450
|
-
async function ensureDir(dirPath) {
|
|
28451
|
-
return createDir(dirPath);
|
|
28452
|
-
}
|
|
28453
|
-
async function copyFile(sourcePath, targetPath) {
|
|
28454
|
-
try {
|
|
28455
|
-
const sourceFile = Bun.file(sourcePath);
|
|
28456
|
-
if (!await sourceFile.exists()) {
|
|
28457
|
-
throw new Error(`Source file does not exist: ${sourcePath}`);
|
|
28458
|
-
}
|
|
28459
|
-
await Bun.write(targetPath, sourceFile);
|
|
28460
|
-
} catch (error) {
|
|
28461
|
-
console.error(`Error copying file from ${sourcePath} to ${targetPath}:`, error);
|
|
28462
|
-
throw error;
|
|
28463
|
-
}
|
|
28464
|
-
}
|
|
28465
|
-
|
|
28466
28491
|
// src/utils/markdown-utils.ts
|
|
28467
28492
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
28468
28493
|
|
|
28494
|
+
// src/utils/date-utils.ts
|
|
28495
|
+
function toPacificTime(date) {
|
|
28496
|
+
return new Date(new Date(date).toLocaleString("en-US", {
|
|
28497
|
+
timeZone: "America/Los_Angeles"
|
|
28498
|
+
}));
|
|
28499
|
+
}
|
|
28500
|
+
function getPacificYear(date) {
|
|
28501
|
+
return toPacificTime(date).getFullYear();
|
|
28502
|
+
}
|
|
28503
|
+
|
|
28469
28504
|
// node_modules/highlight.js/es/core.js
|
|
28470
28505
|
var import_core = __toESM(require_core2(), 1);
|
|
28471
28506
|
var core_default = import_core.default;
|
|
@@ -32887,20 +32922,58 @@ function escape(html, encode) {
|
|
|
32887
32922
|
return html;
|
|
32888
32923
|
}
|
|
32889
32924
|
|
|
32890
|
-
// src/utils/markdown
|
|
32925
|
+
// src/utils/markdown/parser.ts
|
|
32891
32926
|
var import_sanitize_html = __toESM(require_sanitize_html(), 1);
|
|
32892
32927
|
|
|
32893
|
-
// src/utils/
|
|
32894
|
-
|
|
32895
|
-
|
|
32896
|
-
|
|
32897
|
-
|
|
32898
|
-
|
|
32899
|
-
|
|
32900
|
-
|
|
32901
|
-
|
|
32928
|
+
// src/utils/markdown/constants.ts
|
|
32929
|
+
var RELATIVE_LINK_REGEX = /^(\.\.\/)+(\d{4})\/([a-zA-Z0-9_-]+?)(?:\.md)?(?:\/)?(#[^#]*)?$/;
|
|
32930
|
+
var IMAGE_PATH_REGEX = /^\.\.\/\.\.\/assets\/(\d{4})\/([^/]+)\/(.+)$/;
|
|
32931
|
+
var YOUTUBE_EMBED_REGEX = /<a href="(https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)[^"]*)"[^>]*>(.*?)<\/a>/g;
|
|
32932
|
+
var EXTERNAL_LINK_REGEX = /<a href="(https?:\/\/|\/\/)([^"]+)"/g;
|
|
32933
|
+
var SCHEMA_ORG_PLACE_TYPES = new Set([
|
|
32934
|
+
"Accommodation",
|
|
32935
|
+
"Apartment",
|
|
32936
|
+
"Attraction",
|
|
32937
|
+
"Beach",
|
|
32938
|
+
"BodyOfWater",
|
|
32939
|
+
"Bridge",
|
|
32940
|
+
"Building",
|
|
32941
|
+
"BusStation",
|
|
32942
|
+
"Cafe",
|
|
32943
|
+
"Campground",
|
|
32944
|
+
"CivicStructure",
|
|
32945
|
+
"EventVenue",
|
|
32946
|
+
"Ferry",
|
|
32947
|
+
"Garden",
|
|
32948
|
+
"HistoricalSite",
|
|
32949
|
+
"Hotel",
|
|
32950
|
+
"Hostel",
|
|
32951
|
+
"Landmark",
|
|
32952
|
+
"LodgingBusiness",
|
|
32953
|
+
"Market",
|
|
32954
|
+
"Monument",
|
|
32955
|
+
"Museum",
|
|
32956
|
+
"NaturalFeature",
|
|
32957
|
+
"Park",
|
|
32958
|
+
"Playground",
|
|
32959
|
+
"Restaurant",
|
|
32960
|
+
"ServiceCenter",
|
|
32961
|
+
"ShoppingCenter",
|
|
32962
|
+
"Store",
|
|
32963
|
+
"TouristAttraction",
|
|
32964
|
+
"TrainStation",
|
|
32965
|
+
"Viewpoint",
|
|
32966
|
+
"Zoo"
|
|
32967
|
+
]);
|
|
32968
|
+
var ALERT_ICONS = {
|
|
32969
|
+
note: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-7-4a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM9 9a.75.75 0 0 0 0 1.5h.253a.25.25 0 0 1 .244.304l-.459 2.066A1.75 1.75 0 0 0 10.747 15H11a.75.75 0 0 0 0-1.5h-.253a.25.25 0 0 1-.244-.304l.459-2.066A1.75 1.75 0 0 0 9.253 9H9Z" clip-rule="evenodd" /></svg>',
|
|
32970
|
+
tip: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M10 1a6 6 0 0 0-3.815 10.631C7.237 12.5 8 13.443 8 14.456v.644a.75.75 0 0 0 .75.75h2.5a.75.75 0 0 0 .75-.75v-.644c0-1.013.762-1.957 1.815-2.825A6 6 0 0 0 10 1ZM8.863 17.414a.75.75 0 0 0-.226 1.483 9.066 9.066 0 0 0 2.726 0 .75.75 0 0 0-.226-1.483 7.553 7.553 0 0 1-2.274 0Z" /></svg>',
|
|
32971
|
+
important: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-8-5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-1.5 0v-4.5A.75.75 0 0 1 10 5Zm0 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" clip-rule="evenodd" /></svg>',
|
|
32972
|
+
warning: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 10 5Zm0 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" clip-rule="evenodd" /></svg>',
|
|
32973
|
+
caution: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z" clip-rule="evenodd" /></svg>'
|
|
32974
|
+
};
|
|
32902
32975
|
|
|
32903
|
-
// src/utils/markdown
|
|
32976
|
+
// src/utils/markdown/parser.ts
|
|
32904
32977
|
core_default.registerLanguage("javascript", javascript);
|
|
32905
32978
|
core_default.registerLanguage("typescript", typescript);
|
|
32906
32979
|
core_default.registerLanguage("markdown", markdown);
|
|
@@ -32910,8 +32983,11 @@ core_default.registerLanguage("python", python);
|
|
|
32910
32983
|
core_default.registerLanguage("json", json);
|
|
32911
32984
|
core_default.registerLanguage("swift", swift);
|
|
32912
32985
|
var noFollowExceptions = new Set;
|
|
32986
|
+
function setNoFollowExceptions(exceptions) {
|
|
32987
|
+
noFollowExceptions = new Set(exceptions.map((domain) => domain.toLowerCase().replace(/^www\./, "")));
|
|
32988
|
+
}
|
|
32913
32989
|
function transformImagePath(relativePath, config) {
|
|
32914
|
-
const match = relativePath.match(
|
|
32990
|
+
const match = relativePath.match(IMAGE_PATH_REGEX);
|
|
32915
32991
|
if (!match)
|
|
32916
32992
|
return null;
|
|
32917
32993
|
const [, year, slug, filename] = match;
|
|
@@ -32932,37 +33008,19 @@ function createMarked(cdnConfig) {
|
|
|
32932
33008
|
breaks: true
|
|
32933
33009
|
});
|
|
32934
33010
|
marked.use(A({
|
|
32935
|
-
variants: [
|
|
32936
|
-
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
},
|
|
32940
|
-
{
|
|
32941
|
-
type: "tip",
|
|
32942
|
-
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M10 1a6 6 0 0 0-3.815 10.631C7.237 12.5 8 13.443 8 14.456v.644a.75.75 0 0 0 .75.75h2.5a.75.75 0 0 0 .75-.75v-.644c0-1.013.762-1.957 1.815-2.825A6 6 0 0 0 10 1ZM8.863 17.414a.75.75 0 0 0-.226 1.483 9.066 9.066 0 0 0 2.726 0 .75.75 0 0 0-.226-1.483 7.553 7.553 0 0 1-2.274 0Z" /></svg>'
|
|
32943
|
-
},
|
|
32944
|
-
{
|
|
32945
|
-
type: "important",
|
|
32946
|
-
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-8-5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-1.5 0v-4.5A.75.75 0 0 1 10 5Zm0 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" clip-rule="evenodd" /></svg>'
|
|
32947
|
-
},
|
|
32948
|
-
{
|
|
32949
|
-
type: "warning",
|
|
32950
|
-
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 10 5Zm0 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" clip-rule="evenodd" /></svg>'
|
|
32951
|
-
},
|
|
32952
|
-
{
|
|
32953
|
-
type: "caution",
|
|
32954
|
-
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z" clip-rule="evenodd" /></svg>'
|
|
32955
|
-
}
|
|
32956
|
-
]
|
|
33011
|
+
variants: Object.entries(ALERT_ICONS).map(([type, icon]) => ({
|
|
33012
|
+
type,
|
|
33013
|
+
icon
|
|
33014
|
+
}))
|
|
32957
33015
|
}));
|
|
32958
33016
|
marked.use({
|
|
32959
33017
|
walkTokens(token) {
|
|
32960
33018
|
if (token.type === "link") {
|
|
32961
33019
|
token.href = token.href || "";
|
|
32962
|
-
|
|
33020
|
+
const relativeMatch = token.href.match(RELATIVE_LINK_REGEX);
|
|
32963
33021
|
if (relativeMatch) {
|
|
32964
|
-
const [, , year, slug] = relativeMatch;
|
|
32965
|
-
token.href = `/${year}/${slug}
|
|
33022
|
+
const [, , year, slug, anchor = ""] = relativeMatch;
|
|
33023
|
+
token.href = `/${year}/${slug}/${anchor}`;
|
|
32966
33024
|
}
|
|
32967
33025
|
const isExternal = token.href && (token.href.startsWith("http://") || token.href.startsWith("https://") || token.href.startsWith("//"));
|
|
32968
33026
|
if (isExternal) {
|
|
@@ -32987,9 +33045,9 @@ function createMarked(cdnConfig) {
|
|
|
32987
33045
|
return markdown2;
|
|
32988
33046
|
},
|
|
32989
33047
|
postprocess(html) {
|
|
32990
|
-
html = html.replace(
|
|
33048
|
+
html = html.replace(YOUTUBE_EMBED_REGEX, '<div class="video-container"><iframe src="https://www.youtube.com/embed/$4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>');
|
|
32991
33049
|
html = html.replace(/<img /g, '<img loading="lazy" ');
|
|
32992
|
-
return html.replace(
|
|
33050
|
+
return html.replace(EXTERNAL_LINK_REGEX, (match, protocol, rest) => {
|
|
32993
33051
|
const fullUrl = protocol + rest;
|
|
32994
33052
|
let relAttr = 'rel="noopener noreferrer';
|
|
32995
33053
|
try {
|
|
@@ -33009,23 +33067,9 @@ function createMarked(cdnConfig) {
|
|
|
33009
33067
|
});
|
|
33010
33068
|
return marked;
|
|
33011
33069
|
}
|
|
33012
|
-
var marked = createMarked();
|
|
33013
|
-
function setNoFollowExceptions(exceptions) {
|
|
33014
|
-
noFollowExceptions = new Set(exceptions.map((domain) => domain.toLowerCase().replace(/^www\./, "")));
|
|
33015
|
-
marked = createMarked();
|
|
33016
|
-
}
|
|
33017
|
-
function extractExcerpt(content, maxLength = 200) {
|
|
33018
|
-
const plainText = content.replace(/^#.*$/gm, "").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[*_]{1,2}([^*_]+)[*_]{1,2}/g, "$1").replace(/\n+/g, " ").trim();
|
|
33019
|
-
if (plainText.length <= maxLength) {
|
|
33020
|
-
return plainText;
|
|
33021
|
-
}
|
|
33022
|
-
const truncated = plainText.substring(0, maxLength);
|
|
33023
|
-
const lastSpace = truncated.lastIndexOf(" ");
|
|
33024
|
-
return truncated.substring(0, lastSpace) + "...";
|
|
33025
|
-
}
|
|
33026
33070
|
function convertMarkdownToHtml(markdownContent, cdnConfig) {
|
|
33027
|
-
const
|
|
33028
|
-
const html =
|
|
33071
|
+
const marked = createMarked(cdnConfig);
|
|
33072
|
+
const html = marked.parse(markdownContent, { async: false });
|
|
33029
33073
|
let sanitized = import_sanitize_html.default(html, {
|
|
33030
33074
|
allowedTags: import_sanitize_html.default.defaults.allowedTags.concat([
|
|
33031
33075
|
"img",
|
|
@@ -33091,6 +33135,17 @@ function convertMarkdownToHtml(markdownContent, cdnConfig) {
|
|
|
33091
33135
|
sanitized = sanitized.replace(/javascript:/gi, "").replace(/vbscript:/gi, "");
|
|
33092
33136
|
return sanitized;
|
|
33093
33137
|
}
|
|
33138
|
+
function extractExcerpt(content, maxLength = 200) {
|
|
33139
|
+
const plainText = content.replace(/^#.*$/gm, "").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[*_]{1,2}([^*_]+)[*_]{1,2}/g, "$1").replace(/\n+/g, " ").trim();
|
|
33140
|
+
if (plainText.length <= maxLength) {
|
|
33141
|
+
return plainText;
|
|
33142
|
+
}
|
|
33143
|
+
const truncated = plainText.substring(0, maxLength);
|
|
33144
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
33145
|
+
return truncated.substring(0, lastSpace) + "...";
|
|
33146
|
+
}
|
|
33147
|
+
|
|
33148
|
+
// src/utils/markdown/validators.ts
|
|
33094
33149
|
function validateBusinessLocation(business, filePath) {
|
|
33095
33150
|
if (!business)
|
|
33096
33151
|
return null;
|
|
@@ -33106,47 +33161,13 @@ function validateBusinessLocation(business, filePath) {
|
|
|
33106
33161
|
suggestion: "Add 'type: Restaurant' (or Market, Park, Hotel, Museum, Cafe, Zoo, etc.) to frontmatter"
|
|
33107
33162
|
};
|
|
33108
33163
|
}
|
|
33109
|
-
|
|
33110
|
-
|
|
33111
|
-
"Apartment",
|
|
33112
|
-
"Attraction",
|
|
33113
|
-
"Beach",
|
|
33114
|
-
"BodyOfWater",
|
|
33115
|
-
"Bridge",
|
|
33116
|
-
"Building",
|
|
33117
|
-
"BusStation",
|
|
33118
|
-
"Cafe",
|
|
33119
|
-
"Campground",
|
|
33120
|
-
"CivicStructure",
|
|
33121
|
-
"EventVenue",
|
|
33122
|
-
"Ferry",
|
|
33123
|
-
"Garden",
|
|
33124
|
-
"HistoricalSite",
|
|
33125
|
-
"Hotel",
|
|
33126
|
-
"Hostel",
|
|
33127
|
-
"Landmark",
|
|
33128
|
-
"LodgingBusiness",
|
|
33129
|
-
"Market",
|
|
33130
|
-
"Monument",
|
|
33131
|
-
"Museum",
|
|
33132
|
-
"NaturalFeature",
|
|
33133
|
-
"Park",
|
|
33134
|
-
"Playground",
|
|
33135
|
-
"Restaurant",
|
|
33136
|
-
"ServiceCenter",
|
|
33137
|
-
"ShoppingCenter",
|
|
33138
|
-
"Store",
|
|
33139
|
-
"TouristAttraction",
|
|
33140
|
-
"TrainStation",
|
|
33141
|
-
"Viewpoint",
|
|
33142
|
-
"Zoo"
|
|
33143
|
-
];
|
|
33144
|
-
if (!validTypes.includes(loc.type)) {
|
|
33164
|
+
if (!SCHEMA_ORG_PLACE_TYPES.has(loc.type)) {
|
|
33165
|
+
const exampleTypes = Array.from(SCHEMA_ORG_PLACE_TYPES).slice(0, 10);
|
|
33145
33166
|
return {
|
|
33146
33167
|
file: filePath,
|
|
33147
33168
|
type: "validation",
|
|
33148
33169
|
message: `Invalid business type '${loc.type}' in business${locIndex}`,
|
|
33149
|
-
suggestion: `Use a valid Schema.org Place type: ${
|
|
33170
|
+
suggestion: `Use a valid Schema.org Place type: ${exampleTypes.join(", ")}, etc.`
|
|
33150
33171
|
};
|
|
33151
33172
|
}
|
|
33152
33173
|
if (!loc.name) {
|
|
@@ -33177,6 +33198,33 @@ function validateBusinessLocation(business, filePath) {
|
|
|
33177
33198
|
}
|
|
33178
33199
|
return null;
|
|
33179
33200
|
}
|
|
33201
|
+
function validateTags(tags, filePath) {
|
|
33202
|
+
if (!tags || !Array.isArray(tags))
|
|
33203
|
+
return null;
|
|
33204
|
+
const tagsWithSpaces = tags.filter((tag) => tag.includes(" "));
|
|
33205
|
+
if (tagsWithSpaces.length > 0) {
|
|
33206
|
+
return {
|
|
33207
|
+
file: filePath,
|
|
33208
|
+
type: "validation",
|
|
33209
|
+
message: `Tags must not contain spaces. Found: ${tagsWithSpaces.map((t) => `"${t}"`).join(", ")}`,
|
|
33210
|
+
suggestion: `Use hyphens instead of spaces. Example: "new-york-city" instead of "new york city"`
|
|
33211
|
+
};
|
|
33212
|
+
}
|
|
33213
|
+
return null;
|
|
33214
|
+
}
|
|
33215
|
+
function checkDeprecatedLocationField(data, filePath) {
|
|
33216
|
+
if (data && data.location) {
|
|
33217
|
+
return {
|
|
33218
|
+
file: filePath,
|
|
33219
|
+
type: "validation",
|
|
33220
|
+
message: "Use 'business:' instead of deprecated 'location:' field",
|
|
33221
|
+
suggestion: "Replace 'location:' with 'business:' in frontmatter (business requires type, name, lat, lng)"
|
|
33222
|
+
};
|
|
33223
|
+
}
|
|
33224
|
+
return null;
|
|
33225
|
+
}
|
|
33226
|
+
|
|
33227
|
+
// src/utils/markdown-utils.ts
|
|
33180
33228
|
async function parseMarkdownFile(filePath, cdnConfig) {
|
|
33181
33229
|
try {
|
|
33182
33230
|
const fileContent = await readFileAsText(filePath);
|
|
@@ -33207,15 +33255,11 @@ async function parseMarkdownFile(filePath, cdnConfig) {
|
|
|
33207
33255
|
}
|
|
33208
33256
|
};
|
|
33209
33257
|
}
|
|
33210
|
-
|
|
33258
|
+
const deprecatedFieldError = checkDeprecatedLocationField(data, filePath);
|
|
33259
|
+
if (deprecatedFieldError) {
|
|
33211
33260
|
return {
|
|
33212
33261
|
post: null,
|
|
33213
|
-
error:
|
|
33214
|
-
file: filePath,
|
|
33215
|
-
type: "validation",
|
|
33216
|
-
message: "Use 'business:' instead of deprecated 'location:' field",
|
|
33217
|
-
suggestion: "Replace 'location:' with 'business:' in frontmatter (business requires type, name, lat, lng)"
|
|
33218
|
-
}
|
|
33262
|
+
error: deprecatedFieldError
|
|
33219
33263
|
};
|
|
33220
33264
|
}
|
|
33221
33265
|
if (data.business) {
|
|
@@ -33228,20 +33272,15 @@ async function parseMarkdownFile(filePath, cdnConfig) {
|
|
|
33228
33272
|
}
|
|
33229
33273
|
}
|
|
33230
33274
|
if (data.tags && Array.isArray(data.tags)) {
|
|
33231
|
-
const
|
|
33232
|
-
if (
|
|
33275
|
+
const tagsError = validateTags(data.tags, filePath);
|
|
33276
|
+
if (tagsError) {
|
|
33233
33277
|
return {
|
|
33234
33278
|
post: null,
|
|
33235
|
-
error:
|
|
33236
|
-
file: filePath,
|
|
33237
|
-
type: "validation",
|
|
33238
|
-
message: `Tags must not contain spaces. Found: ${tagsWithSpaces.map((t) => `"${t}"`).join(", ")}`,
|
|
33239
|
-
suggestion: `Use hyphens instead of spaces. Example: "new-york-city" instead of "new york city"`
|
|
33240
|
-
}
|
|
33279
|
+
error: tagsError
|
|
33241
33280
|
};
|
|
33242
33281
|
}
|
|
33243
33282
|
}
|
|
33244
|
-
|
|
33283
|
+
const slug = getBaseFilename(filePath);
|
|
33245
33284
|
const sanitizedHtml = convertMarkdownToHtml(content, cdnConfig);
|
|
33246
33285
|
const pacificDate = toPacificTime(data.date);
|
|
33247
33286
|
const postYear = getPacificYear(data.date);
|
|
@@ -33599,43 +33638,569 @@ function generateHomePageSchemas(options2) {
|
|
|
33599
33638
|
return schemas;
|
|
33600
33639
|
}
|
|
33601
33640
|
|
|
33602
|
-
// src/
|
|
33603
|
-
|
|
33604
|
-
|
|
33605
|
-
|
|
33606
|
-
|
|
33607
|
-
|
|
33641
|
+
// src/utils/xml-builder.ts
|
|
33642
|
+
function escapeXml(text) {
|
|
33643
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
33644
|
+
}
|
|
33645
|
+
function buildSitemapUrl(loc, lastmod, changefreq, priority) {
|
|
33646
|
+
return ` <url>
|
|
33647
|
+
<loc>${loc}</loc>
|
|
33648
|
+
<lastmod>${lastmod}</lastmod>
|
|
33649
|
+
<changefreq>${changefreq}</changefreq>
|
|
33650
|
+
<priority>${priority.toFixed(1)}</priority>
|
|
33651
|
+
</url>
|
|
33652
|
+
`;
|
|
33653
|
+
}
|
|
33654
|
+
function calculateFreshnessPriority(date, basePriority, now = Date.now()) {
|
|
33655
|
+
const ONE_DAY = 24 * 60 * 60 * 1000;
|
|
33656
|
+
const ONE_WEEK = 7 * ONE_DAY;
|
|
33657
|
+
const ONE_MONTH = 30 * ONE_DAY;
|
|
33658
|
+
const postTime = new Date(date).getTime();
|
|
33659
|
+
const age = now - postTime;
|
|
33660
|
+
if (age < ONE_WEEK) {
|
|
33661
|
+
return Math.min(1, basePriority + 0.2);
|
|
33662
|
+
} else if (age < ONE_MONTH) {
|
|
33663
|
+
return Math.min(1, basePriority + 0.1);
|
|
33664
|
+
}
|
|
33665
|
+
return basePriority;
|
|
33666
|
+
}
|
|
33667
|
+
function buildRSSItem(params) {
|
|
33668
|
+
const { title, link, pubDate, description, content, tags, author, image } = params;
|
|
33669
|
+
const categoryTags = tags?.map((tag) => ` <category>${escapeXml(tag)}</category>`).join(`
|
|
33670
|
+
`) || "";
|
|
33671
|
+
let itemXml = ` <item>
|
|
33672
|
+
<title><![CDATA[${title}]]></title>
|
|
33673
|
+
<link>${link}</link>
|
|
33674
|
+
<guid isPermaLink="true">${link}</guid>
|
|
33675
|
+
<pubDate>${pubDate}</pubDate>`;
|
|
33676
|
+
if (author) {
|
|
33677
|
+
itemXml += `
|
|
33678
|
+
<author>${author}</author>`;
|
|
33679
|
+
}
|
|
33680
|
+
let fullDescription = description;
|
|
33681
|
+
if (image) {
|
|
33682
|
+
fullDescription = `<img src="${escapeXml(image)}" alt="" style="max-width:100%; height:auto;" /><br/><br/>${description}`;
|
|
33683
|
+
}
|
|
33684
|
+
itemXml += `
|
|
33685
|
+
<description><![CDATA[${fullDescription}]]></description>`;
|
|
33686
|
+
if (categoryTags) {
|
|
33687
|
+
itemXml += `
|
|
33688
|
+
${categoryTags}`;
|
|
33608
33689
|
}
|
|
33609
|
-
|
|
33610
|
-
|
|
33611
|
-
|
|
33612
|
-
|
|
33613
|
-
|
|
33614
|
-
|
|
33690
|
+
itemXml += `
|
|
33691
|
+
<content:encoded><![CDATA[${content}]]></content:encoded>`;
|
|
33692
|
+
if (image) {
|
|
33693
|
+
itemXml += `
|
|
33694
|
+
<media:thumbnail url="${escapeXml(image)}" />`;
|
|
33695
|
+
itemXml += `
|
|
33696
|
+
<enclosure url="${escapeXml(image)}" type="image/jpeg" length="0" />`;
|
|
33697
|
+
}
|
|
33698
|
+
itemXml += `
|
|
33699
|
+
</item>`;
|
|
33700
|
+
return itemXml;
|
|
33701
|
+
}
|
|
33702
|
+
|
|
33703
|
+
// src/utils/pagination.ts
|
|
33704
|
+
function createPagination(items, currentPage, pageSize, pagePath) {
|
|
33705
|
+
const totalItems = items.length;
|
|
33706
|
+
const totalPages = Math.ceil(totalItems / pageSize);
|
|
33707
|
+
return {
|
|
33708
|
+
currentPage,
|
|
33709
|
+
totalPages,
|
|
33710
|
+
hasNextPage: currentPage < totalPages,
|
|
33711
|
+
hasPrevPage: currentPage > 1,
|
|
33712
|
+
nextPage: currentPage < totalPages ? currentPage + 1 : null,
|
|
33713
|
+
prevPage: currentPage > 1 ? currentPage - 1 : null,
|
|
33714
|
+
pageSize,
|
|
33715
|
+
totalItems,
|
|
33716
|
+
pagePath
|
|
33717
|
+
};
|
|
33718
|
+
}
|
|
33719
|
+
function getPaginatedItems(items, page, pageSize) {
|
|
33720
|
+
const startIndex = (page - 1) * pageSize;
|
|
33721
|
+
const endIndex = startIndex + pageSize;
|
|
33722
|
+
return items.slice(startIndex, endIndex);
|
|
33723
|
+
}
|
|
33724
|
+
function getTotalPages(totalItems, pageSize) {
|
|
33725
|
+
return Math.ceil(totalItems / pageSize);
|
|
33726
|
+
}
|
|
33727
|
+
|
|
33728
|
+
// src/generators/feeds.ts
|
|
33729
|
+
function extractFirstImageUrl2(html) {
|
|
33730
|
+
const imgRegex = /<img[^>]+src=["']([^"']+)["']/;
|
|
33731
|
+
const match = html.match(imgRegex);
|
|
33732
|
+
return match ? match[1] : null;
|
|
33733
|
+
}
|
|
33734
|
+
function makeAbsoluteUrl(imageUrl, baseUrl) {
|
|
33735
|
+
return imageUrl.startsWith("http") ? imageUrl : `${baseUrl}${imageUrl}`;
|
|
33736
|
+
}
|
|
33737
|
+
function formatRSSDate(date) {
|
|
33738
|
+
return toPacificTime(date).toUTCString();
|
|
33739
|
+
}
|
|
33740
|
+
function generateRSSFeed(site, config) {
|
|
33741
|
+
const posts = site.posts.slice(0, 15);
|
|
33742
|
+
const now = toPacificTime(new Date);
|
|
33743
|
+
const latestPostDate = posts.length > 0 ? posts[0].date : now.toISOString();
|
|
33744
|
+
const lastBuildDate = formatRSSDate(latestPostDate);
|
|
33745
|
+
const rssItems = posts.map((post) => {
|
|
33746
|
+
const postUrl = `${config.baseUrl}${post.url}`;
|
|
33747
|
+
const pubDate = formatRSSDate(post.date);
|
|
33748
|
+
const featuredImage = extractFirstImageUrl2(post.html);
|
|
33749
|
+
const absoluteImageUrl = featuredImage ? makeAbsoluteUrl(featuredImage, config.baseUrl) : null;
|
|
33750
|
+
const author = config.authorEmail && config.authorName ? `${config.authorEmail} (${config.authorName})` : config.authorEmail || undefined;
|
|
33751
|
+
return buildRSSItem({
|
|
33752
|
+
title: post.title,
|
|
33753
|
+
link: postUrl,
|
|
33754
|
+
pubDate,
|
|
33755
|
+
description: post.excerpt,
|
|
33756
|
+
content: post.html,
|
|
33757
|
+
tags: post.tags,
|
|
33758
|
+
author,
|
|
33759
|
+
image: absoluteImageUrl
|
|
33760
|
+
});
|
|
33761
|
+
}).join(`
|
|
33762
|
+
`);
|
|
33763
|
+
let channelXml = ` <channel>
|
|
33764
|
+
<title><![CDATA[${config.title}]]></title>
|
|
33765
|
+
<link>${config.baseUrl}/</link>
|
|
33766
|
+
<description><![CDATA[${config.description}]]></description>`;
|
|
33767
|
+
const language = config.rssLanguage || "en-US";
|
|
33768
|
+
channelXml += `
|
|
33769
|
+
<language>${language}</language>`;
|
|
33770
|
+
if (config.authorEmail && config.authorName) {
|
|
33771
|
+
channelXml += `
|
|
33772
|
+
<managingEditor>${config.authorEmail} (${config.authorName})</managingEditor>`;
|
|
33773
|
+
} else if (config.authorEmail) {
|
|
33774
|
+
channelXml += `
|
|
33775
|
+
<managingEditor>${config.authorEmail}</managingEditor>`;
|
|
33776
|
+
}
|
|
33777
|
+
if (config.webMaster) {
|
|
33778
|
+
channelXml += `
|
|
33779
|
+
<webMaster>${config.webMaster}</webMaster>`;
|
|
33780
|
+
}
|
|
33781
|
+
if (config.copyright) {
|
|
33782
|
+
channelXml += `
|
|
33783
|
+
<copyright><![CDATA[${config.copyright}]]></copyright>`;
|
|
33784
|
+
}
|
|
33785
|
+
channelXml += `
|
|
33786
|
+
<pubDate>${formatRSSDate(latestPostDate)}</pubDate>
|
|
33787
|
+
<lastBuildDate>${lastBuildDate}</lastBuildDate>
|
|
33788
|
+
<atom:link href="${config.baseUrl}/feed.xml" rel="self" type="application/rss+xml" />`;
|
|
33789
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
33790
|
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/">
|
|
33791
|
+
${channelXml}
|
|
33792
|
+
${rssItems}
|
|
33793
|
+
</channel>
|
|
33794
|
+
</rss>`;
|
|
33795
|
+
}
|
|
33796
|
+
function generateSitemap(site, config, pageSize = 10) {
|
|
33797
|
+
const currentDate = toPacificTime(new Date).toISOString();
|
|
33798
|
+
const now = toPacificTime(new Date).getTime();
|
|
33799
|
+
let sitemapContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
33800
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
33801
|
+
`;
|
|
33802
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/`, currentDate, "daily", 1);
|
|
33803
|
+
const totalHomePages = getTotalPages(site.posts.length, pageSize);
|
|
33804
|
+
for (let page = 2;page <= totalHomePages; page++) {
|
|
33805
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/page/${page}/`, currentDate, "daily", 0.8);
|
|
33806
|
+
}
|
|
33807
|
+
for (const post of site.posts) {
|
|
33808
|
+
const postUrl = `${config.baseUrl}${post.url}`;
|
|
33809
|
+
const postDate = new Date(post.date).toISOString();
|
|
33810
|
+
const priority = calculateFreshnessPriority(post.date, 0.7, now);
|
|
33811
|
+
const age = now - new Date(post.date).getTime();
|
|
33812
|
+
const ONE_MONTH = 30 * 24 * 60 * 60 * 1000;
|
|
33813
|
+
const changefreq = age < ONE_MONTH ? "weekly" : "monthly";
|
|
33814
|
+
sitemapContent += buildSitemapUrl(postUrl, postDate, changefreq, priority);
|
|
33815
|
+
}
|
|
33816
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/tags/`, currentDate, "weekly", 0.5);
|
|
33817
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/map/`, currentDate, "weekly", 0.6);
|
|
33818
|
+
for (const [, tagData] of Object.entries(site.tags)) {
|
|
33819
|
+
const tagUrl = `${config.baseUrl}/tags/${tagData.slug}/`;
|
|
33820
|
+
const mostRecentPost = tagData.posts[0];
|
|
33821
|
+
const tagPriority = mostRecentPost ? calculateFreshnessPriority(mostRecentPost.date, 0.4, now) : 0.4;
|
|
33822
|
+
sitemapContent += buildSitemapUrl(tagUrl, currentDate, "weekly", tagPriority);
|
|
33823
|
+
const totalTagPages = getTotalPages(tagData.posts.length, pageSize);
|
|
33824
|
+
for (let page = 2;page <= totalTagPages; page++) {
|
|
33825
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/tags/${tagData.slug}/page/${page}/`, currentDate, "weekly", Math.max(0.3, tagPriority - 0.1));
|
|
33826
|
+
}
|
|
33827
|
+
}
|
|
33828
|
+
for (const [year, yearPosts] of Object.entries(site.postsByYear)) {
|
|
33829
|
+
const currentYear = new Date().getFullYear();
|
|
33830
|
+
const isCurrentYear = parseInt(year) === currentYear;
|
|
33831
|
+
const yearPriority = isCurrentYear ? 0.7 : 0.5;
|
|
33832
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/${year}/`, currentDate, isCurrentYear ? "weekly" : "monthly", yearPriority);
|
|
33833
|
+
const totalYearPages = getTotalPages(yearPosts.length, pageSize);
|
|
33834
|
+
for (let page = 2;page <= totalYearPages; page++) {
|
|
33835
|
+
sitemapContent += buildSitemapUrl(`${config.baseUrl}/${year}/page/${page}/`, currentDate, isCurrentYear ? "weekly" : "monthly", yearPriority - 0.1);
|
|
33836
|
+
}
|
|
33837
|
+
}
|
|
33838
|
+
sitemapContent += `</urlset>`;
|
|
33839
|
+
return sitemapContent;
|
|
33840
|
+
}
|
|
33841
|
+
function generateSitemapIndex(config) {
|
|
33842
|
+
const currentDate = toPacificTime(new Date).toISOString();
|
|
33843
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
33844
|
+
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
33845
|
+
<sitemap>
|
|
33846
|
+
<loc>${config.baseUrl}/sitemap.xml</loc>
|
|
33847
|
+
<lastmod>${currentDate}</lastmod>
|
|
33848
|
+
</sitemap>
|
|
33849
|
+
</sitemapindex>`;
|
|
33850
|
+
}
|
|
33851
|
+
function generateRobotsTxt(config) {
|
|
33852
|
+
return `# Robots.txt for ${config.domain}
|
|
33853
|
+
# Generated by Bunki
|
|
33854
|
+
|
|
33855
|
+
User-agent: *
|
|
33856
|
+
Allow: /
|
|
33857
|
+
|
|
33858
|
+
# Sitemaps
|
|
33859
|
+
Sitemap: ${config.baseUrl}/sitemap.xml
|
|
33860
|
+
|
|
33861
|
+
# Crawl-delay (optional, adjust as needed)
|
|
33862
|
+
# Crawl-delay: 1
|
|
33863
|
+
|
|
33864
|
+
# Disallow specific paths (uncomment as needed)
|
|
33865
|
+
# Disallow: /private/
|
|
33866
|
+
# Disallow: /admin/
|
|
33867
|
+
# Disallow: /api/
|
|
33868
|
+
`;
|
|
33869
|
+
}
|
|
33870
|
+
|
|
33871
|
+
// src/generators/pages.ts
|
|
33872
|
+
var import_nunjucks = __toESM(require_nunjucks(), 1);
|
|
33873
|
+
import path6 from "path";
|
|
33874
|
+
function getSortedTags(tags, limit) {
|
|
33875
|
+
const sorted = Object.values(tags).sort((a, b2) => b2.count - a.count);
|
|
33876
|
+
return limit ? sorted.slice(0, limit) : sorted;
|
|
33877
|
+
}
|
|
33878
|
+
async function writeHtmlFile(outputDir, relativePath, content) {
|
|
33879
|
+
const fullPath = path6.join(outputDir, relativePath);
|
|
33880
|
+
const dir = path6.dirname(fullPath);
|
|
33881
|
+
await ensureDir(dir);
|
|
33882
|
+
await Bun.write(fullPath, content);
|
|
33883
|
+
}
|
|
33884
|
+
async function generateIndexPages(site, config, outputDir, pageSize = 10) {
|
|
33885
|
+
const totalPages = getTotalPages(site.posts.length, pageSize);
|
|
33886
|
+
for (let page = 1;page <= totalPages; page++) {
|
|
33887
|
+
const paginatedPosts = getPaginatedItems(site.posts, page, pageSize);
|
|
33888
|
+
const pagination = createPagination(site.posts, page, pageSize, "/");
|
|
33889
|
+
let jsonLd = "";
|
|
33890
|
+
if (page === 1) {
|
|
33891
|
+
const schemas = generateHomePageSchemas({ site: config });
|
|
33892
|
+
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33893
|
+
`);
|
|
33894
|
+
}
|
|
33895
|
+
const pageHtml = import_nunjucks.default.render("index.njk", {
|
|
33896
|
+
site: config,
|
|
33897
|
+
posts: paginatedPosts,
|
|
33898
|
+
tags: getSortedTags(site.tags, config.maxTagsOnHomepage),
|
|
33899
|
+
pagination,
|
|
33900
|
+
jsonLd,
|
|
33901
|
+
noindex: page > 2
|
|
33902
|
+
});
|
|
33903
|
+
const outputPath = page === 1 ? "index.html" : `page/${page}/index.html`;
|
|
33904
|
+
await writeHtmlFile(outputDir, outputPath, pageHtml);
|
|
33905
|
+
}
|
|
33906
|
+
}
|
|
33907
|
+
async function generatePostPages(site, config, outputDir) {
|
|
33908
|
+
const batchSize = 10;
|
|
33909
|
+
for (let i = 0;i < site.posts.length; i += batchSize) {
|
|
33910
|
+
const batch = site.posts.slice(i, i + batchSize);
|
|
33911
|
+
await Promise.all(batch.map(async (post) => {
|
|
33912
|
+
const postPath = post.url.substring(1);
|
|
33913
|
+
const imageUrl = extractFirstImageUrl(post.html, config.baseUrl);
|
|
33914
|
+
const schemas = generatePostPageSchemas({
|
|
33915
|
+
post,
|
|
33916
|
+
site: config,
|
|
33917
|
+
imageUrl
|
|
33918
|
+
});
|
|
33919
|
+
const jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33920
|
+
`);
|
|
33921
|
+
const postHtml = import_nunjucks.default.render("post.njk", {
|
|
33922
|
+
site: config,
|
|
33923
|
+
post,
|
|
33924
|
+
jsonLd
|
|
33925
|
+
});
|
|
33926
|
+
await writeHtmlFile(outputDir, `${postPath}index.html`, postHtml);
|
|
33927
|
+
}));
|
|
33928
|
+
}
|
|
33929
|
+
}
|
|
33930
|
+
async function generateTagPages(site, config, outputDir, pageSize = 10) {
|
|
33931
|
+
const tagIndexHtml = import_nunjucks.default.render("tags.njk", {
|
|
33932
|
+
site: config,
|
|
33933
|
+
tags: getSortedTags(site.tags)
|
|
33934
|
+
});
|
|
33935
|
+
await writeHtmlFile(outputDir, "tags/index.html", tagIndexHtml);
|
|
33936
|
+
for (const [tagName, tagData] of Object.entries(site.tags)) {
|
|
33937
|
+
const totalPages = getTotalPages(tagData.posts.length, pageSize);
|
|
33938
|
+
for (let page = 1;page <= totalPages; page++) {
|
|
33939
|
+
const paginatedPosts = getPaginatedItems(tagData.posts, page, pageSize);
|
|
33940
|
+
const paginatedTagData = {
|
|
33941
|
+
...tagData,
|
|
33942
|
+
posts: paginatedPosts
|
|
33943
|
+
};
|
|
33944
|
+
const pagination = createPagination(tagData.posts, page, pageSize, `/tags/${tagData.slug}/`);
|
|
33945
|
+
let jsonLd = "";
|
|
33946
|
+
if (page === 1) {
|
|
33947
|
+
const schemas = [];
|
|
33948
|
+
const description = tagData.description || `Articles tagged with ${tagName}`;
|
|
33949
|
+
schemas.push(generateCollectionPageSchema({
|
|
33950
|
+
title: `${tagName}`,
|
|
33951
|
+
description,
|
|
33952
|
+
url: `${config.baseUrl}/tags/${tagData.slug}/`,
|
|
33953
|
+
posts: tagData.posts,
|
|
33954
|
+
site: config
|
|
33955
|
+
}));
|
|
33956
|
+
schemas.push(generateBreadcrumbListSchema({
|
|
33957
|
+
site: config,
|
|
33958
|
+
items: [
|
|
33959
|
+
{ name: "Home", url: `${config.baseUrl}/` },
|
|
33960
|
+
{
|
|
33961
|
+
name: tagName,
|
|
33962
|
+
url: `${config.baseUrl}/tags/${tagData.slug}/`
|
|
33963
|
+
}
|
|
33964
|
+
]
|
|
33965
|
+
}));
|
|
33966
|
+
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33967
|
+
`);
|
|
33615
33968
|
}
|
|
33616
|
-
|
|
33969
|
+
const tagPageHtml = import_nunjucks.default.render("tag.njk", {
|
|
33970
|
+
site: config,
|
|
33971
|
+
tag: paginatedTagData,
|
|
33972
|
+
tags: Object.values(site.tags),
|
|
33973
|
+
pagination,
|
|
33974
|
+
noindex: page > 2,
|
|
33975
|
+
jsonLd
|
|
33976
|
+
});
|
|
33977
|
+
const outputPath = page === 1 ? `tags/${tagData.slug}/index.html` : `tags/${tagData.slug}/page/${page}/index.html`;
|
|
33978
|
+
await writeHtmlFile(outputDir, outputPath, tagPageHtml);
|
|
33617
33979
|
}
|
|
33618
|
-
return postsByYear;
|
|
33619
33980
|
}
|
|
33620
|
-
|
|
33621
|
-
|
|
33622
|
-
|
|
33981
|
+
}
|
|
33982
|
+
async function generateYearArchives(site, config, outputDir, pageSize = 10) {
|
|
33983
|
+
for (const [year, yearPosts] of Object.entries(site.postsByYear)) {
|
|
33984
|
+
const totalPages = getTotalPages(yearPosts.length, pageSize);
|
|
33985
|
+
for (let page = 1;page <= totalPages; page++) {
|
|
33986
|
+
const paginatedPosts = getPaginatedItems(yearPosts, page, pageSize);
|
|
33987
|
+
const pagination = createPagination(yearPosts, page, pageSize, `/${year}/`);
|
|
33988
|
+
let jsonLd = "";
|
|
33989
|
+
if (page === 1) {
|
|
33990
|
+
const schemas = [];
|
|
33991
|
+
schemas.push(generateCollectionPageSchema({
|
|
33992
|
+
title: `Posts from ${year}`,
|
|
33993
|
+
description: `Articles published in ${year}`,
|
|
33994
|
+
url: `${config.baseUrl}/${year}/`,
|
|
33995
|
+
posts: yearPosts,
|
|
33996
|
+
site: config
|
|
33997
|
+
}));
|
|
33998
|
+
schemas.push(generateBreadcrumbListSchema({
|
|
33999
|
+
site: config,
|
|
34000
|
+
items: [
|
|
34001
|
+
{ name: "Home", url: `${config.baseUrl}/` },
|
|
34002
|
+
{ name: year, url: `${config.baseUrl}/${year}/` }
|
|
34003
|
+
]
|
|
34004
|
+
}));
|
|
34005
|
+
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
34006
|
+
`);
|
|
34007
|
+
}
|
|
34008
|
+
const yearPageHtml = import_nunjucks.default.render("archive.njk", {
|
|
34009
|
+
site: config,
|
|
34010
|
+
posts: paginatedPosts,
|
|
34011
|
+
tags: getSortedTags(site.tags, config.maxTagsOnHomepage),
|
|
34012
|
+
year,
|
|
34013
|
+
pagination,
|
|
34014
|
+
noindex: page > 2,
|
|
34015
|
+
jsonLd
|
|
34016
|
+
});
|
|
34017
|
+
const outputPath = page === 1 ? `${year}/index.html` : `${year}/page/${page}/index.html`;
|
|
34018
|
+
await writeHtmlFile(outputDir, outputPath, yearPageHtml);
|
|
34019
|
+
}
|
|
33623
34020
|
}
|
|
33624
|
-
|
|
33625
|
-
|
|
33626
|
-
|
|
34021
|
+
}
|
|
34022
|
+
async function generate404Page(config, outputDir) {
|
|
34023
|
+
try {
|
|
34024
|
+
const notFoundHtml = import_nunjucks.default.render("404.njk", {
|
|
34025
|
+
site: config
|
|
34026
|
+
});
|
|
34027
|
+
await writeHtmlFile(outputDir, "404.html", notFoundHtml);
|
|
34028
|
+
console.log("Generated 404.html");
|
|
34029
|
+
} catch (error) {
|
|
34030
|
+
if (error instanceof Error && error.message.includes("404.njk")) {
|
|
34031
|
+
console.log("No 404.njk template found, skipping 404 page generation");
|
|
34032
|
+
} else {
|
|
34033
|
+
console.warn("Error generating 404 page:", error);
|
|
34034
|
+
}
|
|
34035
|
+
}
|
|
34036
|
+
}
|
|
34037
|
+
async function generateMapPage(site, config, outputDir) {
|
|
34038
|
+
try {
|
|
34039
|
+
const mapHtml = import_nunjucks.default.render("map.njk", {
|
|
34040
|
+
site: config,
|
|
34041
|
+
posts: site.posts
|
|
34042
|
+
});
|
|
34043
|
+
await writeHtmlFile(outputDir, "map/index.html", mapHtml);
|
|
34044
|
+
console.log("Generated map page");
|
|
34045
|
+
} catch (error) {
|
|
34046
|
+
if (error instanceof Error && error.message.includes("map.njk")) {
|
|
34047
|
+
console.log("No map.njk template found, skipping map page generation");
|
|
34048
|
+
} else {
|
|
34049
|
+
console.warn("Error generating map page:", error);
|
|
34050
|
+
}
|
|
34051
|
+
}
|
|
34052
|
+
}
|
|
34053
|
+
|
|
34054
|
+
// src/generators/assets.ts
|
|
34055
|
+
var {Glob: Glob2 } = globalThis.Bun;
|
|
34056
|
+
import path7 from "path";
|
|
34057
|
+
async function generateStylesheet(config, outputDir) {
|
|
34058
|
+
const cssConfig = config.css || getDefaultCSSConfig();
|
|
34059
|
+
if (!cssConfig.enabled) {
|
|
34060
|
+
console.log("CSS processing is disabled, skipping stylesheet generation.");
|
|
34061
|
+
return;
|
|
34062
|
+
}
|
|
34063
|
+
try {
|
|
34064
|
+
await processCSS({
|
|
34065
|
+
css: cssConfig,
|
|
34066
|
+
projectRoot: process.cwd(),
|
|
34067
|
+
outputDir,
|
|
34068
|
+
verbose: true
|
|
34069
|
+
});
|
|
34070
|
+
} catch (error) {
|
|
34071
|
+
console.error("Error processing CSS:", error);
|
|
34072
|
+
console.log("Falling back to simple CSS file copying...");
|
|
34073
|
+
await fallbackCSSGeneration(cssConfig, outputDir);
|
|
34074
|
+
}
|
|
34075
|
+
}
|
|
34076
|
+
async function fallbackCSSGeneration(cssConfig, outputDir) {
|
|
34077
|
+
const cssFilePath = path7.resolve(process.cwd(), cssConfig.input);
|
|
34078
|
+
const cssFile = Bun.file(cssFilePath);
|
|
34079
|
+
if (!await cssFile.exists()) {
|
|
34080
|
+
console.warn(`CSS input file not found: ${cssFilePath}`);
|
|
34081
|
+
return;
|
|
34082
|
+
}
|
|
34083
|
+
try {
|
|
34084
|
+
const outputPath = path7.resolve(outputDir, cssConfig.output);
|
|
34085
|
+
const outputDirPath = path7.dirname(outputPath);
|
|
34086
|
+
await ensureDir(outputDirPath);
|
|
34087
|
+
await Bun.write(outputPath, cssFile);
|
|
34088
|
+
console.log("\u2705 CSS file copied successfully (fallback mode)");
|
|
34089
|
+
} catch (error) {
|
|
34090
|
+
console.error("Error in fallback CSS generation:", error);
|
|
34091
|
+
}
|
|
34092
|
+
}
|
|
34093
|
+
async function copyStaticAssets(templatesDir, outputDir) {
|
|
34094
|
+
const assetsDir = path7.join(templatesDir, "assets");
|
|
34095
|
+
const publicDir = path7.join(process.cwd(), "public");
|
|
34096
|
+
if (await isDirectory(assetsDir)) {
|
|
34097
|
+
const assetGlob = new Glob2("**/*.*");
|
|
34098
|
+
const assetsOutputDir = path7.join(outputDir, "assets");
|
|
34099
|
+
await ensureDir(assetsOutputDir);
|
|
34100
|
+
for await (const file of assetGlob.scan({
|
|
34101
|
+
cwd: assetsDir,
|
|
34102
|
+
absolute: true
|
|
34103
|
+
})) {
|
|
34104
|
+
const relativePath = path7.relative(assetsDir, file);
|
|
34105
|
+
const targetPath = path7.join(assetsOutputDir, relativePath);
|
|
34106
|
+
const targetDir = path7.dirname(targetPath);
|
|
34107
|
+
await ensureDir(targetDir);
|
|
34108
|
+
await copyFile(file, targetPath);
|
|
34109
|
+
}
|
|
34110
|
+
}
|
|
34111
|
+
if (await isDirectory(publicDir)) {
|
|
34112
|
+
const publicGlob = new Glob2("**/*");
|
|
34113
|
+
for await (const file of publicGlob.scan({
|
|
34114
|
+
cwd: publicDir,
|
|
34115
|
+
absolute: true,
|
|
34116
|
+
dot: true
|
|
34117
|
+
})) {
|
|
34118
|
+
if (await isDirectory(file))
|
|
34119
|
+
continue;
|
|
34120
|
+
const relativePath = path7.relative(publicDir, file);
|
|
34121
|
+
const destPath = path7.join(outputDir, relativePath);
|
|
34122
|
+
const targetDir = path7.dirname(destPath);
|
|
34123
|
+
await ensureDir(targetDir);
|
|
34124
|
+
await copyFile(file, destPath);
|
|
34125
|
+
}
|
|
34126
|
+
console.log("Copied public files to site (including extensionless & dotfiles)");
|
|
34127
|
+
}
|
|
34128
|
+
}
|
|
34129
|
+
|
|
34130
|
+
// src/utils/build-metrics.ts
|
|
34131
|
+
class MetricsCollector {
|
|
34132
|
+
startTime;
|
|
34133
|
+
stageTimings = new Map;
|
|
34134
|
+
currentStage = null;
|
|
34135
|
+
constructor() {
|
|
34136
|
+
this.startTime = performance.now();
|
|
34137
|
+
}
|
|
34138
|
+
startStage(name) {
|
|
34139
|
+
if (this.currentStage) {
|
|
34140
|
+
this.endStage();
|
|
34141
|
+
}
|
|
34142
|
+
this.currentStage = {
|
|
34143
|
+
name,
|
|
34144
|
+
startTime: performance.now()
|
|
34145
|
+
};
|
|
34146
|
+
}
|
|
34147
|
+
endStage() {
|
|
34148
|
+
if (!this.currentStage) {
|
|
34149
|
+
return;
|
|
34150
|
+
}
|
|
34151
|
+
const duration = performance.now() - this.currentStage.startTime;
|
|
34152
|
+
this.stageTimings.set(this.currentStage.name, duration);
|
|
34153
|
+
this.currentStage = null;
|
|
34154
|
+
}
|
|
34155
|
+
getMetrics(outputs) {
|
|
34156
|
+
if (this.currentStage) {
|
|
34157
|
+
this.endStage();
|
|
34158
|
+
}
|
|
34159
|
+
const totalTime = performance.now() - this.startTime;
|
|
33627
34160
|
return {
|
|
33628
|
-
|
|
33629
|
-
|
|
33630
|
-
|
|
33631
|
-
|
|
33632
|
-
|
|
33633
|
-
|
|
33634
|
-
|
|
33635
|
-
|
|
33636
|
-
|
|
34161
|
+
totalTime,
|
|
34162
|
+
stages: {
|
|
34163
|
+
initialization: this.stageTimings.get("initialization") || 0,
|
|
34164
|
+
cssProcessing: this.stageTimings.get("cssProcessing") || 0,
|
|
34165
|
+
pageGeneration: this.stageTimings.get("pageGeneration") || 0,
|
|
34166
|
+
feedGeneration: this.stageTimings.get("feedGeneration") || 0,
|
|
34167
|
+
assetCopying: this.stageTimings.get("assetCopying") || 0
|
|
34168
|
+
},
|
|
34169
|
+
outputs
|
|
33637
34170
|
};
|
|
33638
34171
|
}
|
|
34172
|
+
}
|
|
34173
|
+
function formatBytes(bytes) {
|
|
34174
|
+
if (bytes === 0)
|
|
34175
|
+
return "0 B";
|
|
34176
|
+
const k2 = 1024;
|
|
34177
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
34178
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k2));
|
|
34179
|
+
return `${(bytes / Math.pow(k2, i)).toFixed(2)} ${sizes[i]}`;
|
|
34180
|
+
}
|
|
34181
|
+
function displayMetrics(metrics) {
|
|
34182
|
+
console.log(`
|
|
34183
|
+
\uD83D\uDCCA Build Complete in ${metrics.totalTime.toFixed(0)}ms
|
|
34184
|
+
`);
|
|
34185
|
+
console.log("\u23F1\uFE0F Timing Breakdown:");
|
|
34186
|
+
console.log(` Initialization: ${metrics.stages.initialization.toFixed(0)}ms`);
|
|
34187
|
+
console.log(` CSS Processing: ${metrics.stages.cssProcessing.toFixed(0)}ms`);
|
|
34188
|
+
console.log(` Page Generation: ${metrics.stages.pageGeneration.toFixed(0)}ms`);
|
|
34189
|
+
console.log(` Feed Generation: ${metrics.stages.feedGeneration.toFixed(0)}ms`);
|
|
34190
|
+
console.log(` Asset Copying: ${metrics.stages.assetCopying.toFixed(0)}ms`);
|
|
34191
|
+
console.log(`
|
|
34192
|
+
\uD83D\uDCE6 Output:`);
|
|
34193
|
+
console.log(` Posts: ${metrics.outputs.posts}`);
|
|
34194
|
+
console.log(` Pages: ${metrics.outputs.pages}`);
|
|
34195
|
+
console.log(` Total: ${formatBytes(metrics.outputs.totalSize)}
|
|
34196
|
+
`);
|
|
34197
|
+
}
|
|
34198
|
+
|
|
34199
|
+
// src/site-generator.ts
|
|
34200
|
+
class SiteGenerator {
|
|
34201
|
+
options;
|
|
34202
|
+
site;
|
|
34203
|
+
metrics;
|
|
33639
34204
|
constructor(options2) {
|
|
33640
34205
|
this.options = options2;
|
|
33641
34206
|
this.site = {
|
|
@@ -33644,11 +34209,13 @@ class SiteGenerator {
|
|
|
33644
34209
|
tags: {},
|
|
33645
34210
|
postsByYear: {}
|
|
33646
34211
|
};
|
|
33647
|
-
|
|
34212
|
+
this.metrics = new MetricsCollector;
|
|
34213
|
+
const env = import_nunjucks2.default.configure(this.options.templatesDir, {
|
|
33648
34214
|
autoescape: true,
|
|
33649
|
-
watch: false
|
|
34215
|
+
watch: false,
|
|
34216
|
+
noCache: false
|
|
33650
34217
|
});
|
|
33651
|
-
env.addFilter("date",
|
|
34218
|
+
env.addFilter("date", (date, format) => {
|
|
33652
34219
|
const d2 = toPacificTime(date);
|
|
33653
34220
|
const months = [
|
|
33654
34221
|
"January",
|
|
@@ -33680,13 +34247,14 @@ class SiteGenerator {
|
|
|
33680
34247
|
});
|
|
33681
34248
|
}
|
|
33682
34249
|
async initialize() {
|
|
34250
|
+
this.metrics.startStage("initialization");
|
|
33683
34251
|
console.log("Initializing site generator...");
|
|
33684
34252
|
await ensureDir(this.options.outputDir);
|
|
33685
34253
|
if (this.options.config.noFollowExceptions) {
|
|
33686
34254
|
setNoFollowExceptions(this.options.config.noFollowExceptions);
|
|
33687
34255
|
}
|
|
33688
34256
|
let tagDescriptions = {};
|
|
33689
|
-
const tagsTomlPath =
|
|
34257
|
+
const tagsTomlPath = path8.join(process.cwd(), "src", "tags.toml");
|
|
33690
34258
|
const tagsTomlFile = Bun.file(tagsTomlPath);
|
|
33691
34259
|
if (await tagsTomlFile.exists()) {
|
|
33692
34260
|
try {
|
|
@@ -33723,574 +34291,90 @@ class SiteGenerator {
|
|
|
33723
34291
|
tags[tagName].count += 1;
|
|
33724
34292
|
tags[tagName].posts.push(post);
|
|
33725
34293
|
});
|
|
33726
|
-
});
|
|
33727
|
-
this.site = {
|
|
33728
|
-
name: this.options.config.domain,
|
|
33729
|
-
posts,
|
|
33730
|
-
tags,
|
|
33731
|
-
postsByYear: this.groupPostsByYear(posts)
|
|
33732
|
-
};
|
|
33733
|
-
}
|
|
33734
|
-
async generate() {
|
|
33735
|
-
console.log("Generating static site...");
|
|
33736
|
-
await ensureDir(this.options.outputDir);
|
|
33737
|
-
|
|
33738
|
-
await
|
|
33739
|
-
|
|
33740
|
-
|
|
33741
|
-
this.
|
|
33742
|
-
this.
|
|
33743
|
-
this.
|
|
33744
|
-
this.
|
|
33745
|
-
this.
|
|
33746
|
-
this.
|
|
33747
|
-
|
|
33748
|
-
|
|
33749
|
-
|
|
33750
|
-
|
|
33751
|
-
|
|
33752
|
-
|
|
33753
|
-
|
|
33754
|
-
|
|
33755
|
-
|
|
33756
|
-
|
|
33757
|
-
|
|
33758
|
-
|
|
33759
|
-
|
|
33760
|
-
|
|
33761
|
-
|
|
33762
|
-
} else {
|
|
33763
|
-
console.warn("Error generating 404 page:", error);
|
|
33764
|
-
}
|
|
33765
|
-
}
|
|
33766
|
-
}
|
|
33767
|
-
async generateYearArchives() {
|
|
33768
|
-
for (const [year, yearPosts] of Object.entries(this.site.postsByYear)) {
|
|
33769
|
-
const yearDir = path6.join(this.options.outputDir, year);
|
|
33770
|
-
await ensureDir(yearDir);
|
|
33771
|
-
const pageSize = 10;
|
|
33772
|
-
const totalPages = Math.ceil(yearPosts.length / pageSize);
|
|
33773
|
-
for (let page = 1;page <= totalPages; page++) {
|
|
33774
|
-
const startIndex = (page - 1) * pageSize;
|
|
33775
|
-
const endIndex = startIndex + pageSize;
|
|
33776
|
-
const paginatedPosts = yearPosts.slice(startIndex, endIndex);
|
|
33777
|
-
const pagination = this.createPagination(yearPosts, page, pageSize, `/${year}/`);
|
|
33778
|
-
let jsonLd = "";
|
|
33779
|
-
if (page === 1) {
|
|
33780
|
-
const schemas = [];
|
|
33781
|
-
schemas.push(generateCollectionPageSchema({
|
|
33782
|
-
title: `Posts from ${year}`,
|
|
33783
|
-
description: `Articles published in ${year}`,
|
|
33784
|
-
url: `${this.options.config.baseUrl}/${year}/`,
|
|
33785
|
-
posts: yearPosts,
|
|
33786
|
-
site: this.options.config
|
|
33787
|
-
}));
|
|
33788
|
-
schemas.push(generateBreadcrumbListSchema({
|
|
33789
|
-
site: this.options.config,
|
|
33790
|
-
items: [
|
|
33791
|
-
{ name: "Home", url: `${this.options.config.baseUrl}/` },
|
|
33792
|
-
{ name: year, url: `${this.options.config.baseUrl}/${year}/` }
|
|
33793
|
-
]
|
|
33794
|
-
}));
|
|
33795
|
-
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33796
|
-
`);
|
|
33797
|
-
}
|
|
33798
|
-
const yearPageHtml = import_nunjucks.default.render("archive.njk", {
|
|
33799
|
-
site: this.options.config,
|
|
33800
|
-
posts: paginatedPosts,
|
|
33801
|
-
tags: this.getSortedTags(this.options.config.maxTagsOnHomepage),
|
|
33802
|
-
year,
|
|
33803
|
-
pagination,
|
|
33804
|
-
noindex: page > 2,
|
|
33805
|
-
jsonLd
|
|
33806
|
-
});
|
|
33807
|
-
if (page === 1) {
|
|
33808
|
-
await Bun.write(path6.join(yearDir, "index.html"), yearPageHtml);
|
|
33809
|
-
} else {
|
|
33810
|
-
const pageDir = path6.join(yearDir, "page", page.toString());
|
|
33811
|
-
await ensureDir(pageDir);
|
|
33812
|
-
await Bun.write(path6.join(pageDir, "index.html"), yearPageHtml);
|
|
33813
|
-
}
|
|
33814
|
-
}
|
|
33815
|
-
}
|
|
33816
|
-
}
|
|
33817
|
-
async generateIndexPage() {
|
|
33818
|
-
const pageSize = 10;
|
|
33819
|
-
const totalPages = Math.ceil(this.site.posts.length / pageSize);
|
|
33820
|
-
for (let page = 1;page <= totalPages; page++) {
|
|
33821
|
-
const startIndex = (page - 1) * pageSize;
|
|
33822
|
-
const endIndex = startIndex + pageSize;
|
|
33823
|
-
const paginatedPosts = this.site.posts.slice(startIndex, endIndex);
|
|
33824
|
-
const pagination = this.createPagination(this.site.posts, page, pageSize, "/");
|
|
33825
|
-
let jsonLd = "";
|
|
33826
|
-
if (page === 1) {
|
|
33827
|
-
const schemas = generateHomePageSchemas({
|
|
33828
|
-
site: this.options.config
|
|
33829
|
-
});
|
|
33830
|
-
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33831
|
-
`);
|
|
33832
|
-
}
|
|
33833
|
-
const pageHtml = import_nunjucks.default.render("index.njk", {
|
|
33834
|
-
site: this.options.config,
|
|
33835
|
-
posts: paginatedPosts,
|
|
33836
|
-
tags: this.getSortedTags(this.options.config.maxTagsOnHomepage),
|
|
33837
|
-
pagination,
|
|
33838
|
-
jsonLd,
|
|
33839
|
-
noindex: page > 2
|
|
33840
|
-
});
|
|
33841
|
-
if (page === 1) {
|
|
33842
|
-
await Bun.write(path6.join(this.options.outputDir, "index.html"), pageHtml);
|
|
33843
|
-
} else {
|
|
33844
|
-
const pageDir = path6.join(this.options.outputDir, "page", page.toString());
|
|
33845
|
-
await ensureDir(pageDir);
|
|
33846
|
-
await Bun.write(path6.join(pageDir, "index.html"), pageHtml);
|
|
33847
|
-
}
|
|
33848
|
-
}
|
|
33849
|
-
}
|
|
33850
|
-
async generatePostPages() {
|
|
33851
|
-
for (const post of this.site.posts) {
|
|
33852
|
-
const postPath = post.url.substring(1);
|
|
33853
|
-
const postDir = path6.join(this.options.outputDir, postPath);
|
|
33854
|
-
await ensureDir(postDir);
|
|
33855
|
-
const imageUrl = extractFirstImageUrl(post.html, this.options.config.baseUrl);
|
|
33856
|
-
const schemas = generatePostPageSchemas({
|
|
33857
|
-
post,
|
|
33858
|
-
site: this.options.config,
|
|
33859
|
-
imageUrl
|
|
33860
|
-
});
|
|
33861
|
-
const jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33862
|
-
`);
|
|
33863
|
-
const postHtml = import_nunjucks.default.render("post.njk", {
|
|
33864
|
-
site: this.options.config,
|
|
33865
|
-
post,
|
|
33866
|
-
jsonLd
|
|
33867
|
-
});
|
|
33868
|
-
await Bun.write(path6.join(postDir, "index.html"), postHtml);
|
|
33869
|
-
}
|
|
33870
|
-
}
|
|
33871
|
-
async generateTagPages() {
|
|
33872
|
-
const tagsDir = path6.join(this.options.outputDir, "tags");
|
|
33873
|
-
await ensureDir(tagsDir);
|
|
33874
|
-
const tagIndexHtml = import_nunjucks.default.render("tags.njk", {
|
|
33875
|
-
site: this.options.config,
|
|
33876
|
-
tags: this.getSortedTags()
|
|
33877
|
-
});
|
|
33878
|
-
await Bun.write(path6.join(tagsDir, "index.html"), tagIndexHtml);
|
|
33879
|
-
for (const [tagName, tagData] of Object.entries(this.site.tags)) {
|
|
33880
|
-
const tagDir = path6.join(tagsDir, tagData.slug);
|
|
33881
|
-
await ensureDir(tagDir);
|
|
33882
|
-
const pageSize = 10;
|
|
33883
|
-
const totalPages = Math.ceil(tagData.posts.length / pageSize);
|
|
33884
|
-
for (let page = 1;page <= totalPages; page++) {
|
|
33885
|
-
const startIndex = (page - 1) * pageSize;
|
|
33886
|
-
const endIndex = startIndex + pageSize;
|
|
33887
|
-
const paginatedPosts = tagData.posts.slice(startIndex, endIndex);
|
|
33888
|
-
const paginatedTagData = {
|
|
33889
|
-
...tagData,
|
|
33890
|
-
posts: paginatedPosts
|
|
33891
|
-
};
|
|
33892
|
-
const pagination = this.createPagination(tagData.posts, page, pageSize, `/tags/${tagData.slug}/`);
|
|
33893
|
-
let jsonLd = "";
|
|
33894
|
-
if (page === 1) {
|
|
33895
|
-
const schemas = [];
|
|
33896
|
-
const description = tagData.description || `Articles tagged with ${tagName}`;
|
|
33897
|
-
schemas.push(generateCollectionPageSchema({
|
|
33898
|
-
title: `${tagName}`,
|
|
33899
|
-
description,
|
|
33900
|
-
url: `${this.options.config.baseUrl}/tags/${tagData.slug}/`,
|
|
33901
|
-
posts: tagData.posts,
|
|
33902
|
-
site: this.options.config
|
|
33903
|
-
}));
|
|
33904
|
-
schemas.push(generateBreadcrumbListSchema({
|
|
33905
|
-
site: this.options.config,
|
|
33906
|
-
items: [
|
|
33907
|
-
{ name: "Home", url: `${this.options.config.baseUrl}/` },
|
|
33908
|
-
{ name: tagName, url: `${this.options.config.baseUrl}/tags/${tagData.slug}/` }
|
|
33909
|
-
]
|
|
33910
|
-
}));
|
|
33911
|
-
jsonLd = schemas.map((schema) => toScriptTag(schema)).join(`
|
|
33912
|
-
`);
|
|
33913
|
-
}
|
|
33914
|
-
const tagPageHtml = import_nunjucks.default.render("tag.njk", {
|
|
33915
|
-
site: this.options.config,
|
|
33916
|
-
tag: paginatedTagData,
|
|
33917
|
-
tags: Object.values(this.site.tags),
|
|
33918
|
-
pagination,
|
|
33919
|
-
noindex: page > 2,
|
|
33920
|
-
jsonLd
|
|
33921
|
-
});
|
|
33922
|
-
if (page === 1) {
|
|
33923
|
-
await Bun.write(path6.join(tagDir, "index.html"), tagPageHtml);
|
|
33924
|
-
} else {
|
|
33925
|
-
const pageDir = path6.join(tagDir, "page", page.toString());
|
|
33926
|
-
await ensureDir(pageDir);
|
|
33927
|
-
await Bun.write(path6.join(pageDir, "index.html"), tagPageHtml);
|
|
33928
|
-
}
|
|
33929
|
-
}
|
|
33930
|
-
}
|
|
33931
|
-
}
|
|
33932
|
-
async generateMapPage() {
|
|
33933
|
-
try {
|
|
33934
|
-
const mapDir = path6.join(this.options.outputDir, "map");
|
|
33935
|
-
await ensureDir(mapDir);
|
|
33936
|
-
const mapHtml = import_nunjucks.default.render("map.njk", {
|
|
33937
|
-
site: this.options.config,
|
|
33938
|
-
posts: this.site.posts
|
|
33939
|
-
});
|
|
33940
|
-
await Bun.write(path6.join(mapDir, "index.html"), mapHtml);
|
|
33941
|
-
console.log("Generated map page");
|
|
33942
|
-
} catch (error) {
|
|
33943
|
-
if (error instanceof Error && error.message.includes("map.njk")) {
|
|
33944
|
-
console.log("No map.njk template found, skipping map page generation");
|
|
33945
|
-
} else {
|
|
33946
|
-
console.warn("Error generating map page:", error);
|
|
33947
|
-
}
|
|
33948
|
-
}
|
|
33949
|
-
}
|
|
33950
|
-
async generateStylesheet() {
|
|
33951
|
-
const cssConfig = this.options.config.css || getDefaultCSSConfig();
|
|
33952
|
-
if (!cssConfig.enabled) {
|
|
33953
|
-
console.log("CSS processing is disabled, skipping stylesheet generation.");
|
|
33954
|
-
return;
|
|
33955
|
-
}
|
|
33956
|
-
try {
|
|
33957
|
-
await processCSS({
|
|
33958
|
-
css: cssConfig,
|
|
33959
|
-
projectRoot: process.cwd(),
|
|
33960
|
-
outputDir: this.options.outputDir,
|
|
33961
|
-
verbose: true
|
|
33962
|
-
});
|
|
33963
|
-
} catch (error) {
|
|
33964
|
-
console.error("Error processing CSS:", error);
|
|
33965
|
-
console.log("Falling back to simple CSS file copying...");
|
|
33966
|
-
await this.fallbackCSSGeneration(cssConfig);
|
|
33967
|
-
}
|
|
33968
|
-
}
|
|
33969
|
-
async fallbackCSSGeneration(cssConfig) {
|
|
33970
|
-
const cssFilePath = path6.resolve(process.cwd(), cssConfig.input);
|
|
33971
|
-
const cssFile = Bun.file(cssFilePath);
|
|
33972
|
-
if (!await cssFile.exists()) {
|
|
33973
|
-
console.warn(`CSS input file not found: ${cssFilePath}`);
|
|
33974
|
-
return;
|
|
33975
|
-
}
|
|
33976
|
-
try {
|
|
33977
|
-
const cssContent = await cssFile.text();
|
|
33978
|
-
const outputPath = path6.resolve(this.options.outputDir, cssConfig.output);
|
|
33979
|
-
const outputDir = path6.dirname(outputPath);
|
|
33980
|
-
await ensureDir(outputDir);
|
|
33981
|
-
await Bun.write(outputPath, cssContent);
|
|
33982
|
-
console.log("\u2705 CSS file copied successfully (fallback mode)");
|
|
33983
|
-
} catch (error) {
|
|
33984
|
-
console.error("Error in fallback CSS generation:", error);
|
|
33985
|
-
}
|
|
33986
|
-
}
|
|
33987
|
-
async copyStaticAssets() {
|
|
33988
|
-
const assetsDir = path6.join(this.options.templatesDir, "assets");
|
|
33989
|
-
const publicDir = path6.join(process.cwd(), "public");
|
|
33990
|
-
async function dirExists(p) {
|
|
33991
|
-
try {
|
|
33992
|
-
const stat = await fs2.promises.stat(p);
|
|
33993
|
-
return stat.isDirectory();
|
|
33994
|
-
} catch {
|
|
33995
|
-
return false;
|
|
33996
|
-
}
|
|
33997
|
-
}
|
|
33998
|
-
const assetsDirFile = Bun.file(assetsDir);
|
|
33999
|
-
if (await assetsDirFile.exists() && await dirExists(assetsDir)) {
|
|
34000
|
-
const assetGlob = new Glob2("**/*.*");
|
|
34001
|
-
const assetsOutputDir = path6.join(this.options.outputDir, "assets");
|
|
34002
|
-
await ensureDir(assetsOutputDir);
|
|
34003
|
-
for await (const file of assetGlob.scan({
|
|
34004
|
-
cwd: assetsDir,
|
|
34005
|
-
absolute: true
|
|
34006
|
-
})) {
|
|
34007
|
-
const relativePath = path6.relative(assetsDir, file);
|
|
34008
|
-
const targetPath = path6.join(assetsOutputDir, relativePath);
|
|
34009
|
-
const targetDir = path6.dirname(targetPath);
|
|
34010
|
-
await ensureDir(targetDir);
|
|
34011
|
-
await copyFile(file, targetPath);
|
|
34012
|
-
}
|
|
34013
|
-
}
|
|
34014
|
-
if (await dirExists(publicDir)) {
|
|
34015
|
-
const copyRecursive = async (srcDir) => {
|
|
34016
|
-
const entries = await fs2.promises.readdir(srcDir, {
|
|
34017
|
-
withFileTypes: true
|
|
34018
|
-
});
|
|
34019
|
-
for (const entry of entries) {
|
|
34020
|
-
const srcPath = path6.join(srcDir, entry.name);
|
|
34021
|
-
const relativePath = path6.relative(publicDir, srcPath);
|
|
34022
|
-
const destPath = path6.join(this.options.outputDir, relativePath);
|
|
34023
|
-
if (!relativePath)
|
|
34024
|
-
continue;
|
|
34025
|
-
if (entry.isDirectory()) {
|
|
34026
|
-
await ensureDir(destPath);
|
|
34027
|
-
await copyRecursive(srcPath);
|
|
34028
|
-
} else if (entry.isFile()) {
|
|
34029
|
-
const targetFile = Bun.file(destPath);
|
|
34030
|
-
if (!await targetFile.exists()) {
|
|
34031
|
-
const targetDir = path6.dirname(destPath);
|
|
34032
|
-
await ensureDir(targetDir);
|
|
34033
|
-
await copyFile(srcPath, destPath);
|
|
34034
|
-
}
|
|
34035
|
-
}
|
|
34036
|
-
}
|
|
34037
|
-
};
|
|
34038
|
-
await copyRecursive(publicDir);
|
|
34039
|
-
console.log("Copied public files to site (including extensionless & dotfiles)");
|
|
34040
|
-
}
|
|
34041
|
-
}
|
|
34042
|
-
extractFirstImageUrl(html) {
|
|
34043
|
-
const imgRegex = /<img[^>]+src=["']([^"']+)["']/;
|
|
34044
|
-
const match = html.match(imgRegex);
|
|
34045
|
-
return match ? match[1] : null;
|
|
34046
|
-
}
|
|
34047
|
-
escapeXml(text) {
|
|
34048
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
34049
|
-
}
|
|
34050
|
-
async generateRSSFeed() {
|
|
34051
|
-
const posts = this.site.posts.slice(0, 15);
|
|
34052
|
-
const config = this.options.config;
|
|
34053
|
-
const now = toPacificTime(new Date);
|
|
34054
|
-
const latestPostDate = posts.length > 0 ? posts[0].date : now.toISOString();
|
|
34055
|
-
const lastBuildDate = this.formatRSSDate(latestPostDate);
|
|
34056
|
-
const rssItems = posts.map((post) => {
|
|
34057
|
-
const postUrl = `${config.baseUrl}${post.url}`;
|
|
34058
|
-
const pubDate = this.formatRSSDate(post.date);
|
|
34059
|
-
const featuredImage = this.extractFirstImageUrl(post.html);
|
|
34060
|
-
const categoryTags = post.tags.map((tag) => ` <category>${this.escapeXml(tag)}</category>`).join(`
|
|
34061
|
-
`);
|
|
34062
|
-
let itemXml = ` <item>
|
|
34063
|
-
<title><![CDATA[${post.title}]]></title>
|
|
34064
|
-
<link>${postUrl}</link>
|
|
34065
|
-
<guid isPermaLink="true">${postUrl}</guid>
|
|
34066
|
-
<pubDate>${pubDate}</pubDate>`;
|
|
34067
|
-
if (config.authorEmail && config.authorName) {
|
|
34068
|
-
itemXml += `
|
|
34069
|
-
<author>${config.authorEmail} (${config.authorName})</author>`;
|
|
34070
|
-
} else if (config.authorEmail) {
|
|
34071
|
-
itemXml += `
|
|
34072
|
-
<author>${config.authorEmail}</author>`;
|
|
34073
|
-
}
|
|
34074
|
-
let description = post.excerpt;
|
|
34075
|
-
if (featuredImage) {
|
|
34076
|
-
const absoluteImageUrl = featuredImage.startsWith("http") ? featuredImage : `${config.baseUrl}${featuredImage}`;
|
|
34077
|
-
description = `<img src="${this.escapeXml(absoluteImageUrl)}" alt="" style="max-width:100%; height:auto;" /><br/><br/>${post.excerpt}`;
|
|
34078
|
-
}
|
|
34079
|
-
itemXml += `
|
|
34080
|
-
<description><![CDATA[${description}]]></description>`;
|
|
34081
|
-
if (post.tags.length > 0) {
|
|
34082
|
-
itemXml += `
|
|
34083
|
-
${categoryTags}`;
|
|
34084
|
-
}
|
|
34085
|
-
itemXml += `
|
|
34086
|
-
<content:encoded><![CDATA[${post.html}]]></content:encoded>`;
|
|
34087
|
-
if (featuredImage) {
|
|
34088
|
-
const absoluteImageUrl = featuredImage.startsWith("http") ? featuredImage : `${config.baseUrl}${featuredImage}`;
|
|
34089
|
-
itemXml += `
|
|
34090
|
-
<media:thumbnail url="${this.escapeXml(absoluteImageUrl)}" />`;
|
|
34091
|
-
itemXml += `
|
|
34092
|
-
<enclosure url="${this.escapeXml(absoluteImageUrl)}" type="image/jpeg" length="0" />`;
|
|
34093
|
-
}
|
|
34094
|
-
itemXml += `
|
|
34095
|
-
</item>`;
|
|
34096
|
-
return itemXml;
|
|
34097
|
-
}).join(`
|
|
34098
|
-
`);
|
|
34099
|
-
let channelXml = ` <channel>
|
|
34100
|
-
<title><![CDATA[${config.title}]]></title>
|
|
34101
|
-
<link>${config.baseUrl}/</link>
|
|
34102
|
-
<description><![CDATA[${config.description}]]></description>`;
|
|
34103
|
-
const language = config.rssLanguage || "en-US";
|
|
34104
|
-
channelXml += `
|
|
34105
|
-
<language>${language}</language>`;
|
|
34106
|
-
if (config.authorEmail && config.authorName) {
|
|
34107
|
-
channelXml += `
|
|
34108
|
-
<managingEditor>${config.authorEmail} (${config.authorName})</managingEditor>`;
|
|
34109
|
-
} else if (config.authorEmail) {
|
|
34110
|
-
channelXml += `
|
|
34111
|
-
<managingEditor>${config.authorEmail}</managingEditor>`;
|
|
34112
|
-
}
|
|
34113
|
-
if (config.webMaster) {
|
|
34114
|
-
channelXml += `
|
|
34115
|
-
<webMaster>${config.webMaster}</webMaster>`;
|
|
34116
|
-
}
|
|
34117
|
-
if (config.copyright) {
|
|
34118
|
-
channelXml += `
|
|
34119
|
-
<copyright><![CDATA[${config.copyright}]]></copyright>`;
|
|
34120
|
-
}
|
|
34121
|
-
channelXml += `
|
|
34122
|
-
<pubDate>${this.formatRSSDate(latestPostDate)}</pubDate>
|
|
34123
|
-
<lastBuildDate>${lastBuildDate}</lastBuildDate>
|
|
34124
|
-
<atom:link href="${config.baseUrl}/feed.xml" rel="self" type="application/rss+xml" />`;
|
|
34125
|
-
const rssContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
34126
|
-
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/">
|
|
34127
|
-
${channelXml}
|
|
34128
|
-
${rssItems}
|
|
34129
|
-
</channel>
|
|
34130
|
-
</rss>`;
|
|
34131
|
-
await Bun.write(path6.join(this.options.outputDir, "feed.xml"), rssContent);
|
|
34132
|
-
}
|
|
34133
|
-
async generateSitemap() {
|
|
34134
|
-
const currentDate = toPacificTime(new Date).toISOString();
|
|
34135
|
-
const pageSize = 10;
|
|
34136
|
-
const config = this.options.config;
|
|
34137
|
-
const now = toPacificTime(new Date).getTime();
|
|
34138
|
-
const ONE_DAY = 24 * 60 * 60 * 1000;
|
|
34139
|
-
const ONE_WEEK = 7 * ONE_DAY;
|
|
34140
|
-
const ONE_MONTH = 30 * ONE_DAY;
|
|
34141
|
-
const calculatePriority = (date, basePriority) => {
|
|
34142
|
-
const postTime = new Date(date).getTime();
|
|
34143
|
-
const age = now - postTime;
|
|
34144
|
-
if (age < ONE_WEEK) {
|
|
34145
|
-
return Math.min(1, basePriority + 0.2);
|
|
34146
|
-
} else if (age < ONE_MONTH) {
|
|
34147
|
-
return Math.min(1, basePriority + 0.1);
|
|
34148
|
-
}
|
|
34149
|
-
return basePriority;
|
|
34150
|
-
};
|
|
34151
|
-
let sitemapContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
34152
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
34153
|
-
`;
|
|
34154
|
-
sitemapContent += ` <url>
|
|
34155
|
-
<loc>${config.baseUrl}/</loc>
|
|
34156
|
-
<lastmod>${currentDate}</lastmod>
|
|
34157
|
-
<changefreq>daily</changefreq>
|
|
34158
|
-
<priority>1.0</priority>
|
|
34159
|
-
</url>
|
|
34160
|
-
`;
|
|
34161
|
-
const totalHomePages = Math.ceil(this.site.posts.length / pageSize);
|
|
34162
|
-
if (totalHomePages > 1) {
|
|
34163
|
-
for (let page = 2;page <= totalHomePages; page++) {
|
|
34164
|
-
sitemapContent += ` <url>
|
|
34165
|
-
<loc>${config.baseUrl}/page/${page}/</loc>
|
|
34166
|
-
<lastmod>${currentDate}</lastmod>
|
|
34167
|
-
<changefreq>daily</changefreq>
|
|
34168
|
-
<priority>0.8</priority>
|
|
34169
|
-
</url>
|
|
34170
|
-
`;
|
|
34171
|
-
}
|
|
34172
|
-
}
|
|
34173
|
-
for (const post of this.site.posts) {
|
|
34174
|
-
const postUrl = `${config.baseUrl}${post.url}`;
|
|
34175
|
-
const postDate = new Date(post.date).toISOString();
|
|
34176
|
-
const priority = calculatePriority(post.date, 0.7);
|
|
34177
|
-
const age = now - new Date(post.date).getTime();
|
|
34178
|
-
const changefreq = age < ONE_MONTH ? "weekly" : "monthly";
|
|
34179
|
-
sitemapContent += ` <url>
|
|
34180
|
-
<loc>${postUrl}</loc>
|
|
34181
|
-
<lastmod>${postDate}</lastmod>
|
|
34182
|
-
<changefreq>${changefreq}</changefreq>
|
|
34183
|
-
<priority>${priority.toFixed(1)}</priority>
|
|
34184
|
-
</url>
|
|
34185
|
-
`;
|
|
34186
|
-
}
|
|
34187
|
-
sitemapContent += ` <url>
|
|
34188
|
-
<loc>${config.baseUrl}/tags/</loc>
|
|
34189
|
-
<lastmod>${currentDate}</lastmod>
|
|
34190
|
-
<changefreq>weekly</changefreq>
|
|
34191
|
-
<priority>0.5</priority>
|
|
34192
|
-
</url>
|
|
34193
|
-
`;
|
|
34194
|
-
sitemapContent += ` <url>
|
|
34195
|
-
<loc>${config.baseUrl}/map/</loc>
|
|
34196
|
-
<lastmod>${currentDate}</lastmod>
|
|
34197
|
-
<changefreq>weekly</changefreq>
|
|
34198
|
-
<priority>0.6</priority>
|
|
34199
|
-
</url>
|
|
34200
|
-
`;
|
|
34201
|
-
for (const [, tagData] of Object.entries(this.site.tags)) {
|
|
34202
|
-
const tagUrl = `${config.baseUrl}/tags/${tagData.slug}/`;
|
|
34203
|
-
const mostRecentPost = tagData.posts[0];
|
|
34204
|
-
const tagPriority = mostRecentPost ? calculatePriority(mostRecentPost.date, 0.4) : 0.4;
|
|
34205
|
-
sitemapContent += ` <url>
|
|
34206
|
-
<loc>${tagUrl}</loc>
|
|
34207
|
-
<lastmod>${currentDate}</lastmod>
|
|
34208
|
-
<changefreq>weekly</changefreq>
|
|
34209
|
-
<priority>${tagPriority.toFixed(1)}</priority>
|
|
34210
|
-
</url>
|
|
34211
|
-
`;
|
|
34212
|
-
const totalTagPages = Math.ceil(tagData.posts.length / pageSize);
|
|
34213
|
-
if (totalTagPages > 1) {
|
|
34214
|
-
for (let page = 2;page <= totalTagPages; page++) {
|
|
34215
|
-
sitemapContent += ` <url>
|
|
34216
|
-
<loc>${config.baseUrl}/tags/${tagData.slug}/page/${page}/</loc>
|
|
34217
|
-
<lastmod>${currentDate}</lastmod>
|
|
34218
|
-
<changefreq>weekly</changefreq>
|
|
34219
|
-
<priority>${Math.max(0.3, tagPriority - 0.1).toFixed(1)}</priority>
|
|
34220
|
-
</url>
|
|
34221
|
-
`;
|
|
34222
|
-
}
|
|
34223
|
-
}
|
|
34224
|
-
}
|
|
34225
|
-
for (const [year, yearPosts] of Object.entries(this.site.postsByYear)) {
|
|
34226
|
-
const currentYear = new Date().getFullYear();
|
|
34227
|
-
const isCurrentYear = parseInt(year) === currentYear;
|
|
34228
|
-
const yearPriority = isCurrentYear ? 0.7 : 0.5;
|
|
34229
|
-
sitemapContent += ` <url>
|
|
34230
|
-
<loc>${config.baseUrl}/${year}/</loc>
|
|
34231
|
-
<lastmod>${currentDate}</lastmod>
|
|
34232
|
-
<changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
|
|
34233
|
-
<priority>${yearPriority.toFixed(1)}</priority>
|
|
34234
|
-
</url>
|
|
34235
|
-
`;
|
|
34236
|
-
const totalYearPages = Math.ceil(yearPosts.length / pageSize);
|
|
34237
|
-
if (totalYearPages > 1) {
|
|
34238
|
-
for (let page = 2;page <= totalYearPages; page++) {
|
|
34239
|
-
sitemapContent += ` <url>
|
|
34240
|
-
<loc>${config.baseUrl}/${year}/page/${page}/</loc>
|
|
34241
|
-
<lastmod>${currentDate}</lastmod>
|
|
34242
|
-
<changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
|
|
34243
|
-
<priority>${(yearPriority - 0.1).toFixed(1)}</priority>
|
|
34244
|
-
</url>
|
|
34245
|
-
`;
|
|
34246
|
-
}
|
|
34247
|
-
}
|
|
34248
|
-
}
|
|
34249
|
-
sitemapContent += `</urlset>`;
|
|
34250
|
-
await Bun.write(path6.join(this.options.outputDir, "sitemap.xml"), sitemapContent);
|
|
34294
|
+
});
|
|
34295
|
+
this.site = {
|
|
34296
|
+
name: this.options.config.domain,
|
|
34297
|
+
posts,
|
|
34298
|
+
tags,
|
|
34299
|
+
postsByYear: this.groupPostsByYear(posts)
|
|
34300
|
+
};
|
|
34301
|
+
}
|
|
34302
|
+
async generate() {
|
|
34303
|
+
console.log("Generating static site...");
|
|
34304
|
+
await ensureDir(this.options.outputDir);
|
|
34305
|
+
this.metrics.startStage("cssProcessing");
|
|
34306
|
+
await generateStylesheet(this.options.config, this.options.outputDir);
|
|
34307
|
+
this.metrics.startStage("pageGeneration");
|
|
34308
|
+
await Promise.all([
|
|
34309
|
+
generateIndexPages(this.site, this.options.config, this.options.outputDir),
|
|
34310
|
+
generatePostPages(this.site, this.options.config, this.options.outputDir),
|
|
34311
|
+
generateTagPages(this.site, this.options.config, this.options.outputDir),
|
|
34312
|
+
generateYearArchives(this.site, this.options.config, this.options.outputDir),
|
|
34313
|
+
generateMapPage(this.site, this.options.config, this.options.outputDir),
|
|
34314
|
+
generate404Page(this.options.config, this.options.outputDir)
|
|
34315
|
+
]);
|
|
34316
|
+
this.metrics.startStage("assetCopying");
|
|
34317
|
+
await copyStaticAssets(this.options.templatesDir, this.options.outputDir);
|
|
34318
|
+
this.metrics.startStage("feedGeneration");
|
|
34319
|
+
await this.generateFeeds();
|
|
34320
|
+
const outputStats = await this.calculateOutputStats();
|
|
34321
|
+
const buildMetrics = this.metrics.getMetrics(outputStats);
|
|
34322
|
+
displayMetrics(buildMetrics);
|
|
34323
|
+
}
|
|
34324
|
+
async generateFeeds() {
|
|
34325
|
+
const pageSize = 10;
|
|
34326
|
+
const rssContent = generateRSSFeed(this.site, this.options.config);
|
|
34327
|
+
await Bun.write(path8.join(this.options.outputDir, "feed.xml"), rssContent);
|
|
34328
|
+
const sitemapContent = generateSitemap(this.site, this.options.config, pageSize);
|
|
34329
|
+
await Bun.write(path8.join(this.options.outputDir, "sitemap.xml"), sitemapContent);
|
|
34251
34330
|
console.log("Generated sitemap.xml");
|
|
34252
34331
|
const urlCount = this.site.posts.length + Object.keys(this.site.tags).length + 10;
|
|
34253
34332
|
const sitemapSize = sitemapContent.length;
|
|
34254
34333
|
if (urlCount > 1000 || sitemapSize > 40000) {
|
|
34255
|
-
|
|
34334
|
+
const sitemapIndexContent = generateSitemapIndex(this.options.config);
|
|
34335
|
+
await Bun.write(path8.join(this.options.outputDir, "sitemap_index.xml"), sitemapIndexContent);
|
|
34336
|
+
console.log("Generated sitemap_index.xml");
|
|
34256
34337
|
}
|
|
34338
|
+
const robotsTxtContent = generateRobotsTxt(this.options.config);
|
|
34339
|
+
await Bun.write(path8.join(this.options.outputDir, "robots.txt"), robotsTxtContent);
|
|
34340
|
+
console.log("Generated robots.txt");
|
|
34257
34341
|
}
|
|
34258
|
-
|
|
34259
|
-
const
|
|
34260
|
-
const
|
|
34261
|
-
|
|
34262
|
-
|
|
34263
|
-
|
|
34264
|
-
|
|
34265
|
-
|
|
34266
|
-
|
|
34267
|
-
|
|
34268
|
-
`;
|
|
34269
|
-
sitemapIndexContent += `</sitemapindex>`;
|
|
34270
|
-
await Bun.write(path6.join(this.options.outputDir, "sitemap_index.xml"), sitemapIndexContent);
|
|
34271
|
-
console.log("Generated sitemap_index.xml");
|
|
34342
|
+
groupPostsByYear(posts) {
|
|
34343
|
+
const postsByYear = {};
|
|
34344
|
+
for (const post of posts) {
|
|
34345
|
+
const year = getPacificYear(post.date).toString();
|
|
34346
|
+
if (!postsByYear[year]) {
|
|
34347
|
+
postsByYear[year] = [];
|
|
34348
|
+
}
|
|
34349
|
+
postsByYear[year].push(post);
|
|
34350
|
+
}
|
|
34351
|
+
return postsByYear;
|
|
34272
34352
|
}
|
|
34273
|
-
async
|
|
34274
|
-
const
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
|
|
34278
|
-
|
|
34279
|
-
|
|
34280
|
-
|
|
34281
|
-
|
|
34282
|
-
|
|
34283
|
-
|
|
34284
|
-
|
|
34285
|
-
|
|
34286
|
-
|
|
34287
|
-
|
|
34288
|
-
|
|
34289
|
-
|
|
34290
|
-
|
|
34291
|
-
|
|
34292
|
-
|
|
34293
|
-
|
|
34353
|
+
async calculateOutputStats() {
|
|
34354
|
+
const outputDir = this.options.outputDir;
|
|
34355
|
+
let totalSize = 0;
|
|
34356
|
+
let pageCount = 0;
|
|
34357
|
+
try {
|
|
34358
|
+
const { Glob: Glob3 } = await Promise.resolve(globalThis.Bun);
|
|
34359
|
+
const glob = new Glob3("**/*.html");
|
|
34360
|
+
for await (const filePath of glob.scan({
|
|
34361
|
+
cwd: outputDir,
|
|
34362
|
+
absolute: true
|
|
34363
|
+
})) {
|
|
34364
|
+
pageCount++;
|
|
34365
|
+
const stat = await Bun.file(filePath).stat();
|
|
34366
|
+
if (stat) {
|
|
34367
|
+
totalSize += stat.size;
|
|
34368
|
+
}
|
|
34369
|
+
}
|
|
34370
|
+
} catch (error) {
|
|
34371
|
+
console.warn("Could not calculate output stats:", error);
|
|
34372
|
+
}
|
|
34373
|
+
return {
|
|
34374
|
+
posts: this.site.posts.length,
|
|
34375
|
+
pages: pageCount,
|
|
34376
|
+
totalSize
|
|
34377
|
+
};
|
|
34294
34378
|
}
|
|
34295
34379
|
}
|
|
34296
34380
|
|
|
@@ -34303,10 +34387,10 @@ var defaultDeps2 = {
|
|
|
34303
34387
|
};
|
|
34304
34388
|
async function handleGenerateCommand(options2, deps = defaultDeps2) {
|
|
34305
34389
|
try {
|
|
34306
|
-
const configPath =
|
|
34307
|
-
const contentDir =
|
|
34308
|
-
const outputDir =
|
|
34309
|
-
const templatesDir =
|
|
34390
|
+
const configPath = path9.resolve(options2.config);
|
|
34391
|
+
const contentDir = path9.resolve(options2.content);
|
|
34392
|
+
const outputDir = path9.resolve(options2.output);
|
|
34393
|
+
const templatesDir = path9.resolve(options2.templates);
|
|
34310
34394
|
deps.logger.log("Generating site with:");
|
|
34311
34395
|
deps.logger.log(`- Config file: ${configPath}`);
|
|
34312
34396
|
deps.logger.log(`- Content directory: ${contentDir}`);
|
|
@@ -34334,11 +34418,11 @@ function registerGenerateCommand(program2) {
|
|
|
34334
34418
|
}
|
|
34335
34419
|
|
|
34336
34420
|
// src/utils/image-uploader.ts
|
|
34337
|
-
import
|
|
34421
|
+
import path11 from "path";
|
|
34338
34422
|
|
|
34339
34423
|
// src/utils/s3-uploader.ts
|
|
34340
34424
|
var {S3Client } = globalThis.Bun;
|
|
34341
|
-
import
|
|
34425
|
+
import path10 from "path";
|
|
34342
34426
|
|
|
34343
34427
|
class S3Uploader {
|
|
34344
34428
|
s3Config;
|
|
@@ -34461,8 +34545,8 @@ class S3Uploader {
|
|
|
34461
34545
|
let failedCount = 0;
|
|
34462
34546
|
const uploadTasks = imageFiles.map((imageFile) => async () => {
|
|
34463
34547
|
try {
|
|
34464
|
-
const imagePath =
|
|
34465
|
-
const filename =
|
|
34548
|
+
const imagePath = path10.join(imagesDir, imageFile);
|
|
34549
|
+
const filename = path10.basename(imagePath);
|
|
34466
34550
|
const file = Bun.file(imagePath);
|
|
34467
34551
|
const contentType = file.type;
|
|
34468
34552
|
if (process.env.BUNKI_DRY_RUN === "true") {} else {
|
|
@@ -34496,10 +34580,10 @@ function createUploader(config) {
|
|
|
34496
34580
|
}
|
|
34497
34581
|
|
|
34498
34582
|
// src/utils/image-uploader.ts
|
|
34499
|
-
var DEFAULT_IMAGES_DIR =
|
|
34583
|
+
var DEFAULT_IMAGES_DIR = path11.join(process.cwd(), "assets");
|
|
34500
34584
|
async function uploadImages(options2 = {}) {
|
|
34501
34585
|
try {
|
|
34502
|
-
const imagesDir =
|
|
34586
|
+
const imagesDir = path11.resolve(options2.images || DEFAULT_IMAGES_DIR);
|
|
34503
34587
|
if (!await fileExists(imagesDir)) {
|
|
34504
34588
|
console.log(`Creating images directory at ${imagesDir}...`);
|
|
34505
34589
|
await ensureDir(imagesDir);
|
|
@@ -34536,7 +34620,7 @@ async function uploadImages(options2 = {}) {
|
|
|
34536
34620
|
const uploader = createUploader(s3Config);
|
|
34537
34621
|
const imageUrlMap = await uploader.uploadImages(imagesDir, options2.minYear);
|
|
34538
34622
|
if (options2.outputJson) {
|
|
34539
|
-
const outputFile =
|
|
34623
|
+
const outputFile = path11.resolve(options2.outputJson);
|
|
34540
34624
|
await Bun.write(outputFile, JSON.stringify(imageUrlMap, null, 2));
|
|
34541
34625
|
console.log(`Image URL mapping saved to ${outputFile}`);
|
|
34542
34626
|
}
|
|
@@ -34582,476 +34666,438 @@ function registerImagesPushCommand(program2) {
|
|
|
34582
34666
|
}
|
|
34583
34667
|
|
|
34584
34668
|
// src/cli/commands/init.ts
|
|
34585
|
-
import
|
|
34586
|
-
var defaultDependencies = {
|
|
34587
|
-
createDefaultConfig,
|
|
34588
|
-
ensureDir,
|
|
34589
|
-
writeFile: (filePath, data) => Bun.write(filePath, data),
|
|
34590
|
-
logger: console,
|
|
34591
|
-
exit: (code) => process.exit(code)
|
|
34592
|
-
};
|
|
34593
|
-
async function handleInitCommand(options2, deps = defaultDependencies) {
|
|
34594
|
-
try {
|
|
34595
|
-
const configPath = path10.resolve(options2.config);
|
|
34596
|
-
const configCreated = await deps.createDefaultConfig(configPath);
|
|
34597
|
-
if (!configCreated) {
|
|
34598
|
-
deps.logger.log(`
|
|
34599
|
-
Skipped initialization because the config file already exists`);
|
|
34600
|
-
return;
|
|
34601
|
-
}
|
|
34602
|
-
deps.logger.log("Creating directory structure...");
|
|
34603
|
-
const baseDir = process.cwd();
|
|
34604
|
-
const contentDir = path10.join(baseDir, "content");
|
|
34605
|
-
const templatesDir = path10.join(baseDir, "templates");
|
|
34606
|
-
const stylesDir = path10.join(templatesDir, "styles");
|
|
34607
|
-
const publicDir = path10.join(baseDir, "public");
|
|
34608
|
-
await deps.ensureDir(contentDir);
|
|
34609
|
-
await deps.ensureDir(templatesDir);
|
|
34610
|
-
await deps.ensureDir(stylesDir);
|
|
34611
|
-
await deps.ensureDir(publicDir);
|
|
34612
|
-
for (const [filename, content] of Object.entries(getDefaultTemplates())) {
|
|
34613
|
-
await deps.writeFile(path10.join(templatesDir, filename), content);
|
|
34614
|
-
}
|
|
34615
|
-
await deps.writeFile(path10.join(stylesDir, "main.css"), getDefaultCss());
|
|
34616
|
-
await deps.writeFile(path10.join(contentDir, "welcome.md"), getSamplePost());
|
|
34617
|
-
deps.logger.log(`
|
|
34618
|
-
Initialization complete! Here are the next steps:`);
|
|
34619
|
-
deps.logger.log("1. Edit bunki.config.ts to configure your site");
|
|
34620
|
-
deps.logger.log("2. Add markdown files to the content directory");
|
|
34621
|
-
deps.logger.log('3. Run "bunki generate" to build your site');
|
|
34622
|
-
deps.logger.log('4. Run "bunki serve" to preview your site locally');
|
|
34623
|
-
} catch (error) {
|
|
34624
|
-
deps.logger.error("Error initializing site:", error);
|
|
34625
|
-
deps.exit(1);
|
|
34626
|
-
}
|
|
34627
|
-
}
|
|
34628
|
-
function registerInitCommand(program2, deps = defaultDependencies) {
|
|
34629
|
-
return program2.command("init").description("Initialize a new site with default structure").option("-c, --config <file>", "Path to config file", "bunki.config.ts").action(async (options2) => {
|
|
34630
|
-
await handleInitCommand(options2, deps);
|
|
34631
|
-
});
|
|
34632
|
-
}
|
|
34633
|
-
function getDefaultTemplates() {
|
|
34634
|
-
return {
|
|
34635
|
-
"base.njk": String.raw`<!DOCTYPE html>
|
|
34636
|
-
<html lang="en">
|
|
34637
|
-
<head>
|
|
34638
|
-
<meta charset="UTF-8">
|
|
34639
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
34640
|
-
<title>{% block title %}{{ site.title }}{% endblock %}</title>
|
|
34641
|
-
<meta name="description" content="{% block description %}{{ site.description }}{% endblock %}">
|
|
34642
|
-
<link rel="stylesheet" href="/css/style.css">
|
|
34643
|
-
{% block head %}{% endblock %}
|
|
34644
|
-
</head>
|
|
34645
|
-
<body>
|
|
34646
|
-
<header>
|
|
34647
|
-
<div class="container">
|
|
34648
|
-
<h1><a href="/">{{ site.title }}</a></h1>
|
|
34649
|
-
<nav>
|
|
34650
|
-
<ul>
|
|
34651
|
-
<li><a href="/">Home</a></li>
|
|
34652
|
-
<li><a href="/tags/">Tags</a></li>
|
|
34653
|
-
</ul>
|
|
34654
|
-
</nav>
|
|
34655
|
-
</div>
|
|
34656
|
-
</header>
|
|
34657
|
-
|
|
34658
|
-
<main class="container">
|
|
34659
|
-
{% block content %}{% endblock %}
|
|
34660
|
-
</main>
|
|
34661
|
-
|
|
34662
|
-
<footer>
|
|
34663
|
-
<div class="container">
|
|
34664
|
-
<p>© {{ "now" | date("YYYY") }} {{ site.title }}</p>
|
|
34665
|
-
</div>
|
|
34666
|
-
</footer>
|
|
34667
|
-
</body>
|
|
34668
|
-
</html>`,
|
|
34669
|
-
"index.njk": String.raw`{% extends "base.njk" %}
|
|
34670
|
-
|
|
34671
|
-
{% block content %}
|
|
34672
|
-
<h1>Latest Posts</h1>
|
|
34673
|
-
|
|
34674
|
-
{% if posts.length > 0 %}
|
|
34675
|
-
<div class="posts">
|
|
34676
|
-
{% for post in posts %}
|
|
34677
|
-
<article class="post-card">
|
|
34678
|
-
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
34679
|
-
<div class="post-meta">
|
|
34680
|
-
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34681
|
-
{% if post.tags.length > 0 %}
|
|
34682
|
-
<span class="tags">
|
|
34683
|
-
{% for tag in post.tags %}
|
|
34684
|
-
<a href="/tags/{{ post.tagSlugs[tag] }}/">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
34685
|
-
{% endfor %}
|
|
34686
|
-
</span>
|
|
34687
|
-
{% endif %}
|
|
34688
|
-
</div>
|
|
34689
|
-
<div class="post-excerpt">{{ post.excerpt }}</div>
|
|
34690
|
-
<a href="{{ post.url }}" class="read-more">Read more \u2192</a>
|
|
34691
|
-
</article>
|
|
34692
|
-
{% endfor %}
|
|
34693
|
-
</div>
|
|
34694
|
-
|
|
34695
|
-
{% if pagination.totalPages > 1 %}
|
|
34696
|
-
<nav class="pagination">
|
|
34697
|
-
{% if pagination.hasPrevPage %}
|
|
34698
|
-
<a href="{{ pagination.pagePath }}{% if pagination.prevPage > 1 %}page/{{ pagination.prevPage }}/{% endif %}" class="prev">\u2190 Previous</a>
|
|
34699
|
-
{% endif %}
|
|
34700
|
-
|
|
34701
|
-
{% if pagination.hasNextPage %}
|
|
34702
|
-
<a href="{{ pagination.pagePath }}page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34703
|
-
{% endif %}
|
|
34669
|
+
import path12 from "path";
|
|
34704
34670
|
|
|
34705
|
-
|
|
34706
|
-
|
|
34707
|
-
|
|
34708
|
-
|
|
34709
|
-
|
|
34671
|
+
// src/cli/commands/templates/base-njk.ts
|
|
34672
|
+
var baseNjk = String.raw`<!DOCTYPE html>
|
|
34673
|
+
<html lang="en">
|
|
34674
|
+
<head>
|
|
34675
|
+
<meta charset="UTF-8">
|
|
34676
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
34677
|
+
<title>{% block title %}{{ site.title }}{% endblock %}</title>
|
|
34678
|
+
<meta name="description" content="{% block description %}{{ site.description }}{% endblock %}">
|
|
34679
|
+
<link rel="stylesheet" href="/css/style.css">
|
|
34680
|
+
{% block head %}{% endblock %}
|
|
34681
|
+
</head>
|
|
34682
|
+
<body>
|
|
34683
|
+
<header>
|
|
34684
|
+
<div class="container">
|
|
34685
|
+
<h1><a href="/">{{ site.title }}</a></h1>
|
|
34686
|
+
<nav>
|
|
34687
|
+
<ul>
|
|
34688
|
+
<li><a href="/">Home</a></li>
|
|
34689
|
+
<li><a href="/tags/">Tags</a></li>
|
|
34690
|
+
</ul>
|
|
34691
|
+
</nav>
|
|
34692
|
+
</div>
|
|
34693
|
+
</header>
|
|
34694
|
+
|
|
34695
|
+
<main class="container">
|
|
34696
|
+
{% block content %}{% endblock %}
|
|
34697
|
+
</main>
|
|
34698
|
+
|
|
34699
|
+
<footer>
|
|
34700
|
+
<div class="container">
|
|
34701
|
+
<p>© {{ "now" | date("YYYY") }} {{ site.title }}</p>
|
|
34702
|
+
</div>
|
|
34703
|
+
</footer>
|
|
34704
|
+
</body>
|
|
34705
|
+
</html>`;
|
|
34706
|
+
|
|
34707
|
+
// src/cli/commands/templates/index-njk.ts
|
|
34708
|
+
var indexNjk = String.raw`{% extends "base.njk" %}
|
|
34709
|
+
|
|
34710
|
+
{% block content %}
|
|
34711
|
+
<h1>Latest Posts</h1>
|
|
34712
|
+
|
|
34713
|
+
{% if posts.length > 0 %}
|
|
34714
|
+
<div class="posts">
|
|
34715
|
+
{% for post in posts %}
|
|
34716
|
+
<article class="post-card">
|
|
34717
|
+
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
34718
|
+
<div class="post-meta">
|
|
34719
|
+
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34720
|
+
{% if post.tags.length > 0 %}
|
|
34721
|
+
<span class="tags">
|
|
34722
|
+
{% for tag in post.tags %}
|
|
34723
|
+
<a href="/tags/{{ post.tagSlugs[tag] }}/">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
34724
|
+
{% endfor %}
|
|
34725
|
+
</span>
|
|
34726
|
+
{% endif %}
|
|
34727
|
+
</div>
|
|
34728
|
+
<div class="post-excerpt">{{ post.excerpt }}</div>
|
|
34729
|
+
<a href="{{ post.url }}" class="read-more">Read more \u2192</a>
|
|
34730
|
+
</article>
|
|
34731
|
+
{% endfor %}
|
|
34732
|
+
</div>
|
|
34733
|
+
|
|
34734
|
+
{% if pagination.totalPages > 1 %}
|
|
34735
|
+
<nav class="pagination">
|
|
34736
|
+
{% if pagination.hasPrevPage %}
|
|
34737
|
+
<a href="{{ pagination.pagePath }}{% if pagination.prevPage > 1 %}page/{{ pagination.prevPage }}/{% endif %}" class="prev">\u2190 Previous</a>
|
|
34738
|
+
{% endif %}
|
|
34739
|
+
|
|
34740
|
+
{% if pagination.hasNextPage %}
|
|
34741
|
+
<a href="{{ pagination.pagePath }}page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34742
|
+
{% endif %}
|
|
34743
|
+
|
|
34744
|
+
<span class="page-info">Page {{ pagination.currentPage }} of {{ pagination.totalPages }}</span>
|
|
34745
|
+
</nav>
|
|
34710
34746
|
{% endif %}
|
|
34711
|
-
{%
|
|
34712
|
-
|
|
34713
|
-
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
34720
|
-
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
34724
|
-
|
|
34725
|
-
|
|
34726
|
-
|
|
34727
|
-
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
|
|
34733
|
-
|
|
34734
|
-
{
|
|
34747
|
+
{% else %}
|
|
34748
|
+
<p>No posts yet!</p>
|
|
34749
|
+
{% endif %}
|
|
34750
|
+
{% endblock %}`;
|
|
34751
|
+
|
|
34752
|
+
// src/cli/commands/templates/post-njk.ts
|
|
34753
|
+
var postNjk = String.raw`{% extends "base.njk" %}
|
|
34754
|
+
|
|
34755
|
+
{% block title %}{{ post.title }} | {{ site.title }}{% endblock %}
|
|
34756
|
+
{% block description %}{{ post.excerpt }}{% endblock %}
|
|
34757
|
+
|
|
34758
|
+
{% block content %}
|
|
34759
|
+
<article class="post">
|
|
34760
|
+
<header class="post-header">
|
|
34761
|
+
<h1>{{ post.title }}</h1>
|
|
34762
|
+
<div class="post-meta">
|
|
34763
|
+
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34764
|
+
{% if post.tags.length > 0 %}
|
|
34765
|
+
<span class="tags">
|
|
34766
|
+
{% for tag in post.tags %}
|
|
34767
|
+
<a href="/tags/{{ post.tagSlugs[tag] }}/">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
34768
|
+
{% endfor %}
|
|
34769
|
+
</span>
|
|
34770
|
+
{% endif %}
|
|
34735
34771
|
</div>
|
|
34736
|
-
</
|
|
34737
|
-
{% endblock %}`,
|
|
34738
|
-
"tag.njk": String.raw`{% extends "base.njk" %}
|
|
34739
|
-
|
|
34740
|
-
{% block title %}{{ tag.name }} | {{ site.title }}{% endblock %}
|
|
34741
|
-
{% block description %}Posts tagged with {{ tag.name }} on {{ site.title }}{% endblock %}
|
|
34742
|
-
|
|
34743
|
-
{% block content %}
|
|
34744
|
-
<h1>Posts tagged "{{ tag.name }}"</h1>
|
|
34772
|
+
</header>
|
|
34745
34773
|
|
|
34746
|
-
|
|
34747
|
-
|
|
34774
|
+
<div class="post-content">
|
|
34775
|
+
{{ post.html | safe }}
|
|
34776
|
+
</div>
|
|
34777
|
+
</article>
|
|
34778
|
+
{% endblock %}`;
|
|
34779
|
+
|
|
34780
|
+
// src/cli/commands/templates/tag-njk.ts
|
|
34781
|
+
var tagNjk = String.raw`{% extends "base.njk" %}
|
|
34782
|
+
|
|
34783
|
+
{% block title %}{{ tag.name }} | {{ site.title }}{% endblock %}
|
|
34784
|
+
{% block description %}Posts tagged with {{ tag.name }} on {{ site.title }}{% endblock %}
|
|
34785
|
+
|
|
34786
|
+
{% block content %}
|
|
34787
|
+
<h1>Posts tagged "{{ tag.name }}"</h1>
|
|
34788
|
+
|
|
34789
|
+
{% if tag.description %}
|
|
34790
|
+
<div class="tag-description">{{ tag.description }}</div>
|
|
34791
|
+
{% endif %}
|
|
34792
|
+
|
|
34793
|
+
{% if tag.posts.length > 0 %}
|
|
34794
|
+
<div class="posts">
|
|
34795
|
+
{% for post in tag.posts %}
|
|
34796
|
+
<article class="post-card">
|
|
34797
|
+
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
34798
|
+
<div class="post-meta">
|
|
34799
|
+
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34800
|
+
</div>
|
|
34801
|
+
<div class="post-excerpt">{{ post.excerpt }}</div>
|
|
34802
|
+
<a href="{{ post.url }}" class="read-more">Read more \u2192</a>
|
|
34803
|
+
</article>
|
|
34804
|
+
{% endfor %}
|
|
34805
|
+
</div>
|
|
34806
|
+
|
|
34807
|
+
{% if pagination.totalPages > 1 %}
|
|
34808
|
+
<nav class="pagination">
|
|
34809
|
+
{% if pagination.hasPrevPage %}
|
|
34810
|
+
<a href="{{ pagination.pagePath }}{% if pagination.prevPage > 1 %}page/{{ pagination.prevPage }}/{% endif %}" class="prev">\u2190 Previous</a>
|
|
34811
|
+
{% endif %}
|
|
34812
|
+
|
|
34813
|
+
{% if pagination.hasNextPage %}
|
|
34814
|
+
<a href="{{ pagination.pagePath }}page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34815
|
+
{% endif %}
|
|
34816
|
+
|
|
34817
|
+
<span class="page-info">Page {{ pagination.currentPage }} of {{ pagination.totalPages }}</span>
|
|
34818
|
+
</nav>
|
|
34748
34819
|
{% endif %}
|
|
34749
|
-
|
|
34750
|
-
|
|
34751
|
-
|
|
34752
|
-
|
|
34753
|
-
|
|
34754
|
-
|
|
34755
|
-
|
|
34756
|
-
|
|
34757
|
-
|
|
34758
|
-
|
|
34759
|
-
|
|
34760
|
-
|
|
34761
|
-
|
|
34762
|
-
|
|
34763
|
-
|
|
34764
|
-
|
|
34765
|
-
|
|
34766
|
-
|
|
34767
|
-
|
|
34768
|
-
{
|
|
34769
|
-
|
|
34770
|
-
|
|
34771
|
-
<a href="{{ pagination.pagePath }}page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34820
|
+
{% else %}
|
|
34821
|
+
<p>No posts with this tag yet!</p>
|
|
34822
|
+
{% endif %}
|
|
34823
|
+
{% endblock %}`;
|
|
34824
|
+
|
|
34825
|
+
// src/cli/commands/templates/tags-njk.ts
|
|
34826
|
+
var tagsNjk = String.raw`{% extends "base.njk" %}
|
|
34827
|
+
|
|
34828
|
+
{% block title %}Tags | {{ site.title }}{% endblock %}
|
|
34829
|
+
{% block description %}Browse all tags on {{ site.title }}{% endblock %}
|
|
34830
|
+
|
|
34831
|
+
{% block content %}
|
|
34832
|
+
<h1>All Tags</h1>
|
|
34833
|
+
|
|
34834
|
+
{% if tags.length > 0 %}
|
|
34835
|
+
<ul class="tags-list">
|
|
34836
|
+
{% for tag in tags %}
|
|
34837
|
+
<li>
|
|
34838
|
+
<a href="/tags/{{ tag.slug }}/">{{ tag.name }}</a>
|
|
34839
|
+
<span class="count">({{ tag.count }})</span>
|
|
34840
|
+
{% if tag.description %}
|
|
34841
|
+
<p class="description">{{ tag.description }}</p>
|
|
34772
34842
|
{% endif %}
|
|
34773
|
-
|
|
34774
|
-
|
|
34775
|
-
|
|
34776
|
-
|
|
34777
|
-
|
|
34778
|
-
|
|
34779
|
-
|
|
34780
|
-
|
|
34781
|
-
|
|
34782
|
-
|
|
34783
|
-
|
|
34784
|
-
|
|
34785
|
-
|
|
34786
|
-
|
|
34787
|
-
|
|
34788
|
-
|
|
34789
|
-
|
|
34790
|
-
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
|
|
34794
|
-
|
|
34795
|
-
|
|
34796
|
-
|
|
34843
|
+
</li>
|
|
34844
|
+
{% endfor %}
|
|
34845
|
+
</ul>
|
|
34846
|
+
{% else %}
|
|
34847
|
+
<p>No tags found!</p>
|
|
34848
|
+
{% endif %}
|
|
34849
|
+
{% endblock %}`;
|
|
34850
|
+
|
|
34851
|
+
// src/cli/commands/templates/archive-njk.ts
|
|
34852
|
+
var archiveNjk = String.raw`{% extends "base.njk" %}
|
|
34853
|
+
|
|
34854
|
+
{% block title %}Archive {{ year }} | {{ site.title }}{% endblock %}
|
|
34855
|
+
{% block description %}Posts from {{ year }} on {{ site.title }}{% endblock %}
|
|
34856
|
+
|
|
34857
|
+
{% block content %}
|
|
34858
|
+
<h1>Posts from {{ year }}</h1>
|
|
34859
|
+
|
|
34860
|
+
{% if posts.length > 0 %}
|
|
34861
|
+
<div class="posts">
|
|
34862
|
+
{% for post in posts %}
|
|
34863
|
+
<article class="post-card">
|
|
34864
|
+
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
34865
|
+
<div class="post-meta">
|
|
34866
|
+
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34867
|
+
{% if post.tags.length > 0 %}
|
|
34868
|
+
<span class="tags">
|
|
34869
|
+
{% for tag in post.tags %}
|
|
34870
|
+
<a href="/tags/{{ post.tagSlugs[tag] }}/">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
34871
|
+
{% endfor %}
|
|
34872
|
+
</span>
|
|
34797
34873
|
{% endif %}
|
|
34798
|
-
</
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34874
|
+
</div>
|
|
34875
|
+
<div class="post-excerpt">{{ post.excerpt }}</div>
|
|
34876
|
+
<a href="{{ post.url }}" class="read-more">Read more \u2192</a>
|
|
34877
|
+
</article>
|
|
34878
|
+
{% endfor %}
|
|
34879
|
+
</div>
|
|
34880
|
+
|
|
34881
|
+
{% if pagination.totalPages > 1 %}
|
|
34882
|
+
<nav class="pagination">
|
|
34883
|
+
{% if pagination.hasPrevPage %}
|
|
34884
|
+
<a href="/{{ year }}/{% if pagination.prevPage > 1 %}page/{{ pagination.prevPage }}/{% endif %}" class="prev">\u2190 Previous</a>
|
|
34885
|
+
{% endif %}
|
|
34886
|
+
|
|
34887
|
+
{% if pagination.hasNextPage %}
|
|
34888
|
+
<a href="/{{ year }}/page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34889
|
+
{% endif %}
|
|
34890
|
+
|
|
34891
|
+
<span class="page-info">Page {{ pagination.currentPage }} of {{ pagination.totalPages }}</span>
|
|
34892
|
+
</nav>
|
|
34803
34893
|
{% endif %}
|
|
34804
|
-
{%
|
|
34805
|
-
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
34811
|
-
|
|
34812
|
-
|
|
34813
|
-
|
|
34814
|
-
|
|
34815
|
-
|
|
34816
|
-
<article class="post-card">
|
|
34817
|
-
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
|
34818
|
-
<div class="post-meta">
|
|
34819
|
-
<time datetime="{{ post.date }}">{{ post.date | date("MMMM D, YYYY") }}</time>
|
|
34820
|
-
{% if post.tags.length > 0 %}
|
|
34821
|
-
<span class="tags">
|
|
34822
|
-
{% for tag in post.tags %}
|
|
34823
|
-
<a href="/tags/{{ post.tagSlugs[tag] }}/">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
34824
|
-
{% endfor %}
|
|
34825
|
-
</span>
|
|
34826
|
-
{% endif %}
|
|
34827
|
-
</div>
|
|
34828
|
-
<div class="post-excerpt">{{ post.excerpt }}</div>
|
|
34829
|
-
<a href="{{ post.url }}" class="read-more">Read more \u2192</a>
|
|
34830
|
-
</article>
|
|
34831
|
-
{% endfor %}
|
|
34832
|
-
</div>
|
|
34833
|
-
|
|
34834
|
-
{% if pagination.totalPages > 1 %}
|
|
34835
|
-
<nav class="pagination">
|
|
34836
|
-
{% if pagination.hasPrevPage %}
|
|
34837
|
-
<a href="/{{ year }}/{% if pagination.prevPage > 1 %}page/{{ pagination.prevPage }}/{% endif %}" class="prev">\u2190 Previous</a>
|
|
34838
|
-
{% endif %}
|
|
34839
|
-
|
|
34840
|
-
{% if pagination.hasNextPage %}
|
|
34841
|
-
<a href="/{{ year }}/page/{{ pagination.nextPage }}/" class="next">Next \u2192</a>
|
|
34842
|
-
{% endif %}
|
|
34894
|
+
{% else %}
|
|
34895
|
+
<p>No posts from {{ year }}!</p>
|
|
34896
|
+
{% endif %}
|
|
34897
|
+
{% endblock %}`;
|
|
34898
|
+
|
|
34899
|
+
// src/cli/commands/templates/default-css.ts
|
|
34900
|
+
var defaultCss = String.raw`/* Reset & base styles */
|
|
34901
|
+
* {
|
|
34902
|
+
margin: 0;
|
|
34903
|
+
padding: 0;
|
|
34904
|
+
box-sizing: border-box;
|
|
34905
|
+
}
|
|
34843
34906
|
|
|
34844
|
-
|
|
34845
|
-
|
|
34846
|
-
|
|
34847
|
-
|
|
34848
|
-
|
|
34849
|
-
|
|
34850
|
-
{% endblock %}`
|
|
34851
|
-
};
|
|
34907
|
+
body {
|
|
34908
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
|
34909
|
+
line-height: 1.6;
|
|
34910
|
+
color: #333;
|
|
34911
|
+
background-color: #f8f9fa;
|
|
34912
|
+
padding-bottom: 2rem;
|
|
34852
34913
|
}
|
|
34853
|
-
function getDefaultCss() {
|
|
34854
|
-
return String.raw`/* Reset & base styles */
|
|
34855
|
-
* {
|
|
34856
|
-
margin: 0;
|
|
34857
|
-
padding: 0;
|
|
34858
|
-
box-sizing: border-box;
|
|
34859
|
-
}
|
|
34860
34914
|
|
|
34861
|
-
|
|
34862
|
-
|
|
34863
|
-
|
|
34864
|
-
|
|
34865
|
-
background-color: #f8f9fa;
|
|
34866
|
-
padding-bottom: 2rem;
|
|
34867
|
-
}
|
|
34915
|
+
a {
|
|
34916
|
+
color: #0066cc;
|
|
34917
|
+
text-decoration: none;
|
|
34918
|
+
}
|
|
34868
34919
|
|
|
34869
|
-
|
|
34870
|
-
|
|
34871
|
-
|
|
34872
|
-
}
|
|
34920
|
+
a:hover {
|
|
34921
|
+
text-decoration: underline;
|
|
34922
|
+
}
|
|
34873
34923
|
|
|
34874
|
-
|
|
34875
|
-
|
|
34876
|
-
|
|
34924
|
+
.container {
|
|
34925
|
+
max-width: 800px;
|
|
34926
|
+
margin: 0 auto;
|
|
34927
|
+
padding: 0 1.5rem;
|
|
34928
|
+
}
|
|
34877
34929
|
|
|
34878
|
-
|
|
34879
|
-
|
|
34880
|
-
|
|
34881
|
-
|
|
34882
|
-
|
|
34930
|
+
/* Header */
|
|
34931
|
+
header {
|
|
34932
|
+
background-color: #fff;
|
|
34933
|
+
padding: 1.5rem 0;
|
|
34934
|
+
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
34935
|
+
margin-bottom: 2rem;
|
|
34936
|
+
}
|
|
34883
34937
|
|
|
34884
|
-
|
|
34885
|
-
|
|
34886
|
-
|
|
34887
|
-
|
|
34888
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
34889
|
-
margin-bottom: 2rem;
|
|
34890
|
-
}
|
|
34938
|
+
header h1 {
|
|
34939
|
+
font-size: 1.8rem;
|
|
34940
|
+
margin: 0;
|
|
34941
|
+
}
|
|
34891
34942
|
|
|
34892
|
-
|
|
34893
|
-
|
|
34894
|
-
|
|
34895
|
-
|
|
34943
|
+
header h1 a {
|
|
34944
|
+
color: #333;
|
|
34945
|
+
text-decoration: none;
|
|
34946
|
+
}
|
|
34896
34947
|
|
|
34897
|
-
|
|
34898
|
-
|
|
34899
|
-
|
|
34900
|
-
}
|
|
34948
|
+
header nav {
|
|
34949
|
+
margin-top: 0.5rem;
|
|
34950
|
+
}
|
|
34901
34951
|
|
|
34902
|
-
|
|
34903
|
-
|
|
34904
|
-
|
|
34952
|
+
header nav ul {
|
|
34953
|
+
display: flex;
|
|
34954
|
+
list-style: none;
|
|
34955
|
+
gap: 1.5rem;
|
|
34956
|
+
}
|
|
34905
34957
|
|
|
34906
|
-
|
|
34907
|
-
|
|
34908
|
-
|
|
34909
|
-
|
|
34910
|
-
|
|
34958
|
+
/* Main content */
|
|
34959
|
+
main {
|
|
34960
|
+
background-color: #fff;
|
|
34961
|
+
padding: 2rem;
|
|
34962
|
+
border-radius: 5px;
|
|
34963
|
+
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
34964
|
+
}
|
|
34911
34965
|
|
|
34912
|
-
|
|
34913
|
-
|
|
34914
|
-
|
|
34915
|
-
|
|
34916
|
-
|
|
34917
|
-
|
|
34918
|
-
}
|
|
34966
|
+
/* Posts */
|
|
34967
|
+
.posts {
|
|
34968
|
+
display: flex;
|
|
34969
|
+
flex-direction: column;
|
|
34970
|
+
gap: 2rem;
|
|
34971
|
+
}
|
|
34919
34972
|
|
|
34920
|
-
|
|
34921
|
-
|
|
34922
|
-
|
|
34923
|
-
|
|
34924
|
-
gap: 2rem;
|
|
34925
|
-
}
|
|
34973
|
+
.post-card {
|
|
34974
|
+
border-bottom: 1px solid #eee;
|
|
34975
|
+
padding-bottom: 1.5rem;
|
|
34976
|
+
}
|
|
34926
34977
|
|
|
34927
|
-
|
|
34928
|
-
|
|
34929
|
-
|
|
34930
|
-
}
|
|
34978
|
+
.post-card:last-child {
|
|
34979
|
+
border-bottom: none;
|
|
34980
|
+
}
|
|
34931
34981
|
|
|
34932
|
-
|
|
34933
|
-
|
|
34934
|
-
|
|
34982
|
+
.post-card h2 {
|
|
34983
|
+
margin-bottom: 0.5rem;
|
|
34984
|
+
}
|
|
34935
34985
|
|
|
34936
|
-
|
|
34937
|
-
|
|
34938
|
-
|
|
34986
|
+
.post-meta {
|
|
34987
|
+
font-size: 0.9rem;
|
|
34988
|
+
color: #6c757d;
|
|
34989
|
+
margin-bottom: 1rem;
|
|
34990
|
+
}
|
|
34939
34991
|
|
|
34940
|
-
|
|
34941
|
-
|
|
34942
|
-
|
|
34943
|
-
margin-bottom: 1rem;
|
|
34944
|
-
}
|
|
34992
|
+
.post-excerpt {
|
|
34993
|
+
margin-bottom: 1rem;
|
|
34994
|
+
}
|
|
34945
34995
|
|
|
34946
|
-
|
|
34947
|
-
|
|
34948
|
-
|
|
34996
|
+
.read-more {
|
|
34997
|
+
font-weight: 500;
|
|
34998
|
+
}
|
|
34949
34999
|
|
|
34950
|
-
|
|
34951
|
-
|
|
34952
|
-
|
|
35000
|
+
/* Single post */
|
|
35001
|
+
.post-header {
|
|
35002
|
+
margin-bottom: 2rem;
|
|
35003
|
+
}
|
|
34953
35004
|
|
|
34954
|
-
|
|
34955
|
-
|
|
34956
|
-
|
|
34957
|
-
}
|
|
35005
|
+
.post-content {
|
|
35006
|
+
line-height: 1.8;
|
|
35007
|
+
}
|
|
34958
35008
|
|
|
34959
|
-
|
|
34960
|
-
|
|
34961
|
-
|
|
35009
|
+
.post-content p,
|
|
35010
|
+
.post-content ul,
|
|
35011
|
+
.post-content ol,
|
|
35012
|
+
.post-content blockquote {
|
|
35013
|
+
margin-bottom: 1.5rem;
|
|
35014
|
+
}
|
|
34962
35015
|
|
|
34963
|
-
|
|
34964
|
-
|
|
34965
|
-
|
|
34966
|
-
|
|
34967
|
-
|
|
34968
|
-
|
|
35016
|
+
.post-content h2,
|
|
35017
|
+
.post-content h3,
|
|
35018
|
+
.post-content h4 {
|
|
35019
|
+
margin-top: 2rem;
|
|
35020
|
+
margin-bottom: 1rem;
|
|
35021
|
+
}
|
|
34969
35022
|
|
|
34970
|
-
|
|
34971
|
-
|
|
34972
|
-
|
|
34973
|
-
|
|
34974
|
-
|
|
34975
|
-
|
|
35023
|
+
.post-content img {
|
|
35024
|
+
max-width: 100%;
|
|
35025
|
+
height: auto;
|
|
35026
|
+
display: block;
|
|
35027
|
+
margin: 2rem auto;
|
|
35028
|
+
}
|
|
34976
35029
|
|
|
34977
|
-
|
|
34978
|
-
|
|
34979
|
-
|
|
34980
|
-
|
|
34981
|
-
|
|
34982
|
-
|
|
35030
|
+
.post-content pre {
|
|
35031
|
+
background-color: #f5f5f5;
|
|
35032
|
+
padding: 1rem;
|
|
35033
|
+
border-radius: 4px;
|
|
35034
|
+
overflow-x: auto;
|
|
35035
|
+
margin-bottom: 1.5rem;
|
|
35036
|
+
}
|
|
34983
35037
|
|
|
34984
|
-
|
|
34985
|
-
|
|
34986
|
-
|
|
34987
|
-
|
|
34988
|
-
|
|
34989
|
-
|
|
34990
|
-
|
|
35038
|
+
.post-content code {
|
|
35039
|
+
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
35040
|
+
font-size: 0.9em;
|
|
35041
|
+
background-color: #f5f5f5;
|
|
35042
|
+
padding: 0.2em 0.4em;
|
|
35043
|
+
border-radius: 3px;
|
|
35044
|
+
}
|
|
34991
35045
|
|
|
34992
|
-
|
|
34993
|
-
|
|
34994
|
-
|
|
34995
|
-
|
|
34996
|
-
padding: 0.2em 0.4em;
|
|
34997
|
-
border-radius: 3px;
|
|
34998
|
-
}
|
|
35046
|
+
.post-content pre code {
|
|
35047
|
+
padding: 0;
|
|
35048
|
+
background-color: transparent;
|
|
35049
|
+
}
|
|
34999
35050
|
|
|
35000
|
-
|
|
35001
|
-
|
|
35002
|
-
|
|
35003
|
-
|
|
35051
|
+
/* Tags */
|
|
35052
|
+
.tags a {
|
|
35053
|
+
display: inline-block;
|
|
35054
|
+
margin-left: 0.5rem;
|
|
35055
|
+
}
|
|
35004
35056
|
|
|
35005
|
-
|
|
35006
|
-
|
|
35007
|
-
|
|
35008
|
-
margin-left: 0.5rem;
|
|
35009
|
-
}
|
|
35057
|
+
.tags-list {
|
|
35058
|
+
list-style: none;
|
|
35059
|
+
}
|
|
35010
35060
|
|
|
35011
|
-
|
|
35012
|
-
|
|
35013
|
-
|
|
35061
|
+
.tags-list li {
|
|
35062
|
+
margin-bottom: 1rem;
|
|
35063
|
+
}
|
|
35014
35064
|
|
|
35015
|
-
|
|
35016
|
-
|
|
35017
|
-
|
|
35065
|
+
.tags-list .count {
|
|
35066
|
+
color: #6c757d;
|
|
35067
|
+
font-size: 0.9rem;
|
|
35068
|
+
}
|
|
35018
35069
|
|
|
35019
|
-
|
|
35020
|
-
|
|
35021
|
-
|
|
35022
|
-
|
|
35070
|
+
.tags-list .description {
|
|
35071
|
+
margin-top: 0.25rem;
|
|
35072
|
+
font-size: 0.9rem;
|
|
35073
|
+
color: #6c757d;
|
|
35074
|
+
}
|
|
35023
35075
|
|
|
35024
|
-
|
|
35025
|
-
|
|
35026
|
-
|
|
35027
|
-
|
|
35028
|
-
|
|
35076
|
+
/* Pagination */
|
|
35077
|
+
.pagination {
|
|
35078
|
+
display: flex;
|
|
35079
|
+
justify-content: space-between;
|
|
35080
|
+
align-items: center;
|
|
35081
|
+
margin-top: 2rem;
|
|
35082
|
+
padding-top: 1rem;
|
|
35083
|
+
border-top: 1px solid #eee;
|
|
35084
|
+
}
|
|
35029
35085
|
|
|
35030
|
-
|
|
35031
|
-
|
|
35032
|
-
|
|
35033
|
-
|
|
35034
|
-
align-items: center;
|
|
35035
|
-
margin-top: 2rem;
|
|
35036
|
-
padding-top: 1rem;
|
|
35037
|
-
border-top: 1px solid #eee;
|
|
35038
|
-
}
|
|
35086
|
+
.pagination .page-info {
|
|
35087
|
+
color: #6c757d;
|
|
35088
|
+
font-size: 0.9rem;
|
|
35089
|
+
}
|
|
35039
35090
|
|
|
35040
|
-
|
|
35041
|
-
|
|
35042
|
-
|
|
35043
|
-
|
|
35091
|
+
/* Footer */
|
|
35092
|
+
footer {
|
|
35093
|
+
text-align: center;
|
|
35094
|
+
padding: 2rem 0;
|
|
35095
|
+
color: #6c757d;
|
|
35096
|
+
font-size: 0.9rem;
|
|
35097
|
+
}`;
|
|
35044
35098
|
|
|
35045
|
-
|
|
35046
|
-
|
|
35047
|
-
text-align: center;
|
|
35048
|
-
padding: 2rem 0;
|
|
35049
|
-
color: #6c757d;
|
|
35050
|
-
font-size: 0.9rem;
|
|
35051
|
-
}`;
|
|
35052
|
-
}
|
|
35053
|
-
function getSamplePost() {
|
|
35054
|
-
return `---
|
|
35099
|
+
// src/cli/commands/templates/sample-post.ts
|
|
35100
|
+
var samplePost = `---
|
|
35055
35101
|
title: Welcome to Bunki
|
|
35056
35102
|
date: 2025-01-15T12:00:00Z
|
|
35057
35103
|
tags: [getting-started, bunki]
|
|
@@ -35102,10 +35148,68 @@ function hello() {
|
|
|
35102
35148
|
4. Run \`bunki generate\` to build your site
|
|
35103
35149
|
5. Run \`bunki serve\` to preview your site locally
|
|
35104
35150
|
`;
|
|
35151
|
+
|
|
35152
|
+
// src/cli/commands/templates/index.ts
|
|
35153
|
+
var nunjucks3 = {
|
|
35154
|
+
"base.njk": baseNjk,
|
|
35155
|
+
"index.njk": indexNjk,
|
|
35156
|
+
"post.njk": postNjk,
|
|
35157
|
+
"tag.njk": tagNjk,
|
|
35158
|
+
"tags.njk": tagsNjk,
|
|
35159
|
+
"archive.njk": archiveNjk
|
|
35160
|
+
};
|
|
35161
|
+
|
|
35162
|
+
// src/cli/commands/init.ts
|
|
35163
|
+
var defaultDependencies = {
|
|
35164
|
+
createDefaultConfig,
|
|
35165
|
+
ensureDir,
|
|
35166
|
+
writeFile: (filePath, data) => Bun.write(filePath, data),
|
|
35167
|
+
logger: console,
|
|
35168
|
+
exit: (code) => process.exit(code)
|
|
35169
|
+
};
|
|
35170
|
+
async function handleInitCommand(options2, deps = defaultDependencies) {
|
|
35171
|
+
try {
|
|
35172
|
+
const configPath = path12.resolve(options2.config);
|
|
35173
|
+
const configCreated = await deps.createDefaultConfig(configPath);
|
|
35174
|
+
if (!configCreated) {
|
|
35175
|
+
deps.logger.log(`
|
|
35176
|
+
Skipped initialization because the config file already exists`);
|
|
35177
|
+
return;
|
|
35178
|
+
}
|
|
35179
|
+
deps.logger.log("Creating directory structure...");
|
|
35180
|
+
const baseDir = process.cwd();
|
|
35181
|
+
const contentDir = path12.join(baseDir, "content");
|
|
35182
|
+
const templatesDir = path12.join(baseDir, "templates");
|
|
35183
|
+
const stylesDir = path12.join(templatesDir, "styles");
|
|
35184
|
+
const publicDir = path12.join(baseDir, "public");
|
|
35185
|
+
await deps.ensureDir(contentDir);
|
|
35186
|
+
await deps.ensureDir(templatesDir);
|
|
35187
|
+
await deps.ensureDir(stylesDir);
|
|
35188
|
+
await deps.ensureDir(publicDir);
|
|
35189
|
+
for (const [filename, content] of Object.entries(nunjucks3)) {
|
|
35190
|
+
await deps.writeFile(path12.join(templatesDir, filename), content);
|
|
35191
|
+
}
|
|
35192
|
+
await deps.writeFile(path12.join(stylesDir, "main.css"), defaultCss);
|
|
35193
|
+
await deps.writeFile(path12.join(contentDir, "welcome.md"), samplePost);
|
|
35194
|
+
deps.logger.log(`
|
|
35195
|
+
Initialization complete! Here are the next steps:`);
|
|
35196
|
+
deps.logger.log("1. Edit bunki.config.ts to configure your site");
|
|
35197
|
+
deps.logger.log("2. Add markdown files to the content directory");
|
|
35198
|
+
deps.logger.log('3. Run "bunki generate" to build your site');
|
|
35199
|
+
deps.logger.log('4. Run "bunki serve" to preview your site locally');
|
|
35200
|
+
} catch (error) {
|
|
35201
|
+
deps.logger.error("Error initializing site:", error);
|
|
35202
|
+
deps.exit(1);
|
|
35203
|
+
}
|
|
35204
|
+
}
|
|
35205
|
+
function registerInitCommand(program2, deps = defaultDependencies) {
|
|
35206
|
+
return program2.command("init").description("Initialize a new site with default structure").option("-c, --config <file>", "Path to config file", "bunki.config.ts").action(async (options2) => {
|
|
35207
|
+
await handleInitCommand(options2, deps);
|
|
35208
|
+
});
|
|
35105
35209
|
}
|
|
35106
35210
|
|
|
35107
35211
|
// src/cli/commands/new-post.ts
|
|
35108
|
-
import
|
|
35212
|
+
import path13 from "path";
|
|
35109
35213
|
var defaultDeps4 = {
|
|
35110
35214
|
writeFile: (filePath, data) => Bun.write(filePath, data),
|
|
35111
35215
|
now: () => new Date,
|
|
@@ -35129,7 +35233,7 @@ async function handleNewCommand(title, options2, deps = defaultDeps4) {
|
|
|
35129
35233
|
` + `# ${title}
|
|
35130
35234
|
|
|
35131
35235
|
`;
|
|
35132
|
-
const filePath =
|
|
35236
|
+
const filePath = path13.join(DEFAULT_CONTENT_DIR, `${slug}.md`);
|
|
35133
35237
|
await deps.writeFile(filePath, frontmatter);
|
|
35134
35238
|
deps.logger.log(`Created new post: ${filePath}`);
|
|
35135
35239
|
return filePath;
|
|
@@ -35146,14 +35250,14 @@ function registerNewCommand(program2) {
|
|
|
35146
35250
|
}
|
|
35147
35251
|
|
|
35148
35252
|
// src/cli/commands/serve.ts
|
|
35149
|
-
import
|
|
35253
|
+
import path15 from "path";
|
|
35150
35254
|
|
|
35151
35255
|
// src/server.ts
|
|
35152
|
-
import
|
|
35153
|
-
import
|
|
35256
|
+
import fs2 from "fs";
|
|
35257
|
+
import path14 from "path";
|
|
35154
35258
|
async function startServer(outputDir = DEFAULT_OUTPUT_DIR, port = 3000) {
|
|
35155
35259
|
try {
|
|
35156
|
-
const stats = await
|
|
35260
|
+
const stats = await fs2.promises.stat(outputDir);
|
|
35157
35261
|
if (!stats.isDirectory()) {
|
|
35158
35262
|
const msg = `Error: Output directory ${outputDir} does not exist or is not accessible.`;
|
|
35159
35263
|
console.error(msg);
|
|
@@ -35185,18 +35289,18 @@ async function startServer(outputDir = DEFAULT_OUTPUT_DIR, port = 3000) {
|
|
|
35185
35289
|
let filePath = "";
|
|
35186
35290
|
if (homePaginationMatch) {
|
|
35187
35291
|
const pageNumber = homePaginationMatch[1];
|
|
35188
|
-
filePath =
|
|
35292
|
+
filePath = path14.join(outputDir, "page", pageNumber, "index.html");
|
|
35189
35293
|
} else if (tagPaginationMatch) {
|
|
35190
35294
|
const tagSlug = tagPaginationMatch[1];
|
|
35191
35295
|
const pageNumber = tagPaginationMatch[2];
|
|
35192
|
-
filePath =
|
|
35296
|
+
filePath = path14.join(outputDir, "tags", tagSlug, "page", pageNumber, "index.html");
|
|
35193
35297
|
} else if (yearPaginationMatch) {
|
|
35194
35298
|
const year = yearPaginationMatch[1];
|
|
35195
35299
|
const pageNumber = yearPaginationMatch[2];
|
|
35196
|
-
filePath =
|
|
35300
|
+
filePath = path14.join(outputDir, year, "page", pageNumber, "index.html");
|
|
35197
35301
|
} else {
|
|
35198
|
-
const directPath =
|
|
35199
|
-
const withoutSlash =
|
|
35302
|
+
const directPath = path14.join(outputDir, pathname);
|
|
35303
|
+
const withoutSlash = path14.join(outputDir, pathname + ".html");
|
|
35200
35304
|
const withHtml = pathname.endsWith(".html") ? directPath : withoutSlash;
|
|
35201
35305
|
const bunFileDirect = Bun.file(directPath);
|
|
35202
35306
|
const bunFileHtml = Bun.file(withHtml);
|
|
@@ -35205,7 +35309,7 @@ async function startServer(outputDir = DEFAULT_OUTPUT_DIR, port = 3000) {
|
|
|
35205
35309
|
} else if (await bunFileHtml.exists()) {
|
|
35206
35310
|
filePath = withHtml;
|
|
35207
35311
|
} else {
|
|
35208
|
-
const indexPath =
|
|
35312
|
+
const indexPath = path14.join(outputDir, pathname, "index.html");
|
|
35209
35313
|
const bunFileIndex = Bun.file(indexPath);
|
|
35210
35314
|
if (await bunFileIndex.exists()) {
|
|
35211
35315
|
filePath = indexPath;
|
|
@@ -35219,7 +35323,7 @@ async function startServer(outputDir = DEFAULT_OUTPUT_DIR, port = 3000) {
|
|
|
35219
35323
|
}
|
|
35220
35324
|
}
|
|
35221
35325
|
console.log(`Serving file: ${filePath}`);
|
|
35222
|
-
const extname =
|
|
35326
|
+
const extname = path14.extname(filePath);
|
|
35223
35327
|
let contentType = "text/html";
|
|
35224
35328
|
switch (extname) {
|
|
35225
35329
|
case ".js":
|
|
@@ -35278,7 +35382,7 @@ var defaultDeps5 = {
|
|
|
35278
35382
|
};
|
|
35279
35383
|
async function handleServeCommand(options2, deps = defaultDeps5) {
|
|
35280
35384
|
try {
|
|
35281
|
-
const outputDir =
|
|
35385
|
+
const outputDir = path15.resolve(options2.output);
|
|
35282
35386
|
const port = parseInt(options2.port, 10);
|
|
35283
35387
|
await deps.startServer(outputDir, port);
|
|
35284
35388
|
} catch (error) {
|
|
@@ -35293,26 +35397,28 @@ function registerServeCommand(program2) {
|
|
|
35293
35397
|
}
|
|
35294
35398
|
|
|
35295
35399
|
// src/cli/commands/validate.ts
|
|
35400
|
+
function getErrorMessage(error) {
|
|
35401
|
+
return error instanceof Error ? error.message : String(error);
|
|
35402
|
+
}
|
|
35296
35403
|
function registerValidateCommand(program2) {
|
|
35297
|
-
program2.command("validate").description("Validate markdown files for parsing errors").option("-c, --config <path>", "Path to config file", "bunki.config.ts").action(async (options2) => {
|
|
35404
|
+
program2.command("validate").description("Validate markdown files for parsing errors").option("-c, --config <path>", "Path to config file", "bunki.config.ts").option("-d, --dir <path>", "Override content directory").action(async (options2) => {
|
|
35405
|
+
let config;
|
|
35298
35406
|
try {
|
|
35299
|
-
|
|
35300
|
-
|
|
35301
|
-
`);
|
|
35302
|
-
|
|
35303
|
-
|
|
35304
|
-
|
|
35305
|
-
|
|
35306
|
-
\u2705 All markdown files are valid!`);
|
|
35307
|
-
process.exit(0);
|
|
35308
|
-
} catch (error) {
|
|
35309
|
-
console.error(`
|
|
35310
|
-
\u274C Validation failed
|
|
35407
|
+
config = await loadConfig(options2.config);
|
|
35408
|
+
} catch (error) {
|
|
35409
|
+
console.error(`Failed to load config: ${getErrorMessage(error)}`);
|
|
35410
|
+
process.exit(1);
|
|
35411
|
+
}
|
|
35412
|
+
const contentDir = options2.dir ?? config.contentDir ?? "./content";
|
|
35413
|
+
console.log(`\uD83D\uDD0D Validating markdown files in "${contentDir}"...
|
|
35311
35414
|
`);
|
|
35312
|
-
|
|
35313
|
-
|
|
35415
|
+
try {
|
|
35416
|
+
await parseMarkdownDirectory(contentDir, true);
|
|
35417
|
+
console.log("\u2705 All markdown files are valid!");
|
|
35314
35418
|
} catch (error) {
|
|
35315
|
-
console.error(
|
|
35419
|
+
console.error(`
|
|
35420
|
+
\u274C Validation failed: ${getErrorMessage(error)}
|
|
35421
|
+
`);
|
|
35316
35422
|
process.exit(1);
|
|
35317
35423
|
}
|
|
35318
35424
|
});
|