Skip to content

More website tweaks#977

Merged
aaronpowell merged 8 commits into
stagedfrom
more-website-tweaks
Mar 12, 2026
Merged

More website tweaks#977
aaronpowell merged 8 commits into
stagedfrom
more-website-tweaks

Conversation

@aaronpowell
Copy link
Copy Markdown
Contributor

This pull request updates dependencies and introduces new packages to the website project, primarily adding support for parsing and rendering markdown and front matter, as well as upgrading syntax highlighting libraries. Additionally, a new Astro component is added for embedding page data as JSON. These changes collectively improve content processing and code highlighting capabilities.

aaronpowell and others added 8 commits March 11, 2026 14:47
Render resource listing pages in Astro for first paint and hydrate client filtering/search behavior on top.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 12, 2026 00:46
@aaronpowell aaronpowell merged commit e65c835 into staged Mar 12, 2026
4 checks passed
@aaronpowell aaronpowell deleted the more-website-tweaks branch March 12, 2026 00:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes the website’s client-side rendering and modal preview experience by embedding page JSON into the HTML, refactoring list rendering into shared render helpers, and adding markdown rendering + syntax highlighting support.

Changes:

  • Embed public/data/*.json into pages (via a new EmbeddedPageData component) and have fetchData() read embedded JSON before making network requests.
  • Refactor multiple listing pages (agents/instructions/hooks/skills/workflows/tools/plugins/samples) to use shared *-render.ts helpers and delegated event handling.
  • Upgrade the modal to support rendered markdown (front matter stripped) and highlighted code preview, plus add a skills file switcher and lazy-load JSZip for downloads.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
website/src/styles/global.css Updates modal/listing toolbar styling; adjusts font path and adds new modal/file-switcher styles.
website/src/scripts/utils.ts Adds embedded-data support to fetchData() and introduces loadJSZip() lazy loader; tweaks escaping and resource typing.
website/src/scripts/pages/workflows.ts Switches to shared renderer/sorter and delegated click handling.
website/src/scripts/pages/workflows-render.ts New shared HTML renderer + sorter for workflows.
website/src/scripts/pages/tools.ts Switches to shared renderer, delegated copy handlers, and one-time init guard.
website/src/scripts/pages/tools-render.ts New shared renderer for tools with URL sanitization.
website/src/scripts/pages/skills.ts Uses shared renderer/sorter; adds delegated handlers; lazy-loads JSZip for downloads.
website/src/scripts/pages/skills-render.ts New shared HTML renderer + sorter for skills.
website/src/scripts/pages/samples.ts Refactors rendering/results-count logic into shared renderer utilities; adds init guard and debounced search.
website/src/scripts/pages/samples-render.ts New shared renderer + results-count formatter for cookbook/samples page.
website/src/scripts/pages/plugins.ts Uses shared renderer; removes featured filter; adds delegated click handling.
website/src/scripts/pages/plugins-render.ts New shared HTML renderer for plugins (includes external URL handling).
website/src/scripts/pages/instructions.ts Uses shared renderer/sorter and delegated click handling; widens applyTo typing.
website/src/scripts/pages/instructions-render.ts New shared HTML renderer + sorter for instructions.
website/src/scripts/pages/hooks.ts Uses shared renderer/sorter; delegated click + lazy-load JSZip for downloads.
website/src/scripts/pages/hooks-render.ts New shared HTML renderer + sorter for hooks.
website/src/scripts/pages/agents.ts Uses shared renderer/sorter and delegated click handling; updates results count initialization.
website/src/scripts/pages/agents-render.ts New shared HTML renderer + sorter for agents.
website/src/scripts/modal.ts Adds markdown rendering (marked + front-matter), Shiki highlighting, view-mode toggles, and a skills file switcher.
website/src/scripts/embedded-data.ts New helper for embedding and reading JSON from <script type="application/json">.
website/src/pages/*.astro + website/src/pages/learning-hub/cookbook/index.astro Server-renders initial lists and embeds page JSON for fast client init.
website/src/components/Modal.astro Updates modal layout, adds Render/Raw controls, and adds a file switcher UI.
website/src/components/EmbeddedPageData.astro New component to serialize/inline page JSON payloads.
website/package.json + website/package-lock.json Adds markdown/front matter + highlighting deps (marked/front-matter/shiki) and lock updates.
Files not reviewed (1)
  • website/package-lock.json: Language not supported

You can also share your feedback on Copilot code review. Take the survey.

</button>
<a href="${getGitHubUrl(
item.path
)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This link opens a new tab (target="_blank") without rel="noopener noreferrer", which allows reverse-tabnabbing. Add rel="noopener noreferrer" to external links opened in a new tab.

Suggested change
)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
)}" class="btn btn-secondary" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>

Copilot uses AI. Check for mistakes.
</button>
<a href="${getGitHubUrl(
item.path
)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This link opens a new tab (target="_blank") without rel="noopener noreferrer", which allows reverse-tabnabbing. Add rel="noopener noreferrer" to external links opened in a new tab.

Suggested change
)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
)}" class="btn btn-secondary" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>

Copilot uses AI. Check for mistakes.
${getActionButtonsHtml(item.path, true)}
<a href="${getGitHubUrl(
item.path
)}" class="btn btn-secondary btn-small" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This link opens a new tab (target="_blank") without rel="noopener noreferrer", which allows reverse-tabnabbing. Add rel="noopener noreferrer" to external links opened in a new tab.

Suggested change
)}" class="btn btn-secondary btn-small" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">
)}" class="btn btn-secondary btn-small" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()" title="View on GitHub">

Copilot uses AI. Check for mistakes.
Comment on lines 10 to 13
@font-face {
font-family: 'Monaspace Argon NF';
src: url('../fonts/MonaspaceArgonNF-Regular.woff2') format('woff2');
src: url('../../public/fonts/MonaspaceArgonNF-Regular.woff2') format('woff2');
font-weight: 400;
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The font-face URL points into ../../public/..., which won’t resolve correctly once Astro/Vite bundles src/styles/global.css. Since the font lives in website/public/fonts, reference it via an absolute public path (e.g. /fonts/...) instead of a relative path into public.

Copilot uses AI. Check for mistakes.
Comment on lines +769 to +772
.modal-header-top {
gap: 16px;
min-width: 0;
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

.modal-header-top sets gap and sizing but never sets display: flex, so the title/actions won’t be laid out as intended (and gap will have no effect). Add an explicit layout (e.g. display:flex plus alignment/justification) or move these rules back onto .modal-header.

Copilot uses AI. Check for mistakes.
Comment on lines +334 to +340
if (isMarkdownFile(currentFilePath) && currentViewMode === "rendered") {
const container = ensureDivContent("modal-rendered-content");
if (!container) return;

const { body: markdownBody } = fm(currentFileContent);
container.innerHTML = marked(markdownBody, { async: false });
} else {
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

Markdown is rendered with marked(...) and injected via innerHTML without sanitization. Because repo content can include raw HTML, this enables XSS in the modal. Sanitize the generated HTML (e.g. DOMPurify) or configure the renderer to disallow raw HTML before assigning to innerHTML.

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +339
const { body: markdownBody } = fm(currentFileContent);
container.innerHTML = marked(markdownBody, { async: false });
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

fm(currentFileContent) can throw on malformed front matter, and marked(...) can also throw; currently that would reject openFileModal() and leave the modal in a broken state. Wrap front-matter parsing/markdown rendering in a try/catch and fall back to raw/highlighted rendering (or a safe error message) on failure.

Suggested change
const { body: markdownBody } = fm(currentFileContent);
container.innerHTML = marked(markdownBody, { async: false });
try {
const { body: markdownBody } = fm(currentFileContent);
container.innerHTML = marked(markdownBody, { async: false });
} catch (error) {
// If front-matter parsing or markdown rendering fails, fall back to highlighted view
// rather than leaving the modal in a broken state.
// eslint-disable-next-line no-console
console.error(
"Failed to render markdown content, falling back to highlighted view.",
error
);
await renderHighlightedCode(currentFileContent, currentFilePath);
}

Copilot uses AI. Check for mistakes.
Comment on lines 852 to 866
@@ -438,27 +865,12 @@ export async function openFileModal(
return;
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

When opening a plugin modal, the new Render/Raw buttons aren’t hidden/reset. If a user previously opened a markdown file, the plugin modal can still show these controls even though they don’t apply. Consider explicitly hiding the render/raw controls (or calling a shared reset like updateViewButtons() after clearing currentFilePath/currentFileContent) in the plugin branch.

Copilot uses AI. Check for mistakes.
Comment on lines 152 to 158
categoryFilter.innerHTML =
'<option value="">All Categories</option>' +
data.filters.categories
.map(
(c) => `<option value="${escapeHtml(c)}">${escapeHtml(c)}</option>`
(c) => `<option value="${c}">${c}</option>`
)
.join("");
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

Category options are built via innerHTML using values from tools.json without escaping. If a category string contains HTML special characters, this can become an injection vector. Prefer creating <option> elements and setting textContent/value, or escape the strings before concatenating into HTML.

See below for a potential fix:

    // Clear any existing options
    categoryFilter.innerHTML = "";

    // Add default "All Categories" option
   const defaultOption = document.createElement("option");
    defaultOption.value = "";
    defaultOption.textContent = "All Categories";
    categoryFilter.appendChild(defaultOption);

    // Add options for each category
    data.filters.categories.forEach((c) => {
      const option = document.createElement("option");
      option.value = c;
      option.textContent = c;
      categoryFilter.appendChild(option);
    });

Copilot uses AI. Check for mistakes.
</div>
<div class="resource-actions">
${getActionButtonsHtml(item.path)}
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This link opens a new tab (target="_blank") without rel="noopener noreferrer", which allows reverse-tabnabbing. Add rel="noopener noreferrer" to external links opened in a new tab.

Suggested change
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()" title="View on GitHub">GitHub</a>

Copilot uses AI. Check for mistakes.
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