Skip to content

Commit 06151fc

Browse files
authored
Merge pull request #1486 from processing/search-fix-2
Fix case sensitivity bug in search on 2.0
2 parents 83b49c5 + e46985c commit 06151fc

9 files changed

Lines changed: 70 additions & 39 deletions

File tree

‎public/search-indices/en.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎public/search-indices/es.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎public/search-indices/hi.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎public/search-indices/ko.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎public/search-indices/zh-Hans.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎src/pages/_utils-node.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,24 @@ export const rewriteRelativeLink = (url: string): string => {
7878

7979
return updatedUrl;
8080
};
81+
82+
/**
83+
* Transforms an Astro content slug for an example into the legacy website slug.
84+
*
85+
* Astro automatically uses the directory structure for slug information.
86+
* Historically the p5 website has used a different structure for example file
87+
* vs. webpage routing. This function bridges the two.
88+
*
89+
* Note: This function lives in _utils-node.ts (rather than _utils.ts) so that
90+
* it can be imported by Node-only scripts such as the search-index builder
91+
* without pulling in Astro-specific virtual modules.
92+
*/
93+
export const exampleContentSlugToLegacyWebsiteSlug = (slug: string): string =>
94+
slug
95+
// First transformation: Remove any locale prefix.
96+
.replace(/^[\w-]+?\//, "") // Remove locale prefix
97+
// Second transformation: Convert slugs built from local dev path to the legacy format.
98+
// For example, "123_topicA/456_topicB/description" becomes "topicA-topicB.html".
99+
.replace(/\d+_(.*?)\/\d+_(.*?)\/description$/, "$1-$2")
100+
// Third transformation: Replace all remaining underscores in the slug with hyphens.
101+
.replace(/_/g, "-");

‎src/pages/_utils.ts‎

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { JSDOM } from "jsdom";
1111
import type { JumpToLink, JumpToState } from "../globals/state";
1212
import { categories as referenceCategories } from "../content/reference/config";
1313
import memoize from "lodash/memoize";
14-
import { removeNestedReferencePaths } from "./_utils-node";
14+
import { removeNestedReferencePaths, exampleContentSlugToLegacyWebsiteSlug } from "./_utils-node";
15+
export { exampleContentSlugToLegacyWebsiteSlug };
1516

1617
interface EntryWithId {
1718
id: string;
@@ -141,25 +142,10 @@ export const getRelatedEntriesinCollection = async <
141142
return foundEntries.filter((el) => el !== undefined) as CollectionEntry<C>[];
142143
};
143144

144-
/**
145-
* Astro automatically uses the directory structure for slug information
146-
* Historically the p5 website has used a different structure for example file vs. webpage routing
147-
* This function transforms the Astro slug to the appropriate webpage route to avoid breaking
148-
* Any inbound legacy links
149-
*/
150-
export const exampleContentSlugToLegacyWebsiteSlug = (slug: string): string =>
151-
slug
152-
// First transformation: Remove any locale prefix.
153-
.replace(/^[\w-]+?\//, "") // Remove locale prefix
154-
// Second transformation: Convert slugs built from local dev path to the legacy format.
155-
// For example, "123_topicA/456_topicB/description" becomes "topicA-topicB.html".
156-
.replace(/\d+_(.*?)\/\d+_(.*?)\/description$/, "$1-$2")
157-
// Third transformation: Replace all remaining underscores in the slug with hyphens.
158-
.replace(/_/g, "-");
159-
160145
export const getExampleCategory = (entry: any): string =>
161146
entry.filePath.split("/")[4].split("_").splice(1).join(" ");
162147

148+
163149
export const normalizeReferenceRoute = (route: string): string =>
164150
removeNestedReferencePaths(removeLocaleAndExtension(route));
165151

‎src/scripts/builders/search.ts‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import keywordExtractor from "keyword-extractor";
1010
import { contentTypes } from "../../globals/globals";
1111
import { supportedLocales as localesWithSearchSupport } from "../../i18n/const";
1212
import type { LanguageName } from "keyword-extractor/types/lib/keyword_extractor";
13-
import { removeNestedReferencePaths } from "../../pages/_utils-node";
13+
import { removeNestedReferencePaths, exampleContentSlugToLegacyWebsiteSlug } from "../../pages/_utils-node";
1414

1515
interface SearchIndex {
1616
[title: string]: {
@@ -223,19 +223,19 @@ export const generateSearchIndex = async (
223223
title = data.title;
224224
description = getKeywordsFromContent(content, locale);
225225
break;
226-
case "examples":
227-
relativeUrl = file
226+
case "examples": {
227+
// The helper expects a slug with the locale prefix intact (e.g.
228+
// "en/05_Transformation/01_Rotate/description") because its first
229+
// regex strips ^[\w-]+?/ (the locale). contentRelativeUrl is already
230+
// locale-stripped, so derive the slug from the content base path.
231+
const exampleSlug = file
228232
.replace("src/content/examples/", "")
229-
.replace(".mdx", "")
230-
.toLowerCase()
231-
// TODO: Separate Astro utils from the exampleContentSlugToLegacyWebsiteSlug
232-
.replace(/^[\w-]+?\//, "")
233-
.replace(/\d+_(.*?)\/\d+_(.*?)\/description$/, "$1-$2")
234-
.replace(/_/g, "-");
235-
relativeUrl = `/examples/${relativeUrl}`;
233+
.replace(".mdx", "");
234+
relativeUrl = `/examples/${exampleContentSlugToLegacyWebsiteSlug(exampleSlug)}`;
236235
title = data.title;
237236
description = getKeywordsFromContent(content, locale);
238237
break;
238+
}
239239
case "reference":
240240
relativeUrl = removeNestedReferencePaths(relativeUrl);
241241
title = data.title;

‎test/scripts/build-search.test.ts‎

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import { describe, expect, test, vi } from "vitest";
22
import { generateSearchIndex } from "../../src/scripts/builders/search";
3+
import { getContentFilePaths } from "../../src/scripts/utils";
34
import type {
45
ContentType,
56
SearchSupportedLocales,
67
} from "../../types/content.interface";
78

89
vi.mock("../../src/scripts/utils", () => ({
9-
getContentFilePaths: vi
10-
.fn()
11-
.mockResolvedValue([
12-
"src/content/reference/en/p5/mouseX.mdx",
13-
"src/content/reference/en/p5.Vector/add.mdx",
14-
"src/content/reference/en/p5/loadImage.mdx",
15-
]),
10+
getContentFilePaths: vi.fn(),
1611
}));
1712

13+
const mockedGetContentFilePaths = vi.mocked(getContentFilePaths);
14+
1815
describe("Search Index Title Generation", () => {
1916
test("generates correct titles for reference items", async () => {
17+
mockedGetContentFilePaths.mockResolvedValue([
18+
"src/content/reference/en/p5/mouseX.mdx",
19+
"src/content/reference/en/p5.Vector/add.mdx",
20+
"src/content/reference/en/p5/loadImage.mdx",
21+
]);
22+
2023
const mockContentType: ContentType = "reference";
2124
const mockLocale: SearchSupportedLocales = "en";
2225

@@ -40,3 +43,24 @@ describe("Search Index Title Generation", () => {
4043
expect(result?.["loadImage()"].alias).toBe("loadImage");
4144
});
4245
});
46+
47+
describe("Search Index Example URL Generation", () => {
48+
test("generates correct case-sensitive URLs for example items", async () => {
49+
mockedGetContentFilePaths.mockResolvedValue([
50+
"src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx",
51+
"src/content/examples/en/05_Transformation/01_Rotate/description.mdx",
52+
]);
53+
54+
const result = await generateSearchIndex("examples", "en");
55+
56+
expect(result).toBeDefined();
57+
58+
// Verify URLs preserve original casing and match Astro routing
59+
expect(result?.["Shape Primitives"].relativeUrl).toBe(
60+
"/examples/Shapes-And-Color-Shape-Primitives",
61+
);
62+
expect(result?.["Rotate"].relativeUrl).toBe(
63+
"/examples/Transformation-Rotate",
64+
);
65+
});
66+
});

0 commit comments

Comments
 (0)