@ox-content/vite-plugin 2.74.0 → 2.75.1

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
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk.cjs");
3
+ const require_interop = require("./interop.cjs");
3
4
  const require_napi = require("./napi.cjs");
4
5
  const require_mermaid = require("./mermaid.cjs");
5
6
  const require_tabs = require("./tabs.cjs");
@@ -117,6 +118,8 @@ function createMarkdownEnvironment(options) {
117
118
  /**
118
119
  * Syntax highlighting with Shiki via rehype.
119
120
  */
121
+ const rehypeParse$1 = require_interop.interopDefault(rehype_parse.default);
122
+ const rehypeStringify$1 = require_interop.interopDefault(rehype_stringify.default);
120
123
  const BUILTIN_LANGS = [
121
124
  "javascript",
122
125
  "typescript",
@@ -195,7 +198,7 @@ function rehypeShikiHighlight(options) {
195
198
  lang,
196
199
  theme: themeName
197
200
  });
198
- const parsed = (0, unified.unified)().use(rehype_parse.default, { fragment: true }).parse(highlighted);
201
+ const parsed = (0, unified.unified)().use(rehypeParse$1, { fragment: true }).parse(highlighted);
199
202
  if (parsed.children[0]?.type === "element") {
200
203
  const highlightedPre = parsed.children[0];
201
204
  highlightedPre.properties ??= {};
@@ -217,7 +220,7 @@ function rehypeShikiHighlight(options) {
217
220
  lang,
218
221
  theme: themeName
219
222
  });
220
- const parsed = (0, unified.unified)().use(rehype_parse.default, { fragment: true }).parse(highlighted);
223
+ const parsed = (0, unified.unified)().use(rehypeParse$1, { fragment: true }).parse(highlighted);
221
224
  if (parsed.children[0]?.type === "element") {
222
225
  const highlightedCode = parsed.children[0].children.find((child) => child.type === "element" && child.tagName === "code");
223
226
  if (highlightedCode) {
@@ -273,10 +276,10 @@ function normalizeClassName(className) {
273
276
  * Apply syntax highlighting to HTML using Shiki.
274
277
  */
275
278
  async function highlightCode(html, theme = "github-dark", langs = []) {
276
- const result = await (0, unified.unified)().use(rehype_parse.default, { fragment: true }).use(rehypeShikiHighlight, {
279
+ const result = await (0, unified.unified)().use(rehypeParse$1, { fragment: true }).use(rehypeShikiHighlight, {
277
280
  theme,
278
281
  langs
279
- }).use(rehype_stringify.default).process(html);
282
+ }).use(rehypeStringify$1).process(html);
280
283
  return String(result);
281
284
  }
282
285
  //#endregion
@@ -1667,6 +1670,8 @@ async function renderSinglePage(entry, templateFn, templateSource, options, cach
1667
1670
  * Detects <Island> components in HTML and transforms them
1668
1671
  * into hydration-ready elements with data attributes.
1669
1672
  */
1673
+ const rehypeParse = require_interop.interopDefault(rehype_parse.default);
1674
+ const rehypeStringify = require_interop.interopDefault(rehype_stringify.default);
1670
1675
  /**
1671
1676
  * Get element attribute value.
1672
1677
  */
@@ -1797,7 +1802,7 @@ function rehypeIslands(collectedIslands) {
1797
1802
  */
1798
1803
  async function transformIslands(html) {
1799
1804
  const islands = [];
1800
- const result = await (0, unified.unified)().use(rehype_parse.default, { fragment: true }).use(rehypeIslands, islands).use(rehype_stringify.default).process(html);
1805
+ const result = await (0, unified.unified)().use(rehypeParse, { fragment: true }).use(rehypeIslands, islands).use(rehypeStringify).process(html);
1801
1806
  return {
1802
1807
  html: String(result),
1803
1808
  islands
@@ -3040,6 +3045,314 @@ function generateI18nModule(options, root) {
3040
3045
  throw new Error("[ox-content:i18n] @ox-content/napi does not expose generateI18nModule. Please rebuild the NAPI package.");
3041
3046
  }
3042
3047
  //#endregion
3048
+ //#region src/collections-runtime.ts
3049
+ const runtime = String.raw`
3050
+ function getValue(row, field) {
3051
+ if (field in row) return row[field];
3052
+ return String(field)
3053
+ .split(".")
3054
+ .reduce((value, key) => (value == null ? undefined : value[key]), row);
3055
+ }
3056
+
3057
+ function normalizePath(value) {
3058
+ const path = String(value || "/");
3059
+ if (path === "/") return path;
3060
+ return path.startsWith("/") ? path.replace(/\/+$/, "") : "/" + path.replace(/\/+$/, "");
3061
+ }
3062
+
3063
+ function likePattern(value) {
3064
+ const escaped = String(value).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
3065
+ return new RegExp("^" + escaped.replace(/%/g, ".*").replace(/_/g, ".") + "$", "i");
3066
+ }
3067
+
3068
+ function compare(left, right) {
3069
+ if (left == null && right == null) return 0;
3070
+ if (left == null) return -1;
3071
+ if (right == null) return 1;
3072
+ if (typeof left === "number" && typeof right === "number") return left - right;
3073
+ if (left instanceof Date || right instanceof Date) {
3074
+ return new Date(left).getTime() - new Date(right).getTime();
3075
+ }
3076
+ return String(left).localeCompare(String(right), undefined, {
3077
+ numeric: true,
3078
+ sensitivity: "base",
3079
+ });
3080
+ }
3081
+
3082
+ function createPredicate(field, operator, value) {
3083
+ let op = String(operator ?? "=").toUpperCase();
3084
+ let expected = value;
3085
+ if (arguments.length === 2) {
3086
+ op = "=";
3087
+ expected = operator;
3088
+ }
3089
+
3090
+ return (row) => {
3091
+ const actual = getValue(row, field);
3092
+ switch (op) {
3093
+ case "=":
3094
+ case "==":
3095
+ return actual === expected;
3096
+ case "!=":
3097
+ case "<>":
3098
+ return actual !== expected;
3099
+ case ">":
3100
+ return compare(actual, expected) > 0;
3101
+ case ">=":
3102
+ return compare(actual, expected) >= 0;
3103
+ case "<":
3104
+ return compare(actual, expected) < 0;
3105
+ case "<=":
3106
+ return compare(actual, expected) <= 0;
3107
+ case "IN":
3108
+ return Array.isArray(expected) && expected.includes(actual);
3109
+ case "NOT IN":
3110
+ return Array.isArray(expected) && !expected.includes(actual);
3111
+ case "BETWEEN":
3112
+ return Array.isArray(expected) && expected.length >= 2
3113
+ ? compare(actual, expected[0]) >= 0 && compare(actual, expected[1]) <= 0
3114
+ : false;
3115
+ case "NOT BETWEEN":
3116
+ return Array.isArray(expected) && expected.length >= 2
3117
+ ? compare(actual, expected[0]) < 0 || compare(actual, expected[1]) > 0
3118
+ : false;
3119
+ case "IS NULL":
3120
+ return actual == null;
3121
+ case "IS NOT NULL":
3122
+ return actual != null;
3123
+ case "LIKE":
3124
+ return likePattern(expected).test(String(actual ?? ""));
3125
+ case "NOT LIKE":
3126
+ return !likePattern(expected).test(String(actual ?? ""));
3127
+ default:
3128
+ throw new Error("Unsupported collection query operator: " + op);
3129
+ }
3130
+ };
3131
+ }
3132
+
3133
+ class QueryGroup {
3134
+ constructor(rows) {
3135
+ this.rows = rows;
3136
+ this.conditions = [];
3137
+ }
3138
+
3139
+ where(field, operator, value) {
3140
+ const test =
3141
+ arguments.length === 2
3142
+ ? createPredicate(field, operator)
3143
+ : createPredicate(field, operator, value);
3144
+ this.conditions.push({ join: "and", test });
3145
+ return this;
3146
+ }
3147
+
3148
+ andWhere(factory) {
3149
+ const group = new QueryGroup(this.rows);
3150
+ factory(group);
3151
+ this.conditions.push({ join: "and", test: (row) => group.test(row) });
3152
+ return this;
3153
+ }
3154
+
3155
+ orWhere(factory) {
3156
+ const group = new QueryGroup(this.rows);
3157
+ factory(group);
3158
+ this.conditions.push({ join: "or", test: (row) => group.test(row) });
3159
+ return this;
3160
+ }
3161
+
3162
+ test(row) {
3163
+ let matched = true;
3164
+ for (const condition of this.conditions) {
3165
+ matched =
3166
+ condition.join === "or" ? matched || condition.test(row) : matched && condition.test(row);
3167
+ }
3168
+ return matched;
3169
+ }
3170
+ }
3171
+
3172
+ class CollectionQueryBuilder extends QueryGroup {
3173
+ constructor(rows) {
3174
+ super(rows);
3175
+ this.orders = [];
3176
+ this.selected = undefined;
3177
+ this.offset = 0;
3178
+ this.max = undefined;
3179
+ }
3180
+
3181
+ path(path) {
3182
+ return this.where("path", "=", normalizePath(path));
3183
+ }
3184
+
3185
+ select(...fields) {
3186
+ this.selected = fields;
3187
+ return this;
3188
+ }
3189
+
3190
+ order(field, direction = "ASC") {
3191
+ this.orders.push({ field, direction: String(direction).toUpperCase() });
3192
+ return this;
3193
+ }
3194
+
3195
+ limit(limit) {
3196
+ this.max = Math.max(0, Number(limit) || 0);
3197
+ return this;
3198
+ }
3199
+
3200
+ skip(skip) {
3201
+ this.offset = Math.max(0, Number(skip) || 0);
3202
+ return this;
3203
+ }
3204
+
3205
+ materialize() {
3206
+ let rows = this.conditions.length ? this.rows.filter((row) => this.test(row)) : this.rows;
3207
+ if (this.orders.length) {
3208
+ rows = [...rows].sort((left, right) => {
3209
+ for (const order of this.orders) {
3210
+ const result = compare(getValue(left, order.field), getValue(right, order.field));
3211
+ if (result !== 0) return order.direction === "DESC" ? -result : result;
3212
+ }
3213
+ return 0;
3214
+ });
3215
+ }
3216
+ if (this.offset || this.max !== undefined) {
3217
+ rows = rows.slice(this.offset, this.max === undefined ? undefined : this.offset + this.max);
3218
+ }
3219
+ if (!this.selected) return rows;
3220
+ return rows.map((row) => {
3221
+ const selected = {};
3222
+ for (const field of this.selected) selected[field] = getValue(row, field);
3223
+ return selected;
3224
+ });
3225
+ }
3226
+
3227
+ async all() {
3228
+ return this.materialize();
3229
+ }
3230
+
3231
+ async first() {
3232
+ return this.materialize()[0] ?? null;
3233
+ }
3234
+
3235
+ async count() {
3236
+ return this.conditions.length
3237
+ ? this.rows.filter((row) => this.test(row)).length
3238
+ : this.rows.length;
3239
+ }
3240
+ }
3241
+
3242
+ export function getCollection(name) {
3243
+ return collections[name] ? [...collections[name]] : [];
3244
+ }
3245
+
3246
+ export function queryCollection(name) {
3247
+ return new CollectionQueryBuilder(collections[name] || []);
3248
+ }
3249
+
3250
+ export const collectionNames = Object.keys(collections);
3251
+ export { CollectionQueryBuilder };
3252
+ export default { collections, collectionNames, getCollection, queryCollection };
3253
+ `;
3254
+ function generateCollectionsModule(manifest) {
3255
+ return `const collections = ${JSON.stringify(manifest.collections)};\n${runtime}`;
3256
+ }
3257
+ //#endregion
3258
+ //#region src/collections.ts
3259
+ const DEFAULT_COLLECTION_NAME = "content";
3260
+ const DEFAULT_COLLECTION_SOURCE = "**/*";
3261
+ function defineCollection(collection) {
3262
+ return collection;
3263
+ }
3264
+ function defineCollections(collections) {
3265
+ return collections;
3266
+ }
3267
+ function resolveCollectionsOptions(options) {
3268
+ if (options === false) return {
3269
+ enabled: false,
3270
+ collections: {}
3271
+ };
3272
+ const source = options === true || options === void 0 ? defaultCollections() : options;
3273
+ const collections = {};
3274
+ for (const [name, value] of Object.entries(source)) {
3275
+ const collection = normalizeCollectionOptions(value);
3276
+ collections[name] = {
3277
+ name,
3278
+ source: normalizeSourcePatterns(collection.source),
3279
+ include: [...new Set(collection.include ?? [])]
3280
+ };
3281
+ }
3282
+ return {
3283
+ enabled: true,
3284
+ collections
3285
+ };
3286
+ }
3287
+ async function buildCollectionManifest(root, options) {
3288
+ if (!options.collections.enabled) return { collections: {} };
3289
+ return parseCollectionManifest((await require_napi.importNapiModule()).buildCollectionManifest({
3290
+ srcDir: node_path.resolve(root, options.srcDir),
3291
+ extensions: [...options.extensions],
3292
+ frontmatter: options.frontmatter,
3293
+ collections: Object.values(options.collections.collections).map((collection) => ({
3294
+ name: collection.name,
3295
+ source: collection.source,
3296
+ include: collection.include
3297
+ })),
3298
+ transformOptions: createNativeTransformOptions(options)
3299
+ }));
3300
+ }
3301
+ async function generateCollectionsVirtualModule(root, options) {
3302
+ return generateCollectionsModule(await buildCollectionManifest(root, options));
3303
+ }
3304
+ function normalizeCollectionOptions(options) {
3305
+ if (typeof options === "string" || Array.isArray(options)) return { source: options };
3306
+ return options;
3307
+ }
3308
+ function normalizeSourcePatterns(source) {
3309
+ return (Array.isArray(source) ? source : [source ?? DEFAULT_COLLECTION_SOURCE]).map((value) => value || DEFAULT_COLLECTION_SOURCE);
3310
+ }
3311
+ function parseCollectionManifest(json) {
3312
+ const value = JSON.parse(json);
3313
+ if (!value || typeof value !== "object" || !("collections" in value)) throw new Error("[ox-content] Native collection manifest returned an invalid payload.");
3314
+ return value;
3315
+ }
3316
+ function createNativeTransformOptions(options) {
3317
+ return {
3318
+ gfm: options.gfm,
3319
+ footnotes: options.footnotes,
3320
+ taskLists: options.taskLists,
3321
+ tables: options.tables,
3322
+ strikethrough: options.strikethrough,
3323
+ frontmatter: options.frontmatter,
3324
+ tocMaxDepth: options.tocMaxDepth,
3325
+ codeAnnotations: options.codeAnnotations?.enabled ?? false,
3326
+ codeAnnotationMetaKey: options.codeAnnotations?.metaKey ?? "annotate",
3327
+ codeAnnotationSyntax: options.codeAnnotations?.notation ?? "attribute",
3328
+ codeAnnotationDefaultLineNumbers: options.codeAnnotations?.defaultLineNumbers ?? false,
3329
+ wikiLinks: options.wikiLinks?.enabled ? {
3330
+ enabled: true,
3331
+ baseUrl: options.wikiLinks.baseUrl
3332
+ } : void 0,
3333
+ emojiShortcodes: options.emojiShortcodes?.enabled ? {
3334
+ enabled: true,
3335
+ custom: options.emojiShortcodes.custom
3336
+ } : void 0,
3337
+ attributes: options.attrs?.enabled ? { enabled: true } : void 0,
3338
+ cjkEmphasis: options.cjkEmphasis ?? false,
3339
+ codeImports: options.codeImports?.enabled ? {
3340
+ enabled: true,
3341
+ rootDir: options.codeImports.rootDir
3342
+ } : void 0,
3343
+ editThisPage: options.editThisPage?.enabled ? {
3344
+ enabled: true,
3345
+ repoUrl: options.editThisPage.repoUrl,
3346
+ branch: options.editThisPage.branch,
3347
+ rootDir: options.editThisPage.rootDir,
3348
+ label: options.editThisPage.label
3349
+ } : void 0
3350
+ };
3351
+ }
3352
+ function defaultCollections() {
3353
+ return { [DEFAULT_COLLECTION_NAME]: { source: DEFAULT_COLLECTION_SOURCE } };
3354
+ }
3355
+ //#endregion
3043
3356
  //#region src/incremental.ts
3044
3357
  function toNativeParserOptions(options = {}) {
3045
3358
  return {
@@ -3193,6 +3506,10 @@ function createFrameworkMarkdownOptions(options) {
3193
3506
  placeholder: "Search...",
3194
3507
  hotkey: "k"
3195
3508
  },
3509
+ collections: {
3510
+ enabled: false,
3511
+ collections: {}
3512
+ },
3196
3513
  embeds: {
3197
3514
  github: options.embeds?.github ?? {},
3198
3515
  openGraph: options.embeds?.openGraph ?? {},
@@ -4560,6 +4877,7 @@ function oxContent(options = {}) {
4560
4877
  createEnvironmentPlugin(resolvedOptions),
4561
4878
  createDocsPlugin(resolvedOptions, getRoot),
4562
4879
  createSsgPlugin(resolvedOptions, getRoot, ssgDevCache),
4880
+ createCollectionsPlugin(resolvedOptions, getRoot),
4563
4881
  createSearchPlugin(resolvedOptions, getRoot)
4564
4882
  ];
4565
4883
  if (resolvedOptions.i18n) plugins.push(createI18nPlugin(resolvedOptions));
@@ -4588,12 +4906,12 @@ function createMainPlugin(resolvedOptions, setConfig) {
4588
4906
  });
4589
4907
  },
4590
4908
  resolveId(id) {
4591
- if (id.startsWith("virtual:ox-content/")) return "\0" + id;
4909
+ if (id === "virtual:ox-content/config" || id === "virtual:ox-content/runtime") return "\0" + id;
4592
4910
  if (isMarkdownFilePath(id, resolvedOptions.extensions)) return id;
4593
4911
  return null;
4594
4912
  },
4595
4913
  async load(id) {
4596
- if (id.startsWith("\0virtual:ox-content/")) return generateVirtualModule(id.slice(20), resolvedOptions);
4914
+ if (id === "\0virtual:ox-content/config" || id === "\0virtual:ox-content/runtime") return generateVirtualModule(id.slice(20), resolvedOptions);
4597
4915
  return null;
4598
4916
  },
4599
4917
  async transform(code, id) {
@@ -4615,6 +4933,37 @@ function createMainPlugin(resolvedOptions, setConfig) {
4615
4933
  }
4616
4934
  };
4617
4935
  }
4936
+ function createCollectionsPlugin(resolvedOptions, getRoot) {
4937
+ const moduleId = "\0virtual:ox-content/collections";
4938
+ let moduleCode;
4939
+ const invalidate = (devServer) => {
4940
+ moduleCode = void 0;
4941
+ const mod = devServer.moduleGraph.getModuleById(moduleId);
4942
+ if (mod) {
4943
+ devServer.moduleGraph.invalidateModule(mod);
4944
+ devServer.ws.send({ type: "full-reload" });
4945
+ }
4946
+ };
4947
+ return {
4948
+ name: "ox-content:collections",
4949
+ resolveId(id) {
4950
+ return id === "virtual:ox-content/collections" ? moduleId : null;
4951
+ },
4952
+ async load(id) {
4953
+ if (id !== moduleId) return null;
4954
+ moduleCode ??= generateCollectionsVirtualModule(getRoot(), resolvedOptions);
4955
+ return moduleCode;
4956
+ },
4957
+ configureServer(devServer) {
4958
+ if (!resolvedOptions.collections.enabled) return;
4959
+ const srcDir = path.resolve(getRoot(), resolvedOptions.srcDir);
4960
+ devServer.watcher.add(srcDir);
4961
+ devServer.watcher.on("all", (_event, file) => {
4962
+ if (file.startsWith(srcDir) && isMarkdownFilePath(file, resolvedOptions.extensions)) invalidate(devServer);
4963
+ });
4964
+ }
4965
+ };
4966
+ }
4618
4967
  function createEnvironmentPlugin(resolvedOptions) {
4619
4968
  return {
4620
4969
  name: "ox-content:environment",
@@ -4768,6 +5117,7 @@ function resolveOptions(options) {
4768
5117
  transformers: options.transformers ?? [],
4769
5118
  docs: resolveDocsOptions(options.docs),
4770
5119
  search: resolveSearchOptions(options.search),
5120
+ collections: resolveCollectionsOptions(options.collections),
4771
5121
  ogViewer: options.ogViewer ?? true,
4772
5122
  embeds: resolveBuiltinEmbedOptions(options.embeds),
4773
5123
  i18n: resolveI18nOptions(options.i18n)
@@ -5030,6 +5380,7 @@ exports.DocsTestRunError = DocsTestRunError;
5030
5380
  exports.Fragment = Fragment;
5031
5381
  exports.IncrementalMarkdownParser = IncrementalMarkdownParser;
5032
5382
  exports.IncrementalMarkdownRenderer = IncrementalMarkdownRenderer;
5383
+ exports.buildCollectionManifest = buildCollectionManifest;
5033
5384
  exports.buildSearchIndex = buildSearchIndex;
5034
5385
  exports.buildSsg = buildSsg;
5035
5386
  exports.clearRenderContext = clearRenderContext;
@@ -5046,6 +5397,8 @@ exports.createIncrementalMarkdownRenderer = createIncrementalMarkdownRenderer;
5046
5397
  exports.createMarkdownEnvironment = createMarkdownEnvironment;
5047
5398
  exports.createTheme = createTheme;
5048
5399
  exports.defaultTheme = require_vitepress.defaultTheme;
5400
+ exports.defineCollection = defineCollection;
5401
+ exports.defineCollections = defineCollections;
5049
5402
  exports.defineTheme = require_vitepress.defineTheme;
5050
5403
  exports.each = each;
5051
5404
  exports.escapeSvelteMarkup = escapeSvelteMarkup;
@@ -5058,6 +5411,7 @@ exports.fetchGitHubSource = require_github.fetchGitHubSource;
5058
5411
  exports.fetchOgpData = require_ogp.fetchOgpData;
5059
5412
  exports.fetchRepoData = require_github.fetchRepoData;
5060
5413
  exports.fromVitePressConfig = require_vitepress.fromVitePressConfig;
5414
+ exports.generateCollectionsVirtualModule = generateCollectionsVirtualModule;
5061
5415
  exports.generateFrontmatterTypes = generateFrontmatterTypes;
5062
5416
  exports.generateHydrationScript = generateHydrationScript;
5063
5417
  exports.generateMarkdown = generateMarkdown;
@@ -5098,6 +5452,7 @@ exports.renderMarkdownStream = renderMarkdownStream;
5098
5452
  exports.renderPage = renderPage;
5099
5453
  exports.renderToString = renderToString;
5100
5454
  exports.resolveBuiltinEmbedOptions = resolveBuiltinEmbedOptions;
5455
+ exports.resolveCollectionsOptions = resolveCollectionsOptions;
5101
5456
  exports.resolveDocsOptions = resolveDocsOptions;
5102
5457
  exports.resolveI18nOptions = resolveI18nOptions;
5103
5458
  exports.resolveOgImageOptions = resolveOgImageOptions;