@ox-content/vite-plugin 2.74.0 → 2.75.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/dist/index.cjs CHANGED
@@ -3040,6 +3040,314 @@ function generateI18nModule(options, root) {
3040
3040
  throw new Error("[ox-content:i18n] @ox-content/napi does not expose generateI18nModule. Please rebuild the NAPI package.");
3041
3041
  }
3042
3042
  //#endregion
3043
+ //#region src/collections-runtime.ts
3044
+ const runtime = String.raw`
3045
+ function getValue(row, field) {
3046
+ if (field in row) return row[field];
3047
+ return String(field)
3048
+ .split(".")
3049
+ .reduce((value, key) => (value == null ? undefined : value[key]), row);
3050
+ }
3051
+
3052
+ function normalizePath(value) {
3053
+ const path = String(value || "/");
3054
+ if (path === "/") return path;
3055
+ return path.startsWith("/") ? path.replace(/\/+$/, "") : "/" + path.replace(/\/+$/, "");
3056
+ }
3057
+
3058
+ function likePattern(value) {
3059
+ const escaped = String(value).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
3060
+ return new RegExp("^" + escaped.replace(/%/g, ".*").replace(/_/g, ".") + "$", "i");
3061
+ }
3062
+
3063
+ function compare(left, right) {
3064
+ if (left == null && right == null) return 0;
3065
+ if (left == null) return -1;
3066
+ if (right == null) return 1;
3067
+ if (typeof left === "number" && typeof right === "number") return left - right;
3068
+ if (left instanceof Date || right instanceof Date) {
3069
+ return new Date(left).getTime() - new Date(right).getTime();
3070
+ }
3071
+ return String(left).localeCompare(String(right), undefined, {
3072
+ numeric: true,
3073
+ sensitivity: "base",
3074
+ });
3075
+ }
3076
+
3077
+ function createPredicate(field, operator, value) {
3078
+ let op = String(operator ?? "=").toUpperCase();
3079
+ let expected = value;
3080
+ if (arguments.length === 2) {
3081
+ op = "=";
3082
+ expected = operator;
3083
+ }
3084
+
3085
+ return (row) => {
3086
+ const actual = getValue(row, field);
3087
+ switch (op) {
3088
+ case "=":
3089
+ case "==":
3090
+ return actual === expected;
3091
+ case "!=":
3092
+ case "<>":
3093
+ return actual !== expected;
3094
+ case ">":
3095
+ return compare(actual, expected) > 0;
3096
+ case ">=":
3097
+ return compare(actual, expected) >= 0;
3098
+ case "<":
3099
+ return compare(actual, expected) < 0;
3100
+ case "<=":
3101
+ return compare(actual, expected) <= 0;
3102
+ case "IN":
3103
+ return Array.isArray(expected) && expected.includes(actual);
3104
+ case "NOT IN":
3105
+ return Array.isArray(expected) && !expected.includes(actual);
3106
+ case "BETWEEN":
3107
+ return Array.isArray(expected) && expected.length >= 2
3108
+ ? compare(actual, expected[0]) >= 0 && compare(actual, expected[1]) <= 0
3109
+ : false;
3110
+ case "NOT BETWEEN":
3111
+ return Array.isArray(expected) && expected.length >= 2
3112
+ ? compare(actual, expected[0]) < 0 || compare(actual, expected[1]) > 0
3113
+ : false;
3114
+ case "IS NULL":
3115
+ return actual == null;
3116
+ case "IS NOT NULL":
3117
+ return actual != null;
3118
+ case "LIKE":
3119
+ return likePattern(expected).test(String(actual ?? ""));
3120
+ case "NOT LIKE":
3121
+ return !likePattern(expected).test(String(actual ?? ""));
3122
+ default:
3123
+ throw new Error("Unsupported collection query operator: " + op);
3124
+ }
3125
+ };
3126
+ }
3127
+
3128
+ class QueryGroup {
3129
+ constructor(rows) {
3130
+ this.rows = rows;
3131
+ this.conditions = [];
3132
+ }
3133
+
3134
+ where(field, operator, value) {
3135
+ const test =
3136
+ arguments.length === 2
3137
+ ? createPredicate(field, operator)
3138
+ : createPredicate(field, operator, value);
3139
+ this.conditions.push({ join: "and", test });
3140
+ return this;
3141
+ }
3142
+
3143
+ andWhere(factory) {
3144
+ const group = new QueryGroup(this.rows);
3145
+ factory(group);
3146
+ this.conditions.push({ join: "and", test: (row) => group.test(row) });
3147
+ return this;
3148
+ }
3149
+
3150
+ orWhere(factory) {
3151
+ const group = new QueryGroup(this.rows);
3152
+ factory(group);
3153
+ this.conditions.push({ join: "or", test: (row) => group.test(row) });
3154
+ return this;
3155
+ }
3156
+
3157
+ test(row) {
3158
+ let matched = true;
3159
+ for (const condition of this.conditions) {
3160
+ matched =
3161
+ condition.join === "or" ? matched || condition.test(row) : matched && condition.test(row);
3162
+ }
3163
+ return matched;
3164
+ }
3165
+ }
3166
+
3167
+ class CollectionQueryBuilder extends QueryGroup {
3168
+ constructor(rows) {
3169
+ super(rows);
3170
+ this.orders = [];
3171
+ this.selected = undefined;
3172
+ this.offset = 0;
3173
+ this.max = undefined;
3174
+ }
3175
+
3176
+ path(path) {
3177
+ return this.where("path", "=", normalizePath(path));
3178
+ }
3179
+
3180
+ select(...fields) {
3181
+ this.selected = fields;
3182
+ return this;
3183
+ }
3184
+
3185
+ order(field, direction = "ASC") {
3186
+ this.orders.push({ field, direction: String(direction).toUpperCase() });
3187
+ return this;
3188
+ }
3189
+
3190
+ limit(limit) {
3191
+ this.max = Math.max(0, Number(limit) || 0);
3192
+ return this;
3193
+ }
3194
+
3195
+ skip(skip) {
3196
+ this.offset = Math.max(0, Number(skip) || 0);
3197
+ return this;
3198
+ }
3199
+
3200
+ materialize() {
3201
+ let rows = this.conditions.length ? this.rows.filter((row) => this.test(row)) : this.rows;
3202
+ if (this.orders.length) {
3203
+ rows = [...rows].sort((left, right) => {
3204
+ for (const order of this.orders) {
3205
+ const result = compare(getValue(left, order.field), getValue(right, order.field));
3206
+ if (result !== 0) return order.direction === "DESC" ? -result : result;
3207
+ }
3208
+ return 0;
3209
+ });
3210
+ }
3211
+ if (this.offset || this.max !== undefined) {
3212
+ rows = rows.slice(this.offset, this.max === undefined ? undefined : this.offset + this.max);
3213
+ }
3214
+ if (!this.selected) return rows;
3215
+ return rows.map((row) => {
3216
+ const selected = {};
3217
+ for (const field of this.selected) selected[field] = getValue(row, field);
3218
+ return selected;
3219
+ });
3220
+ }
3221
+
3222
+ async all() {
3223
+ return this.materialize();
3224
+ }
3225
+
3226
+ async first() {
3227
+ return this.materialize()[0] ?? null;
3228
+ }
3229
+
3230
+ async count() {
3231
+ return this.conditions.length
3232
+ ? this.rows.filter((row) => this.test(row)).length
3233
+ : this.rows.length;
3234
+ }
3235
+ }
3236
+
3237
+ export function getCollection(name) {
3238
+ return collections[name] ? [...collections[name]] : [];
3239
+ }
3240
+
3241
+ export function queryCollection(name) {
3242
+ return new CollectionQueryBuilder(collections[name] || []);
3243
+ }
3244
+
3245
+ export const collectionNames = Object.keys(collections);
3246
+ export { CollectionQueryBuilder };
3247
+ export default { collections, collectionNames, getCollection, queryCollection };
3248
+ `;
3249
+ function generateCollectionsModule(manifest) {
3250
+ return `const collections = ${JSON.stringify(manifest.collections)};\n${runtime}`;
3251
+ }
3252
+ //#endregion
3253
+ //#region src/collections.ts
3254
+ const DEFAULT_COLLECTION_NAME = "content";
3255
+ const DEFAULT_COLLECTION_SOURCE = "**/*";
3256
+ function defineCollection(collection) {
3257
+ return collection;
3258
+ }
3259
+ function defineCollections(collections) {
3260
+ return collections;
3261
+ }
3262
+ function resolveCollectionsOptions(options) {
3263
+ if (options === false) return {
3264
+ enabled: false,
3265
+ collections: {}
3266
+ };
3267
+ const source = options === true || options === void 0 ? defaultCollections() : options;
3268
+ const collections = {};
3269
+ for (const [name, value] of Object.entries(source)) {
3270
+ const collection = normalizeCollectionOptions(value);
3271
+ collections[name] = {
3272
+ name,
3273
+ source: normalizeSourcePatterns(collection.source),
3274
+ include: [...new Set(collection.include ?? [])]
3275
+ };
3276
+ }
3277
+ return {
3278
+ enabled: true,
3279
+ collections
3280
+ };
3281
+ }
3282
+ async function buildCollectionManifest(root, options) {
3283
+ if (!options.collections.enabled) return { collections: {} };
3284
+ return parseCollectionManifest((await require_napi.importNapiModule()).buildCollectionManifest({
3285
+ srcDir: node_path.resolve(root, options.srcDir),
3286
+ extensions: [...options.extensions],
3287
+ frontmatter: options.frontmatter,
3288
+ collections: Object.values(options.collections.collections).map((collection) => ({
3289
+ name: collection.name,
3290
+ source: collection.source,
3291
+ include: collection.include
3292
+ })),
3293
+ transformOptions: createNativeTransformOptions(options)
3294
+ }));
3295
+ }
3296
+ async function generateCollectionsVirtualModule(root, options) {
3297
+ return generateCollectionsModule(await buildCollectionManifest(root, options));
3298
+ }
3299
+ function normalizeCollectionOptions(options) {
3300
+ if (typeof options === "string" || Array.isArray(options)) return { source: options };
3301
+ return options;
3302
+ }
3303
+ function normalizeSourcePatterns(source) {
3304
+ return (Array.isArray(source) ? source : [source ?? DEFAULT_COLLECTION_SOURCE]).map((value) => value || DEFAULT_COLLECTION_SOURCE);
3305
+ }
3306
+ function parseCollectionManifest(json) {
3307
+ const value = JSON.parse(json);
3308
+ if (!value || typeof value !== "object" || !("collections" in value)) throw new Error("[ox-content] Native collection manifest returned an invalid payload.");
3309
+ return value;
3310
+ }
3311
+ function createNativeTransformOptions(options) {
3312
+ return {
3313
+ gfm: options.gfm,
3314
+ footnotes: options.footnotes,
3315
+ taskLists: options.taskLists,
3316
+ tables: options.tables,
3317
+ strikethrough: options.strikethrough,
3318
+ frontmatter: options.frontmatter,
3319
+ tocMaxDepth: options.tocMaxDepth,
3320
+ codeAnnotations: options.codeAnnotations?.enabled ?? false,
3321
+ codeAnnotationMetaKey: options.codeAnnotations?.metaKey ?? "annotate",
3322
+ codeAnnotationSyntax: options.codeAnnotations?.notation ?? "attribute",
3323
+ codeAnnotationDefaultLineNumbers: options.codeAnnotations?.defaultLineNumbers ?? false,
3324
+ wikiLinks: options.wikiLinks?.enabled ? {
3325
+ enabled: true,
3326
+ baseUrl: options.wikiLinks.baseUrl
3327
+ } : void 0,
3328
+ emojiShortcodes: options.emojiShortcodes?.enabled ? {
3329
+ enabled: true,
3330
+ custom: options.emojiShortcodes.custom
3331
+ } : void 0,
3332
+ attributes: options.attrs?.enabled ? { enabled: true } : void 0,
3333
+ cjkEmphasis: options.cjkEmphasis ?? false,
3334
+ codeImports: options.codeImports?.enabled ? {
3335
+ enabled: true,
3336
+ rootDir: options.codeImports.rootDir
3337
+ } : void 0,
3338
+ editThisPage: options.editThisPage?.enabled ? {
3339
+ enabled: true,
3340
+ repoUrl: options.editThisPage.repoUrl,
3341
+ branch: options.editThisPage.branch,
3342
+ rootDir: options.editThisPage.rootDir,
3343
+ label: options.editThisPage.label
3344
+ } : void 0
3345
+ };
3346
+ }
3347
+ function defaultCollections() {
3348
+ return { [DEFAULT_COLLECTION_NAME]: { source: DEFAULT_COLLECTION_SOURCE } };
3349
+ }
3350
+ //#endregion
3043
3351
  //#region src/incremental.ts
