diff --git a/src/pages/api/[version]/[section]/[page]/props.ts b/src/pages/api/[version]/[section]/[page]/props.ts
new file mode 100644
index 0000000..53adaf7
--- /dev/null
+++ b/src/pages/api/[version]/[section]/[page]/props.ts
@@ -0,0 +1,49 @@
+import type { APIRoute } from 'astro'
+import { createJsonResponse } from '../../../../../utils/apiHelpers'
+import { getConfig } from '../../../../../../cli/getConfig'
+import { join } from 'node:path'
+import { readFileSync } from 'node:fs'
+import { sentenceCase } from '../../../../../utils/case'
+
+export const prerender = false
+
+export const GET: APIRoute = async ({ params }) => {
+ const { version, section, page } = params
+
+ if (!version || !section || !page) {
+ return createJsonResponse(
+ { error: 'Version, section, and page parameters are required' },
+ 400,
+ )
+ }
+
+ try {
+ const config = await getConfig(`${process.cwd()}/pf-docs.config.mjs`)
+ const outputDir = config?.outputDir || join(process.cwd(), 'dist')
+
+ const propsFilePath = join(outputDir, 'props.json')
+ const propsDataFile = readFileSync(propsFilePath)
+ const props = JSON.parse(propsDataFile.toString())
+
+ const propsData = props[sentenceCase(page)]
+
+ if(propsData === undefined) {
+ return createJsonResponse(
+ { error: `Props data for ${page} not found` },
+ 404,
+ )
+ }
+
+ return createJsonResponse(propsData)
+
+ } catch (error) {
+ const details = error instanceof Error ? error.message : String(error)
+ return createJsonResponse(
+ { error: 'Props data not found', details },
+ 500,
+ )
+ }
+}
+
+
+
diff --git a/src/pages/api/[version]/[section]/names.ts b/src/pages/api/[version]/[section]/names.ts
new file mode 100644
index 0000000..9558119
--- /dev/null
+++ b/src/pages/api/[version]/[section]/names.ts
@@ -0,0 +1,41 @@
+import type { APIRoute } from 'astro'
+import { createJsonResponse } from '../../../../utils/apiHelpers'
+import { getConfig } from '../../../../../cli/getConfig'
+import { join } from 'node:path'
+import { readFileSync } from 'node:fs'
+
+export const prerender = false
+
+export const GET: APIRoute = async ({ params }) => {
+ const { version, section } = params
+
+ if (!version || !section) {
+ return createJsonResponse(
+ { error: 'Version and section parameters are required' },
+ 400,
+ )
+ }
+
+ try {
+ const config = await getConfig(`${process.cwd()}/pf-docs.config.mjs`)
+ const outputDir = config?.outputDir || join(process.cwd(), 'dist')
+
+ const propsFilePath = join(outputDir, 'props.json')
+ const propsDataFile = readFileSync(propsFilePath)
+ const props = JSON.parse(propsDataFile.toString())
+
+ const propsKey = new RegExp("Props", 'i'); // ignore ComponentProps objects
+ const names = Object.keys(props).filter(name => !propsKey.test(name))
+
+ return createJsonResponse(names)
+ } catch (error) {
+ const details = error instanceof Error ? error.message : String(error)
+ return createJsonResponse(
+ { error: 'Component names data not found', details },
+ 500,
+ )
+ }
+}
+
+
+
diff --git a/src/pages/api/index.ts b/src/pages/api/index.ts
index cead58f..cdd59c4 100644
--- a/src/pages/api/index.ts
+++ b/src/pages/api/index.ts
@@ -98,6 +98,36 @@ export const GET: APIRoute = async () =>
example: ['alert', 'button', 'card'],
},
},
+ {
+ path: '/api/{version}/{section}/names',
+ method: 'GET',
+ description: 'Get component names that have props data',
+ parameters: [
+ {
+ name: 'version',
+ in: 'path',
+ required: true,
+ type: 'string',
+ example: 'v6',
+ },
+ {
+ name: 'section',
+ in: 'path',
+ required: true,
+ type: 'string',
+ example: 'components',
+ }
+ ],
+ returns: {
+ type: 'array',
+ items: 'string',
+ description: 'All component names with props data',
+ example: [
+ 'Alert',
+ 'AlertGroup'
+ ],
+ },
+ },
{
path: '/api/{version}/{section}/{page}',
method: 'GET',
@@ -132,6 +162,46 @@ export const GET: APIRoute = async () =>
example: ['react', 'react-demos', 'html'],
},
},
+ {
+ path: '/api/{version}/{section}/{page}/props',
+ method: 'GET',
+ description: 'Get props for a specific component',
+ parameters: [
+ {
+ name: 'version',
+ in: 'path',
+ required: true,
+ type: 'string',
+ example: 'v6',
+ },
+ {
+ name: 'section',
+ in: 'path',
+ required: true,
+ type: 'string',
+ example: 'components',
+ },
+ {
+ name: 'page',
+ in: 'path',
+ required: true,
+ type: 'string',
+ example: 'alert',
+ },
+ ],
+ returns: {
+ type: 'array',
+ items: 'object',
+ description: 'Props for a specific component',
+ example: [
+ {
+ name: 'actionClose',
+ type: 'React.ReactNode',
+ description: 'Close button; use the alert action close button component.',
+ },
+ ],
+ },
+ },
{
path: '/api/{version}/{section}/{page}/{tab}',
method: 'GET',
diff --git a/src/pages/api/openapi.json.ts b/src/pages/api/openapi.json.ts
index 0262f0d..babd078 100644
--- a/src/pages/api/openapi.json.ts
+++ b/src/pages/api/openapi.json.ts
@@ -23,7 +23,7 @@ export const GET: APIRoute = async ({ url }) => {
const details = error instanceof Error ? error.message : String(error)
return createJsonResponse(
{ error: 'Failed to load API index', details },
- 500
+ 500,
)
}
@@ -103,7 +103,8 @@ export const GET: APIRoute = async ({ url }) => {
'/openapi.json': {
get: {
summary: 'Get OpenAPI specification',
- description: 'Returns the complete OpenAPI 3.0 specification for this API',
+ description:
+ 'Returns the complete OpenAPI 3.0 specification for this API',
operationId: 'getOpenApiSpec',
responses: {
'200': {
@@ -234,6 +235,70 @@ export const GET: APIRoute = async ({ url }) => {
},
},
},
+ '/{version}/{section}/names': {
+ get: {
+ summary: 'Get component names',
+ description: 'Returns the component names that have props data',
+ operationId: 'getNames',
+ parameters: [
+ {
+ name: 'version',
+ in: 'path',
+ required: true,
+ description: 'Documentation version',
+ schema: {
+ type: 'string',
+ enum: versions,
+ },
+ example: 'v6',
+ },
+ {
+ name: 'section',
+ in: 'path',
+ required: true,
+ description: 'Documentation section',
+ schema: {
+ type: 'string',
+ },
+ example: 'components',
+ },
+ ],
+ responses: {
+ '200': {
+ description: 'Component names with props data',
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'array',
+ items: {
+ type: 'string'
+ },
+ },
+ example: [
+ 'Alert',
+ 'AlertGroup'
+ ],
+ },
+ },
+ },
+ '404': {
+ description: 'Props not found',
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ properties: {
+ error: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
'/{version}/{section}/{page}': {
get: {
summary: 'List tabs for a page',
@@ -306,6 +371,102 @@ export const GET: APIRoute = async ({ url }) => {
},
},
},
+ '/{version}/{section}/{page}/props': {
+ get: {
+ summary: 'Get component props',
+ description: 'Returns the props for the specified component',
+ operationId: 'getProps',
+ parameters: [
+ {
+ name: 'version',
+ in: 'path',
+ required: true,
+ description: 'Documentation version',
+ schema: {
+ type: 'string',
+ enum: versions,
+ },
+ example: 'v6',
+ },
+ {
+ name: 'section',
+ in: 'path',
+ required: true,
+ description: 'Documentation section',
+ schema: {
+ type: 'string',
+ },
+ example: 'components',
+ },
+ {
+ name: 'page',
+ in: 'path',
+ required: true,
+ description: 'Page ID (kebab-cased)',
+ schema: {
+ type: 'string',
+ },
+ example: 'alert',
+ },
+ ],
+ responses: {
+ '200': {
+ description: 'Props for the specified component',
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ name: { type: 'string' },
+ type: { type: 'string' },
+ description: { type: 'string' },
+ defaultValue: { type: 'string' },
+ },
+ },
+ },
+ example: [
+ {
+ name: 'actionClose',
+ type: 'React.ReactNode',
+ description:
+ 'Close button; use the alert action close button component.',
+ },
+ {
+ name: 'actionLinks',
+ type: 'React.ReactNode',
+ description:
+ 'Action links; use a single alert action link component or multiple wrapped in an array\nor React fragment.',
+ },
+ {
+ name: 'children',
+ type: 'React.ReactNode',
+ description: 'Content rendered inside the alert.',
+ defaultValue: "''",
+ },
+ ],
+ },
+ },
+ },
+ '404': {
+ description: 'Props not found',
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ properties: {
+ error: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
'/{version}/{section}/{page}/{tab}': {
get: {
summary: 'Validate and redirect to text endpoint',
@@ -357,7 +518,8 @@ export const GET: APIRoute = async ({ url }) => {
],
responses: {
'302': {
- description: 'Redirects to /{version}/{section}/{page}/{tab}/text',
+ description:
+ 'Redirects to /{version}/{section}/{page}/{tab}/text',
},
'404': {
description: 'Tab not found',
@@ -554,8 +716,7 @@ export const GET: APIRoute = async ({ url }) => {
'/{version}/{section}/{page}/{tab}/examples/{example}': {
get: {
summary: 'Get example code',
- description:
- 'Returns the raw source code for a specific example',
+ description: 'Returns the raw source code for a specific example',
operationId: 'getExampleCode',
parameters: [
{
@@ -619,7 +780,7 @@ export const GET: APIRoute = async ({ url }) => {
type: 'string',
},
example:
- 'import React from \'react\';\nimport { Alert } from \'@patternfly/react-core\';\n\nexport const AlertBasic = () => ;',
+ "import React from 'react';\nimport { Alert } from '@patternfly/react-core';\n\nexport const AlertBasic = () => ;",
},
},
},