diff --git a/astro.config.mjs b/astro.config.mjs
index 7d5c233..21521de 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -11,7 +11,7 @@ export default defineConfig({
vite: {
ssr: {
noExternal: ["@patternfly/*", "react-dropzone"],
- external: ["node:fs", "node:path", "fs/promises", "path"]
+ external: ["fs", "node:fs", "node:path", "path", "fs/promises"]
},
server: {
fs: {
@@ -19,5 +19,7 @@ export default defineConfig({
}
},
},
- adapter: cloudflare()
+ adapter: cloudflare({
+ imageService: 'compile'
+ })
});
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index eb6c533..cd74b9a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,7 +20,7 @@
"@patternfly/react-code-editor": "^6.2.2",
"@patternfly/react-core": "^6.0.0",
"@patternfly/react-drag-drop": "^6.0.0",
- "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-icons": "6.5.0-prerelease.13",
"@patternfly/react-styles": "^6.0.0",
"@patternfly/react-table": "^6.0.0",
"@patternfly/react-tokens": "^6.0.0",
@@ -35,6 +35,7 @@
"react-docgen": "^7.1.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^6.0.0",
+ "react-icons": "^5.5.0",
"sass": "^1.90.0",
"typescript": "^5.9.2"
},
@@ -4084,6 +4085,16 @@
"react-dom": "^17 || ^18"
}
},
+ "node_modules/@patternfly/react-code-editor/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-component-groups": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-6.4.0.tgz",
@@ -4103,6 +4114,17 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-component-groups/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-core": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.4.0.tgz",
@@ -4121,6 +4143,16 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-core/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-data-view": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-data-view/-/react-data-view-6.4.0.tgz",
@@ -4140,6 +4172,17 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-data-view/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-drag-drop": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@patternfly/react-drag-drop/-/react-drag-drop-6.2.2.tgz",
@@ -4159,7 +4202,7 @@
"react-dom": "^17 || ^18"
}
},
- "node_modules/@patternfly/react-icons": {
+ "node_modules/@patternfly/react-drag-drop/node_modules/@patternfly/react-icons": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
"integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
@@ -4169,6 +4212,16 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-icons": {
+ "version": "6.5.0-prerelease.13",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.5.0-prerelease.13.tgz",
+ "integrity": "sha512-40eSxfFytIAQkQ9EM6K4rqdDHIL9AwivqUbsYHZqJPNoipkL8RukxegPr7Lzvwt9kZ6OWGmTPtGySd4BkXzAqg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-styles": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-6.4.0.tgz",
@@ -4193,6 +4246,16 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-table/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@patternfly/react-tokens": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-6.4.0.tgz",
@@ -4214,6 +4277,17 @@
"react-dom": "^17 || ^18 || ^19"
}
},
+ "node_modules/@patternfly/react-user-feedback/node_modules/@patternfly/react-icons": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.4.0.tgz",
+ "integrity": "sha512-SPjzatm73NUYv/BL6A/cjRA5sFQ15NkiyPAcT8gmklI7HY+ptd6/eg49uBDFmxTQcSwbb5ISW/R6wwCQBY2M+Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ }
+ },
"node_modules/@pkgr/core": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
@@ -21902,6 +21976,15 @@
"react": ">=16.13.1"
}
},
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
diff --git a/package.json b/package.json
index cf3fc79..9b695c5 100644
--- a/package.json
+++ b/package.json
@@ -55,14 +55,14 @@
"@nanostores/react": "^0.8.4",
"@patternfly/ast-helpers": "1.4.0-alpha.190",
"@patternfly/patternfly": "^6.0.0",
+ "@patternfly/quickstarts": "^6.0.0",
"@patternfly/react-code-editor": "^6.2.2",
"@patternfly/react-core": "^6.0.0",
"@patternfly/react-drag-drop": "^6.0.0",
- "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-icons": "6.5.0-prerelease.13",
"@patternfly/react-styles": "^6.0.0",
"@patternfly/react-table": "^6.0.0",
"@patternfly/react-tokens": "^6.0.0",
- "@patternfly/quickstarts": "^6.0.0",
"@types/react": "^18.3.23",
"@types/react-dom": "^18.3.7",
"astro": "^5.15.9",
@@ -74,6 +74,7 @@
"react-docgen": "^7.1.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^6.0.0",
+ "react-icons": "^5.5.0",
"sass": "^1.90.0",
"typescript": "^5.9.2"
},
@@ -82,6 +83,8 @@
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.26.0",
"@eslint/js": "^9.16.0",
+ "@patternfly/react-data-view": "^6.0.0",
+ "@patternfly/react-user-feedback": "^6.0.0",
"@semantic-release/git": "^10.0.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.1.0",
@@ -110,9 +113,7 @@
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript-eslint": "^8.15.0",
- "wrangler": "^4.20.0",
- "@patternfly/react-user-feedback": "^6.0.0",
- "@patternfly/react-data-view": "^6.0.0"
+ "wrangler": "^4.20.0"
},
"config": {
"commitizen": {
diff --git a/src/__tests__/pages/api/__tests__/[version]/icons/[iconName].test.ts b/src/__tests__/pages/api/__tests__/[version]/icons/[iconName].test.ts
new file mode 100644
index 0000000..c9c2840
--- /dev/null
+++ b/src/__tests__/pages/api/__tests__/[version]/icons/[iconName].test.ts
@@ -0,0 +1,176 @@
+import { GET } from '../../../../../../pages/api/[version]/icons/[iconName]'
+
+const mockApiIndex = {
+ versions: ['v5', 'v6'],
+ sections: {},
+ pages: {},
+ tabs: {},
+}
+
+const mockSvg = ''
+
+const mockIconSvgs: Record> = {
+ pf: { CircleIcon: mockSvg },
+}
+
+const mockIconsIndex = {
+ icons: [
+ { name: 'circle', reactName: 'CircleIcon', usage: '' },
+ ],
+}
+
+function createFetchMock(): typeof fetch {
+ return jest.fn((input: RequestInfo | URL) => {
+ const url = typeof input === 'string' ? input : input.toString()
+ if (url.includes('/iconsIndex.json')) {
+ return Promise.resolve({
+ ok: true,
+ json: () => Promise.resolve(mockIconsIndex),
+ } as Response)
+ }
+ const match = url.match(/\/api\/[^/]+\/icons\/([^/]+)\.json/)
+ if (match) {
+ const setId = match[1]
+ const svgs = mockIconSvgs[setId] ?? {}
+ return Promise.resolve({
+ ok: true,
+ json: () => Promise.resolve(svgs),
+ } as Response)
+ }
+ return Promise.resolve({
+ ok: true,
+ json: () => Promise.resolve(mockApiIndex),
+ } as Response)
+ }) as typeof fetch
+}
+
+it('returns SVG markup for valid icon', async () => {
+ global.fetch = createFetchMock()
+
+ const response = await GET({
+ params: { version: 'v6', iconName: 'CircleIcon' },
+ url: new URL('http://localhost:4321/api/v6/icons/CircleIcon'),
+ } as any)
+ const body = await response.text()
+
+ expect(response.status).toBe(200)
+ expect(response.headers.get('Content-Type')).toBe(
+ 'image/svg+xml; charset=utf-8',
+ )
+ expect(body).toBe(mockSvg)
+ expect(body).toContain('