3044
3352
  function toNativeParserOptions(options = {}) {
3045
3353
  return {
@@ -3193,6 +3501,10 @@ function createFrameworkMarkdownOptions(options) {
3193
3501
  placeholder: "Search...",
3194
3502
  hotkey: "k"
3195
3503
  },
3504
+ collections: {
3505
+ enabled: false,
3506
+ collections: {}
3507
+ },
3196
3508
  embeds: {
3197
3509
  github: options.embeds?.github ?? {},
3198
3510
  openGraph: options.embeds?.openGraph ?? {},
@@ -4560,6 +4872,7 @@ function oxContent(options = {}) {
4560
4872
  createEnvironmentPlugin(resolvedOptions),
4561
4873
  createDocsPlugin(resolvedOptions, getRoot),
4562
4874
  createSsgPlugin(resolvedOptions, getRoot, ssgDevCache),
4875
+ createCollectionsPlugin(resolvedOptions, getRoot),
4563
4876
  createSearchPlugin(resolvedOptions, getRoot)
4564
4877
  ];
4565
4878
  if (resolvedOptions.i18n) plugins.push(createI18nPlugin(resolvedOptions));
@@ -4588,12 +4901,12 @@ function createMainPlugin(resolvedOptions, setConfig) {
4588
4901
  });
4589
4902
  },
4590
4903
  resolveId(id) {
4591
- if (id.startsWith("virtual:ox-content/")) return "\0" + id;
4904
+ if (id === "virtual:ox-content/config" || id === "virtual:ox-content/runtime") return "\0" + id;
4592
4905
  if (isMarkdownFilePath(id, resolvedOptions.extensions)) return id;
4593
4906
  return null;
4594
4907
  },
4595
4908
  async load(id) {
4596
- if (id.startsWith("\0virtual:ox-content/")) return generateVirtualModule(id.slice(20), resolvedOptions);
4909
+ if (id === "\0virtual:ox-content/config" || id === "\0virtual:ox-content/runtime") return generateVirtualModule(id.slice(20), resolvedOptions);
4597
4910
  return null;
4598
4911
  },
4599
4912
  async transform(code, id) {
@@ -4615,6 +4928,37 @@ function createMainPlugin(resolvedOptions, setConfig) {
4615
4928
  }
4616
4929
  };
4617
4930
  }
