diff --git a/docs/userGuide/makingTheSiteSearchable.md b/docs/userGuide/makingTheSiteSearchable.md
index 709939541f..a1e92e96f4 100644
--- a/docs/userGuide/makingTheSiteSearchable.md
+++ b/docs/userGuide/makingTheSiteSearchable.md
@@ -101,34 +101,58 @@ In your `site.json`:
This tells Pagefind to exclude any element with the `algolia-no-index` class (or containing it in a space-separated list) from the search index, similar to using `data-pagefind-ignore`.
+For more details, see the [Pagefind documentation on exclude selector configuration option](https://pagefind.app/docs/config-options/#exclude-selectors).
+
#### Limiting Which Pages Are Searchable
-You can use the `glob` option to limit which pages are indexed by Pagefind. This is useful when you want search results to only show pages from specific sections of your site.
+Pagefind uses the existing `searchable` property in your `pages` configuration to determine which pages should be indexed. This provides a seamless way to control search indexing without additional configuration.
In your `site.json`:
```json
{
- "pagefind": {
- "glob": [
- "devGuide",
- "userGuide/*"
- ]
- }
+ "pages": [
+ {
+ "src": "index.md"
+ },
+ {
+ "src": "internal/notes.md",
+ "searchable": "no"
+ },
+ {
+ "glob": "devGuide/**/*.md",
+ "searchable": "no"
+ }
+ ]
}
```
-MarkBind supports glob patterns and will automatically append `.html` to your patterns if not specified. For example:
-- `"devGuide"` becomes `"devGuide/**/*.html"`
-- `"devGuide/*"` becomes `"devGuide/*.html"`
-- `"**/devGuide/**"` becomes `"**/devGuide/**/*.html"`
-- `"*.html"` remains `"*.html"` (no change needed)
+- Pages with `searchable: "no"` (or `false`) will not appear in search results
+- By default, all pages are searchable (`searchable: "yes"`)
+
+For more details on the `searchable` property, see [site.json file documentation](siteJsonFile.html#pages).
+
+
+
+MarkBind controls page indexing through the `searchable` property, which determines whether pages are passed to Pagefind for indexing. However, Pagefind also provides native attributes that can affect indexing:
-Only pages matching these glob patterns will appear in search results. This can be particularly useful for:
-- Multi-site setups where you want to search only specific sections
-- Including only certain directories from search results
+- [**`data-pagefind-body`**](https://pagefind.app/docs/indexing/#limiting-what-sections-of-a-page-are-indexed): Marks a specific element as the search content container. When this attribute exists on ANY page of your site, pages WITHOUT this attribute will not be indexed.
+- [**`data-pagefind-ignore`**](https://pagefind.app/docs/indexing/#removing-individual-elements-from-the-index): Excludes specific elements from the search index.
-For more details on glob patterns, see the [Pagefind documentation](https://pagefind.app/docs/config-options/#glob).
+**How MarkBind handles this:**
+
+1. Pages with `searchable: "no"` are NOT passed to Pagefind at all (they are never indexed).
+2. Pages with `searchable: "yes"` (default) ARE passed to Pagefind for indexing.
+
+**Interactions to be aware of:**
+
+- If you add `data-pagefind-body` to a searchable page, it works as expected - the page is indexed. However, only pages with this attribute will be searchable.
+- If you add `data-pagefind-body` to a non-searchable page, MarkBind will still NOT index it (because it's filtered before being passed to Pagefind).
+- Adding `data-pagefind-ignore` to a searchable page will NOT prevent it from being indexed - the page is still added via MarkBind's indexing, but the content within that element will be ignored by Pagefind.
+
+**Recommendation:** Use MarkBind's `searchable` property in site.json to control which pages are indexed & use `data-pagefind-body` attribute to exlcude specific elements within a page from being searchable. Avoid using `data-pagefind-body` as it is redundant and may lead to confusion.
+
+
diff --git a/docs/userGuide/siteJsonFile.md b/docs/userGuide/siteJsonFile.md
index d1a740baea..4f4b15546f 100644
--- a/docs/userGuide/siteJsonFile.md
+++ b/docs/userGuide/siteJsonFile.md
@@ -135,7 +135,7 @@ _(Optional)_ **The styling options to be applied to the site.** This includes:
* **`globExclude`**: An array of file patterns to be excluded from rendering when using `glob`, also defined in the glob syntax.
* **`title`**: The page `` for the generated web page. Titles specified here take priority over titles specified in the [frontmatter](tweakingThePageStructure.html#frontmatter) of individual pages.
* **`layout`**: The [layout](tweakingThePageStructure.html#layouts) to be used by the page. Default: `default`.
-* **`searchable`**: Specifies that the page(s) should be excluded from searching. Default: `yes`.
+* **`searchable`**: Specifies whether the page(s) should be included in search indexing. This applies to both the built-in search and Pagefind (if enabled). Set to `"no"` or `false` to exclude the page(s) from search results. Default: `yes`.
* **`externalScripts`**: An array of external scripts to be referenced on the page. Scripts referenced will be run before the layout script.
* **`frontmatter`**: Specifies properties to add to the frontmatter of a page or glob of pages. Overrides any existing properties if they have the same name, and overrides any frontmatter properties specified in `globalOverride`.
* **`fileExtension`**: A string that specifies the output file extension (e.g., `".json"`, `".txt"`) for the generated file. If not specified, defaults to `".html"`. Note that non-HTML files do not support frontmatter or scripts.
diff --git a/packages/core/src/Page/page.njk b/packages/core/src/Page/page.njk
index 7a96999e7d..b305315a95 100644
--- a/packages/core/src/Page/page.njk
+++ b/packages/core/src/Page/page.njk
@@ -34,7 +34,9 @@
-
+
{{ content }}
{{- pageUserScriptsAndStyles -}}
diff --git a/packages/core/src/Site/SiteConfig.ts b/packages/core/src/Site/SiteConfig.ts
index 0190ed7a86..5e68f62e8a 100644
--- a/packages/core/src/Site/SiteConfig.ts
+++ b/packages/core/src/Site/SiteConfig.ts
@@ -66,7 +66,6 @@ export class SiteConfig {
pagefind?: {
exclude_selectors?: string[];
- glob?: string | string[];
};
/**
diff --git a/packages/core/src/Site/SiteGenerationManager.ts b/packages/core/src/Site/SiteGenerationManager.ts
index fcc40c6737..a5fce2f302 100644
--- a/packages/core/src/Site/SiteGenerationManager.ts
+++ b/packages/core/src/Site/SiteGenerationManager.ts
@@ -871,74 +871,6 @@ export class SiteGenerationManager {
1000,
);
- /**
- * Validates that a glob pattern is safe and won't traverse outside the output directory.
- *
- * @param pattern - The glob pattern to validate
- * @returns true if the pattern is safe, false otherwise
- */
- // eslint-disable-next-line class-methods-use-this
- private isValidGlobPattern(pattern: string): boolean {
- if (pattern.includes('..')) {
- return false;
- }
-
- const isUnixAbsolutePath = pattern.startsWith('/');
- const isWindowsAbsolutePath = /^[a-zA-Z]:[\\/]/.test(pattern);
- if (isUnixAbsolutePath || isWindowsAbsolutePath) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Normalizes a gitignore-style glob pattern to a valid Wax/Pagefind pattern
- * by appending .html extension if not already present.
- * Invalid patterns (e.g., path traversal attempts) are logged and return empty string.
- *
- * @param pattern - The glob pattern from user config (gitignore-style)
- * @returns A valid Wax/Pagefind glob pattern, or empty string if invalid
- */
- private normalizeGlobPattern(pattern: string): string {
- const normalizedPattern = pattern.replace(/\\/g, '/');
-
- if (!this.isValidGlobPattern(pattern)) {
- logger.error(`Invalid glob pattern rejected (potential path traversal): ${pattern}`);
- return '';
- }
-
- if (normalizedPattern.endsWith('.html')) {
- return normalizedPattern;
- }
-
- if (normalizedPattern.endsWith('/**')) {
- return `${normalizedPattern}/*.html`;
- }
-
- if (normalizedPattern.endsWith('/*')) {
- return `${normalizedPattern}.html`;
- }
-
- if (normalizedPattern.endsWith('/')) {
- return `${normalizedPattern}**/*.html`;
- }
-
- return `${normalizedPattern}/**/*.html`;
- }
-
- /**
- * Indexes all HTML files in the output directory and logs any errors.
- * @param index - The pagefind index instance
- * @returns The number of pages indexed
- */
- // eslint-disable-next-line class-methods-use-this
- private async indexAllHtmlFiles(index: any): Promise {
- const result = await index.addDirectory({ path: this.outputPath });
- result.errors.forEach((error: string) => logger.error(error));
- return result.page_count;
- }
-
/**
* Indexes all the pages of the site using pagefind.
* @returns true if indexing succeeded and pagefind assets were written, false otherwise.
@@ -963,40 +895,43 @@ export class SiteGenerationManager {
const { index } = await createIndex(createIndexOptions);
if (index) {
- // Handle glob patterns - support both single string and array of strings
- const globValue = pagefindConfig.glob;
- const value = globValue ?? [];
- const globPatterns = Array.isArray(value) ? value : [value];
+ // Filter pages that should be indexed (searchable !== false)
+ const searchablePages = this.sitePages.pages.filter(
+ page => page.pageConfig.searchable,
+ );
let totalPageCount = 0;
- if (globPatterns.length > 0) {
- const normalizedPatterns = globPatterns
- .map(pattern => this.normalizeGlobPattern(pattern))
- .filter(pattern => pattern !== '');
-
- if (normalizedPatterns.length > 0) {
- const results = await Promise.all(
- normalizedPatterns.map(async (normalizedPattern) => {
- logger.info(`Pagefind indexing with glob: ${normalizedPattern}`);
- const result = await index.addDirectory({
- path: this.outputPath,
- glob: normalizedPattern,
- });
-
- result.errors.forEach((error: string) => logger.error(error));
-
- return result.page_count;
- }),
- );
-
- totalPageCount += results.reduce((acc, count) => acc + count, 0);
- } else {
- logger.warn('All glob patterns were invalid, falling back to indexing all HTML files');
- totalPageCount = await this.indexAllHtmlFiles(index);
- }
+ if (searchablePages.length === 0) {
+ logger.info('No pages configured for search indexing');
} else {
- totalPageCount = await this.indexAllHtmlFiles(index);
+ // Add each searchable page to the index using addHTMLFile
+ const indexingResults = await Promise.all(
+ searchablePages.map(async (page) => {
+ try {
+ const content = await fs.readFile(page.pageConfig.resultPath, 'utf8');
+ const relativePath = path.relative(this.outputPath, page.pageConfig.resultPath);
+
+ return index.addHTMLFile({
+ sourcePath: relativePath,
+ content,
+ });
+ } catch (error) {
+ logger.error(`Failed to index ${page.pageConfig.resultPath}: ${error}`);
+ return null;
+ }
+ }),
+ );
+
+ // Count successful indexings
+ totalPageCount = indexingResults.filter(r => r !== null).length;
+
+ // Log any errors from indexing results
+ indexingResults.forEach((result) => {
+ if (result && result.errors) {
+ result.errors.forEach((error: string) => logger.error(error));
+ }
+ });
}
const endTime = new Date();
diff --git a/packages/core/test/unit/Site/SiteGenerationManager.test.ts b/packages/core/test/unit/Site/SiteGenerationManager.test.ts
index 4e9cdb0559..02745f543b 100644
--- a/packages/core/test/unit/Site/SiteGenerationManager.test.ts
+++ b/packages/core/test/unit/Site/SiteGenerationManager.test.ts
@@ -32,7 +32,11 @@ jest.mock('../../../src/Site/SiteAssetsManager', () => ({
jest.mock('../../../src/Site/SitePagesManager', () => ({
SitePagesManager: jest.fn().mockImplementation(function (this: any) {
this.baseUrlMap = new Set();
- this.collectAddressablePages = jest.fn();
+ this.addressablePages = [];
+ this.pages = [];
+ this.collectAddressablePages = jest.fn().mockImplementation(() => {
+ // Do nothing - preserve the manually set addressablePages for testing
+ });
this.setBaseUrlMap = jest.fn().mockImplementation((map) => {
this.baseUrlMap = map;
});
@@ -80,45 +84,6 @@ describe('SiteGenerationManager', () => {
generationManager.configure(siteAssets, sitePages);
});
- describe('normalizeGlobPattern', () => {
- const prototypeMethod = (SiteGenerationManager.prototype as any).normalizeGlobPattern;
-
- test('should return pattern as-is if it ends with .html', () => {
- const result = prototypeMethod.call(generationManager, 'page.html');
- expect(result).toBe('page.html');
- });
-
- test('should append /*.html if pattern ends with /**', () => {
- const result = prototypeMethod.call(generationManager, 'dir/**');
- expect(result).toBe('dir/**/*.html');
- });
-
- test('should append .html if pattern ends with /*', () => {
- const result = prototypeMethod.call(generationManager, 'dir/*');
- expect(result).toBe('dir/*.html');
- });
-
- test('should append **/*.html if pattern ends with /', () => {
- const result = prototypeMethod.call(generationManager, 'dir/');
- expect(result).toBe('dir/**/*.html');
- });
-
- test('should append /**/*.html for plain directory names', () => {
- const result = prototypeMethod.call(generationManager, 'dir');
- expect(result).toBe('dir/**/*.html');
- });
-
- test('should return empty string for invalid path traversal patterns', () => {
- const result = prototypeMethod.call(generationManager, '../../../etc/**');
- expect(result).toBe('');
- });
-
- test('should return empty string for absolute paths', () => {
- const result = prototypeMethod.call(generationManager, '/etc/passwd');
- expect(result).toBe('');
- });
- });
-
describe('indexSiteWithPagefind', () => {
beforeEach(() => {
const json = {
@@ -154,42 +119,6 @@ describe('SiteGenerationManager', () => {
});
});
- test('should read glob configuration as string', async () => {
- const customSiteJson = createSiteJsonWithPagefind({
- pagefind: {
- glob: '**/docs/*.html',
- },
- });
- mockFs.vol.fromJSON({
- ...PAGE_NJK,
- 'site.json': customSiteJson,
- '_site/index.html': 'Test',
- }, rootPath);
-
- await generationManager.readSiteConfig();
- expect(generationManager.siteConfig.pagefind).toEqual({
- glob: '**/docs/*.html',
- });
- });
-
- test('should read glob configuration as array', async () => {
- const customSiteJson = createSiteJsonWithPagefind({
- pagefind: {
- glob: ['**/docs/*.html', '**/guide/*.html'],
- },
- });
- mockFs.vol.fromJSON({
- ...PAGE_NJK,
- 'site.json': customSiteJson,
- '_site/index.html': 'Test',
- }, rootPath);
-
- await generationManager.readSiteConfig();
- expect(generationManager.siteConfig.pagefind).toEqual({
- glob: ['**/docs/*.html', '**/guide/*.html'],
- });
- });
-
test('should index site with default configuration', async () => {
const json = {
...PAGE_NJK,
@@ -245,70 +174,66 @@ describe('SiteGenerationManager', () => {
pagefindSpy.mockRestore();
});
- test('should handle glob pattern as string', async () => {
- const customSiteJson = createSiteJsonWithPagefind({
- pagefind: {
- glob: '**/docs/*.html',
- },
- });
- mockFs.vol.fromJSON({
+ test('should index searchable pages using addHTMLFile', async () => {
+ const json = {
...PAGE_NJK,
- 'site.json': customSiteJson,
+ 'site.json': SITE_JSON_DEFAULT,
'_site/index.html': 'Test',
- }, rootPath);
+ };
+ mockFs.vol.fromJSON(json, rootPath);
- const mockIndex = createMockIndex({ page_count: 3, errors: [] });
+ const mockIndex = createMockIndex({ page_count: 1, errors: [] }, { errors: [] });
const mockPagefindInstance = createMockPagefind(mockIndex, true);
const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
mockPagefindInstance.createIndex({}) as any,
);
- await generationManager.readSiteConfig();
+ generationManager.siteConfig = { enableSearch: true, pages: [] } as any;
+ const pageConfig = { resultPath: path.join(outputPath, 'index.html'), searchable: true };
+ generationManager.sitePages.pages = [{ pageConfig }] as any;
+
await generationManager.indexSiteWithPagefind();
- expect(mockIndex.addDirectory).toHaveBeenCalledWith({
- path: outputPath,
- glob: '**/docs/*.html',
+ expect(mockIndex.addHTMLFile).toHaveBeenCalledWith({
+ sourcePath: 'index.html',
+ content: 'Test',
});
pagefindSpy.mockRestore();
});
- test('should handle glob pattern as array', async () => {
- const customSiteJson = createSiteJsonWithPagefind({
- pagefind: {
- glob: ['**/docs/*.html', '**/guide/*.html'],
- },
- });
- mockFs.vol.fromJSON({
+ test('should log errors from addHTMLFile', async () => {
+ const json = {
...PAGE_NJK,
- 'site.json': customSiteJson,
+ 'site.json': SITE_JSON_DEFAULT,
'_site/index.html': 'Test',
- }, rootPath);
+ };
+ mockFs.vol.fromJSON(json, rootPath);
- const mockIndex = createMockIndex({ page_count: 2, errors: [] });
+ const mockIndex = createMockIndex(
+ { page_count: 0, errors: [] },
+ { errors: ['Error 1', 'Error 2'] },
+ );
const mockPagefindInstance = createMockPagefind(mockIndex, true);
const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
mockPagefindInstance.createIndex({}) as any,
);
+ const errorSpy = jest.spyOn(logger, 'error').mockImplementation();
+
+ generationManager.siteConfig = { enableSearch: true, pages: [] } as any;
+ const pageConfig2 = { resultPath: path.join(outputPath, 'index.html'), searchable: true };
+ generationManager.sitePages.pages = [{ pageConfig: pageConfig2 }] as any;
- await generationManager.readSiteConfig();
await generationManager.indexSiteWithPagefind();
- expect(mockIndex.addDirectory).toHaveBeenCalledTimes(2);
- expect(mockIndex.addDirectory).toHaveBeenNthCalledWith(1, {
- path: outputPath,
- glob: '**/docs/*.html',
- });
- expect(mockIndex.addDirectory).toHaveBeenNthCalledWith(2, {
- path: outputPath,
- glob: '**/guide/*.html',
- });
+ expect(errorSpy).toHaveBeenCalledWith('Error 1');
+ expect(errorSpy).toHaveBeenCalledWith('Error 2');
pagefindSpy.mockRestore();
+ errorSpy.mockRestore();
});
- test('should index all HTML files when no glob specified', async () => {
+ test('should skip indexing when pagefind import fails', async () => {
const json = {
...PAGE_NJK,
'site.json': SITE_JSON_DEFAULT,
@@ -316,23 +241,21 @@ describe('SiteGenerationManager', () => {
};
mockFs.vol.fromJSON(json, rootPath);
- const mockIndex = createMockIndex({ page_count: 10, errors: [] });
- const mockPagefindInstance = createMockPagefind(mockIndex, true);
- const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
- mockPagefindInstance.createIndex({}) as any,
+ const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockRejectedValue(
+ new Error('Module not found'),
);
+ const warnSpy = jest.spyOn(logger, 'warn').mockImplementation();
await generationManager.readSiteConfig();
await generationManager.indexSiteWithPagefind();
- expect(mockIndex.addDirectory).toHaveBeenCalledWith({
- path: outputPath,
- });
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Pagefind indexing skipped'));
pagefindSpy.mockRestore();
+ warnSpy.mockRestore();
});
- test('should log errors from addDirectory', async () => {
+ test('should handle when createIndex returns null index', async () => {
const json = {
...PAGE_NJK,
'site.json': SITE_JSON_DEFAULT,
@@ -340,8 +263,7 @@ describe('SiteGenerationManager', () => {
};
mockFs.vol.fromJSON(json, rootPath);
- const mockIndex = createMockIndex({ page_count: 1, errors: ['Error 1', 'Error 2'] });
- const mockPagefindInstance = createMockPagefind(mockIndex, true);
+ const mockPagefindInstance = createMockPagefindNullIndex();
const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
mockPagefindInstance.createIndex({}) as any,
);
@@ -350,56 +272,98 @@ describe('SiteGenerationManager', () => {
await generationManager.readSiteConfig();
await generationManager.indexSiteWithPagefind();
- expect(errorSpy).toHaveBeenCalledWith('Error 1');
- expect(errorSpy).toHaveBeenCalledWith('Error 2');
+ expect(errorSpy).toHaveBeenCalledWith('Pagefind failed to create index');
pagefindSpy.mockRestore();
errorSpy.mockRestore();
});
- test('should skip indexing when pagefind import fails', async () => {
+ test('should calculate searchable page count from addressablePages', async () => {
const json = {
...PAGE_NJK,
'site.json': SITE_JSON_DEFAULT,
- '_site/index.html': 'Test',
+ '_site/index.html': 'Test page',
+ '_site/page1.html': 'Page 1',
+ '_site/page2.html': 'Page 2',
};
mockFs.vol.fromJSON(json, rootPath);
- const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockRejectedValue(
- new Error('Module not found'),
+ const mockIndex = createMockIndex({ page_count: 3, errors: [] }, { errors: [] });
+ const mockPagefindInstance = createMockPagefind(mockIndex, true);
+ const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
+ mockPagefindInstance.createIndex({}) as any,
);
- const warnSpy = jest.spyOn(logger, 'warn').mockImplementation();
+ const infoSpy = jest.spyOn(logger, 'info').mockImplementation();
+
+ generationManager.siteConfig = { enableSearch: true, pages: [] } as any;
+ generationManager.sitePages.pages = [
+ { pageConfig: { resultPath: path.join(outputPath, 'index.html'), searchable: true } },
+ { pageConfig: { resultPath: path.join(outputPath, 'page1.html'), searchable: true } },
+ { pageConfig: { resultPath: path.join(outputPath, 'page2.html'), searchable: false } },
+ ] as any;
- await generationManager.readSiteConfig();
await generationManager.indexSiteWithPagefind();
- expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Pagefind indexing skipped'));
+ expect(infoSpy).toHaveBeenCalledWith(expect.stringMatching(/Pagefind indexed 2 pages in/));
pagefindSpy.mockRestore();
- warnSpy.mockRestore();
+ infoSpy.mockRestore();
});
- test('should handle when createIndex returns null index', async () => {
+ test('should handle searchable as string "no"', async () => {
const json = {
...PAGE_NJK,
'site.json': SITE_JSON_DEFAULT,
- '_site/index.html': 'Test',
+ '_site/index.html': 'Test page',
+ '_site/page1.html': 'Page 1',
};
mockFs.vol.fromJSON(json, rootPath);
- const mockPagefindInstance = createMockPagefindNullIndex();
+ const mockIndex = createMockIndex({ page_count: 1, errors: [] }, { errors: [] });
+ const mockPagefindInstance = createMockPagefind(mockIndex, true);
const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
mockPagefindInstance.createIndex({}) as any,
);
- const errorSpy = jest.spyOn(logger, 'error').mockImplementation();
+ const infoSpy = jest.spyOn(logger, 'info').mockImplementation();
+
+ generationManager.siteConfig = { enableSearch: true, pages: [] } as any;
+ generationManager.sitePages.pages = [
+ { pageConfig: { resultPath: path.join(outputPath, 'index.html'), searchable: false } },
+ { pageConfig: { resultPath: path.join(outputPath, 'page1.html'), searchable: true } },
+ ] as any;
- await generationManager.readSiteConfig();
await generationManager.indexSiteWithPagefind();
- expect(errorSpy).toHaveBeenCalledWith('Pagefind failed to create index');
+ expect(infoSpy).toHaveBeenCalledWith(expect.stringMatching(/Pagefind indexed 1 pages in/));
pagefindSpy.mockRestore();
- errorSpy.mockRestore();
+ infoSpy.mockRestore();
+ });
+
+ test('should handle all pages non-searchable', async () => {
+ const json = {
+ ...PAGE_NJK,
+ 'site.json': SITE_JSON_DEFAULT,
+ '_site/index.html': 'Test page',
+ };
+ mockFs.vol.fromJSON(json, rootPath);
+
+ const mockIndex = createMockIndex({ page_count: 1, errors: [] });
+ const mockPagefindInstance = createMockPagefind(mockIndex, true);
+ const pagefindSpy = jest.spyOn(pagefind, 'createIndex').mockResolvedValue(
+ mockPagefindInstance.createIndex({}) as any,
+ );
+ const infoSpy = jest.spyOn(logger, 'info').mockImplementation();
+
+ generationManager.siteConfig = { enableSearch: true } as any;
+ generationManager.sitePages.addressablePages = [{ src: 'index.md', searchable: false }];
+
+ await generationManager.indexSiteWithPagefind();
+
+ expect(infoSpy).toHaveBeenCalledWith(expect.stringMatching(/Pagefind indexed 0 pages in/));
+
+ pagefindSpy.mockRestore();
+ infoSpy.mockRestore();
});
});
diff --git a/packages/core/test/unit/utils/data.ts b/packages/core/test/unit/utils/data.ts
index 7d223f4942..65762818b6 100644
--- a/packages/core/test/unit/utils/data.ts
+++ b/packages/core/test/unit/utils/data.ts
@@ -102,8 +102,14 @@ export interface MockAddDirectoryResult {
errors?: string[];
}
+export interface MockAddHTMLFileResult {
+ file?: { path: string };
+ errors?: string[];
+}
+
export interface MockIndex {
addDirectory: ReturnType;
+ addHTMLFile: ReturnType;
writeFiles: ReturnType;
}
@@ -115,12 +121,15 @@ export interface MockPagefind {
/**
* Creates a mock pagefind index
* @param result - The result to return from addDirectory
+ * @param htmlFileResult - The result to return from addHTMLFile
*/
export function createMockIndex(
result: MockAddDirectoryResult = { page_count: 1, errors: [] },
+ htmlFileResult: MockAddHTMLFileResult = { errors: [] },
): MockIndex {
return {
addDirectory: jest.fn().mockResolvedValue(result),
+ addHTMLFile: jest.fn().mockResolvedValue(htmlFileResult),
writeFiles: jest.fn().mockResolvedValue(undefined),
};
}