Canvas manifest implementation for extensions (#2029)

* Add keyword display to extension cards on website

- Add .resource-keywords and .keyword-tag CSS styles for rendering keyword badges
- Update renderExtensionsHtml() to display keywords below extension description
- Keywords now visible on the website extensions page with styled badges
- Regenerate website data to include keyword metadata

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Canvas manifest implementation for all extensions

Add per-extension canvas manifests with:
- Structured canvas metadata (name, description, version, keywords)
- Screenshot definitions (icon and gallery with path/type)
- Relative paths for images within each extension directory

Enhance extension metadata:
- Generate meaningful descriptions from source analysis
- Extract and assign keywords for discoverability
- Store metadata in package.json and extension source files

Update website rendering and data generation:
- Include keywords in extension cards and search index
- Add per-extension canvas.json files for independent evolution
- Support screenshot metadata in manifest structure
- Generate extensions.json with full canonical paths for website

All 9 local canvas extensions now have complete manifests with descriptions, keywords, and screenshot references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Tweaking some descriptions

* Fix description priority to prefer package.json over in-source metadata

Reverse the priority in canvasDescription so that package.json descriptions
(which contain the enhanced, manually-curated descriptions) take precedence
over older in-source descriptions extracted from createCanvas(...) calls.

This prevents regression when npm run website:data regenerates outputs,
ensuring that committed canvas.json files maintain the current descriptions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix canvas validation to skip external.json file

The validation script was treating extensions/external.json as if it were
a directory, causing false validation failures. Added check to skip files
(identified by presence of dot in filename) and only validate actual
canvas extension directories.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-06-17 15:28:15 +10:00
committed by GitHub
parent 37cfa33ef4
commit 17b174fb0a
29 changed files with 923 additions and 89 deletions
@@ -2,11 +2,26 @@ import { escapeHtml, getGitHubUrl, getLastUpdatedHtml } from "../utils";
export interface RenderableExtension {
id: string;
canvasId?: string;
extensionId?: string;
extensionName?: string;
name: string;
path?: string | null;
ref?: string | null;
version?: string | null;
description?: string;
lastUpdated?: string | null;
keywords?: string[];
screenshots?: {
icon?: {
path?: string | null;
type?: string | null;
} | null;
gallery?: {
path?: string | null;
type?: string | null;
} | null;
} | null;
imageUrl?: string | null;
assetPath?: string | null;
installUrl?: string | null;
@@ -69,6 +84,18 @@ export function renderExtensionsHtml(items: RenderableExtension[]): string {
<div class="resource-description">${escapeHtml(
item.description || "Canvas extension"
)}</div>
<div class="resource-keywords">
${
item.keywords && item.keywords.length > 0
? item.keywords
.map(
(kw) =>
`<span class="keyword-tag">${escapeHtml(kw)}</span>`
)
.join("")
: ""
}
</div>
<div class="resource-meta">
${
item.external