4931
+ function createCollectionsPlugin(resolvedOptions, getRoot) {
4932
+ const moduleId = "\0virtual:ox-content/collections";
4933
+ let moduleCode;
4934
+ const invalidate = (devServer) => {
4935
+ moduleCode = void 0;
4936
+ const mod = devServer.moduleGraph.getModuleById(moduleId);
4937
+ if (mod) {
4938
+ devServer.moduleGraph.invalidateModule(mod);
4939
+ devServer.ws.send({ type: "full-reload" });
4940
+ }
4941
+ };
4942
+ return {
4943
+ name: "ox-content:collections",
4944
+ resolveId(id) {
4945
+ return id === "virtual:ox-content/collections" ? moduleId : null;
4946
+ },
4947
+ async load(id) {
4948
+ if (id !== moduleId) return null;
4949
+ moduleCode ??= generateCollectionsVirtualModule(getRoot(), resolvedOptions);
4950
+ return moduleCode;
4951
+ },
4952
+ configureServer(devServer) {
4953
+ if (!resolvedOptions.collections.enabled) return;
4954
+ const srcDir = path.resolve(getRoot(), resolvedOptions.srcDir);
4955
+ devServer.watcher.add(srcDir);
4956
+ devServer.watcher.on("all", (_event, file) => {
4957
+ if (file.startsWith(srcDir) && isMarkdownFilePath(file, resolvedOptions.extensions)) invalidate(devServer);
4958
+ });
4959
+ }
4960
+ };
4961
+ }
4618
4962
  function createEnvironmentPlugin(resolvedOptions) {
4619
4963
  return {
4620
4964
  name: "ox-content:environment",
@@ -4768,6 +5112,7 @@ function resolveOptions(options) {
4768
5112
  transformers: options.transformers ?? [],
4769
5113
  docs: resolveDocsOptions(options.docs),
4770
5114
  search: resolveSearchOptions(options.search),
5115
+ collections: resolveCollectionsOptions(options.collections),
4771
5116
  ogViewer: options.ogViewer ?? true,
4772
5117
  embeds: resolveBuiltinEmbedOptions(options.embeds),
4773
5118
  i18n: resolveI18nOptions(options.i18n)
@@ -5030,6 +5375,7 @@ exports.DocsTestRunError = DocsTestRunError;
5030
5375
  exports.Fragment = Fragment;
5031
5376
  exports.IncrementalMarkdownParser = IncrementalMarkdownParser;
5032
5377
  exports.IncrementalMarkdownRenderer = IncrementalMarkdownRenderer;
5378
+ exports.buildCollectionManifest = buildCollectionManifest;
5033
5379
  exports.buildSearchIndex = buildSearchIndex;
5034
5380
  exports.buildSsg = buildSsg;
5035
5381
  exports.clearRenderContext = clearRenderContext;
@@ -5046,6 +5392,8 @@ exports.createIncrementalMarkdownRenderer = createIncrementalMarkdownRenderer;
5046
5392
  exports.createMarkdownEnvironment = createMarkdownEnvironment;
5047
5393
  exports.createTheme = createTheme;
5048
5394
  exports.defaultTheme = require_vitepress.defaultTheme;
5395
+ exports.defineCollection = defineCollection;
5396
+ exports.defineCollections = defineCollections;
5049
5397
  exports.defineTheme = require_vitepress.defineTheme;
5050
5398
  exports.each = each;
5051
5399
  exports.escapeSvelteMarkup = escapeSvelteMarkup;
@@ -5058,6 +5406,7 @@ exports.fetchGitHubSource = require_github.fetchGitHubSource;
5058
5406
  exports.fetchOgpData = require_ogp.fetchOgpData;
5059
5407
  exports.fetchRepoData = require_github.fetchRepoData;
5060
5408
  exports.fromVitePressConfig = require_vitepress.fromVitePressConfig;
5409
+ exports.generateCollectionsVirtualModule = generateCollectionsVirtualModule;
5061
5410
  exports.generateFrontmatterTypes = generateFrontmatterTypes;
5062
5411
  exports.generateHydrationScript = generateHydrationScript;
5063
5412
  exports.generateMarkdown = generateMarkdown;
@@ -5098,6 +5447,7 @@ exports.renderMarkdownStream = renderMarkdownStream;
5098
5447
  exports.renderPage = renderPage;
5099
5448
  exports.renderToString = renderToString;
5100
5449
  exports.resolveBuiltinEmbedOptions = resolveBuiltinEmbedOptions;
5450
+ exports.resolveCollectionsOptions = resolveCollectionsOptions;
5101
5451
  exports.resolveDocsOptions = resolveDocsOptions;
5102
5452
  exports.resolveI18nOptions = resolveI18nOptions;
5103
5453
  exports.resolveOgImageOptions = resolveOgImageOptions;