Skip to content

Conversation

jjspace
Copy link
Contributor

@jjspace jjspace commented Jul 21, 2025

Description

Re-implement searching for sandcastles in the Gallery using pagefind.

Pagefind is primarily targeted at indexing static html files. We need to build our own custom indexes so it can search in the JS code. I've looped this into the script that already builds the gallery list of metadata. I've also chosen to store the build output inside the gallery directory so the FE can be pointed at a single "gallery path" and load everything it needs for search and the list and assets. (Eventually we will need to support multiple galleries but this is not part of this PR)

When pagefind builds an index it also builds the JS module we should import for that index. This makes vite (and TS) a bit upset because it doesn't know where the files are. We need to do a dynamic import and tell vite to ignore it to actually load the pagefind web module. I encapsulated all this logic in the GallerySearch component to keep it all in one place.

Issue number and link

Part of #12566

Testing plan

  • run npm run dev in the package or npm run build-sandcastle and npm start from the project root
  • Search for something in the gallery. Test multiple terms, including ones that have no results
  • Test the dropdown for filtering tags. Make sure it works with a search term and without
  • If you want to test with all the sandcastles copy the convertGallery.js script into packages/sandcastle/scripts and run it. This will generate all the other sandcastles and re-running the build scripts will index them all.

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

@jjspace jjspace requested a review from ggetz July 21, 2025 20:33
Copy link

Thank you for the pull request, @jjspace!

✅ We can confirm we have a CLA on file for you.

Copy link
Contributor

@ggetz ggetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Searching is so much better 🎉 This was a HUGE user request, so it's fantastic to see.

So much so, I suggest considering adding a top-level button to the project bar— similar to VS Code. If we like it, let's implement outside of this PR.

Image

const jsFile = readFileSync(`${galleryBase}/main.js`, "utf-8");
await index.addCustomRecord({
url: `?id=${slug}`,
content: jsFile,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we surround this with <code> tags for better suggestion display?

Suggested change
content: jsFile,
content: `<pre><code>${jsFile}</pre></code>`,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried out multiple options for this and none preserve the newlines like we'd want to display them directly... This tool is very focused at plain text.

AFAICT when using addCustomRecord it always processes the content as text and escapes html and considers it part of the result.

There is also an addHTMLFile function that lets you pass in a string of html to be processed as html but even then it pulls out the plaintext of the content and seems to strip newlines.

It might be possible to dig into this a bit more but everything I've tried so far doesn't help our unique situation. I think what we have now might be the best we get without a decent bit of extra effort and maybe changes to pagefind itself.

isNew: boolean;
};

export function GallerySearch({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this component to its own file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it that way at first but then it felt excessive. These components are fairly coupled in logic and data flow. I only separated them for encapsulation of logic, specifically the pagefind loading. Also this component is only used inside the larger Gallery component that this file actually exports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, hearing that they're tightly coupled seems like a red flag to me. What do you think is the biggest culprit of the coupling? Is it that we're relying on reducers and not contexts to share state?

Comment on lines +141 to +146
<option value={"All"}>All</option>
{Object.keys(availableFilters.tags).map((label) => (
<option value={label} key={label}>
{label}
</option>
))}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may end up being a bit much to iterate on for this particular PR, but I think we discussed some alternatives for how the categories/labels are presented offline.

Could you please add "Refine gallery filter by label presentation" to the list of TODO's?

@jjspace
Copy link
Contributor Author

jjspace commented Jul 28, 2025

now that #12752 is merged in this will include all sandcastles and demonstrate search better

Base automatically changed from stratakit-ui to sandcastle-v2 July 28, 2025 22:06
@jjspace
Copy link
Contributor Author

jjspace commented Aug 1, 2025

@ggetz I think this is ready for another look

@ggetz
Copy link
Contributor

ggetz commented Aug 4, 2025

Overall this is looking good. I do have some concerns about the coupled components, and left a follow up comment above.

When testing out the search, it doesn't appear that sandcastle titles are being included in the search. I think they should be. No worries if that's addresses here or in a follow up PR. Just let me know what you'd prefer @jjspace.

@ggetz
Copy link
Contributor

ggetz commented Aug 8, 2025

Seems like it'll make sense to follow up on this in subsequent PRs, so I'll go ahead and merge this.

@ggetz ggetz merged commit 37dd9c1 into sandcastle-v2 Aug 8, 2025
9 checks passed
@ggetz ggetz deleted the gallery-search branch August 8, 2025 15:59
@jjspace jjspace mentioned this pull request Sep 2, 2025
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants