From 926a211bf98ed0df16fb83639957c8fb8647a4f5 Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 5 Dec 2024 18:49:53 +0100 Subject: [PATCH 1/3] build: update API generator --- packages/docs/build/api.mjs | 72 +++++++++++++++++++++++++++++------ packages/docs/gatsby-node.mjs | 2 +- packages/docs/package.json | 3 +- 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/packages/docs/build/api.mjs b/packages/docs/build/api.mjs index e6b6d7be..d0fddefe 100644 --- a/packages/docs/build/api.mjs +++ b/packages/docs/build/api.mjs @@ -7,18 +7,21 @@ import { writeFile, mkdir } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' import { parse } from 'react-docgen-typescript' +import showdown from 'showdown' /** * Derive __dirname in ESM */ const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) +const converter = new showdown.Converter({ simpleLineBreaks: true }) /** * Glob patterns to locate .tsx files for documentation. * Adjust these patterns based on your project structure. */ const GLOB_PATTERNS = [ + // '**/src/components/date-picker/*.tsx', '**/src/**/*.tsx', '../node_modules/@coreui/icons-react/src/**/*.tsx', '../node_modules/@coreui/react-chartjs/src/**/*.tsx', @@ -44,7 +47,6 @@ const EXCLUDED_FILES = [] // Currently unused, but can be utilized if needed * Options for react-docgen-typescript parser. */ const DOCGEN_OPTIONS = { - savePropValueAsString: true, shouldIncludePropTagMap: true, } @@ -52,18 +54,32 @@ const DOCGEN_OPTIONS = { * List of pro components that require special handling. */ const PRO_COMPONENTS = [ + 'CCalendar', 'CDatePicker', 'CDateRangePicker', 'CFormMask', 'CLoadingButton', 'CMultiSelect', 'CRating', + 'CRangeSlider', + 'CRating', 'CSmartPagination', 'CSmartTable', 'CTimePicker', 'CVirtualScroller', ] +const TEXT_REPLACEMENTS = { + CDatePicker: { + description: [{ 'React Calendar': 'React Date Picker' }], + example: [{ CCalendar: 'CDatePicker' }], + }, + CDateRangePicker: { + description: [{ 'React Calendar': 'React Date Range Picker' }], + example: [{ CCalendar: 'CDateRangePicker' }], + }, +} + /** * Escapes special characters in text to prevent Markdown rendering issues. * @@ -72,13 +88,10 @@ const PRO_COMPONENTS = [ */ function escapeMarkdown(text) { if (typeof text !== 'string') return text - return ( - text - .replaceAll(/(<)/g, String.raw`\$1`) - // .replaceAll(//g, '``') - .replaceAll('\n', '
') - .replaceAll(/`([^`]+)`/g, '{`$1`}') - ) + return text + .replaceAll(/(<)/g, String.raw`\$1`) + .replaceAll('\n', '
') + .replaceAll(/`([^`]+)`/g, '{`$1`}') } /** @@ -110,6 +123,10 @@ function getRelativeFilename(file) { * @throws {Error} Throws an error if there are unmatched braces or parentheses in the input. */ function splitOutsideBracesAndParentheses(input) { + if (input.endsWith('...')) { + return [input] + } + const parts = [] let currentPart = '' let braceDepth = 0 // Tracks depth of curly braces {} @@ -172,6 +189,23 @@ function splitOutsideBracesAndParentheses(input) { return parts } +function replaceText(componenName, keyName, text) { + const keyNames = Object.keys(TEXT_REPLACEMENTS) + + if (keyNames.includes(componenName)) { + const replacements = TEXT_REPLACEMENTS[componenName][keyName] + for (const replacement of replacements) { + for (const [key, value] of Object.entries(replacement)) { + if (text && key && value) { + return text.replaceAll(key, value) + } + } + } + } else { + return text + } +} + /** * Creates an MDX file with the component's API documentation. * @@ -190,10 +224,10 @@ async function createMdx(file, component) { let content = `\n\`\`\`jsx\n` const importPathParts = relativeFilename.split('/') if (importPathParts.length > 1) { - content += `import { ${component.displayName} } from '@coreui/${importPathParts[1]}'\n` + content += `import { ${component.displayName} } from '@coreui/${importPathParts[0]}'\n` } content += `// or\n` - content += `import ${component.displayName} from '@coreui${relativeFilename.replace('.tsx', '')}'\n` + content += `import ${component.displayName} from '@coreui/${relativeFilename.replace('.tsx', '')}'\n` content += `\`\`\`\n\n` const sortedProps = Object.entries(component.props).sort(([a], [b]) => a.localeCompare(b)) @@ -240,7 +274,9 @@ async function createMdx(file, component) { const deprecated = propInfo.tags?.deprecated ? `Deprecated ${propInfo.tags.since}` : '' - const description = propInfo.description || '-' + const description = propInfo.description + ? replaceText(component.displayName, 'description', propInfo.description) + : '-' const type = propInfo.type ? propInfo.type.name.includes('ReactElement') @@ -248,6 +284,9 @@ async function createMdx(file, component) { : propInfo.type.name : '' const defaultValue = propInfo.defaultValue ? `\`${propInfo.defaultValue.value}\`` : `undefined` + const example = propInfo.tags?.example + ? replaceText(component.displayName, 'example', propInfo.tags?.example) + : false // Format types as inline code const types = splitOutsideBracesAndParentheses(type) @@ -263,7 +302,16 @@ async function createMdx(file, component) { content += ` ${escapeMarkdown(types)}\n` content += ` \n` content += ` \n` - content += ` ${escapeMarkdown(description)}${propInfo.tags?.example ? `
` : ''}\n` + content += ` \n` + content += ` ${converter + .makeHtml(description) + .replaceAll(/(.*?)<\/code>/g, '{`$1`}')}\n` + + if (example) { + content += ` \n` + } + + content += ` \n` content += ` \n` if (isLast) { diff --git a/packages/docs/gatsby-node.mjs b/packages/docs/gatsby-node.mjs index 9f29a5a7..64d30826 100644 --- a/packages/docs/gatsby-node.mjs +++ b/packages/docs/gatsby-node.mjs @@ -34,7 +34,7 @@ export const createPages = async ({ }) => { const result = await graphql(` query { - allMdx { + allMdx(filter: { fields: { slug: { regex: "/^(?!/api/).*/" } } }) { nodes { id fields { diff --git a/packages/docs/package.json b/packages/docs/package.json index f2be65eb..bd396108 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -60,7 +60,8 @@ "react-imask": "^7.6.1", "react-markdown": "^9.0.1", "rimraf": "^6.0.1", - "sass": "^1.80.4" + "sass": "^1.80.4", + "showdown": "^2.1.0" }, "devDependencies": { "npm-run-all": "^4.1.5" From 3bef1841dfbadf2001c5b4723d413b35c6e039aa Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 5 Dec 2024 18:50:12 +0100 Subject: [PATCH 2/3] docs: update API table style --- packages/docs/src/styles/_table-api.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/docs/src/styles/_table-api.scss b/packages/docs/src/styles/_table-api.scss index 19afef0b..c537fce8 100644 --- a/packages/docs/src/styles/_table-api.scss +++ b/packages/docs/src/styles/_table-api.scss @@ -10,6 +10,10 @@ tr th { padding: 0.75rem 1rem; + + &:nth-child(3) { + width: 50%; + } } tr td { @@ -37,5 +41,10 @@ padding: 0.25rem 1rem; border: 0; border-radius: 0; + border: 2px solid var(--cui-body-bg); + + code[class*=language-], pre[class*=language-] { + white-space: pre-wrap; + } } } From f76c46cc23992f539ac4d8ee105db08aa62e872c Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 5 Dec 2024 18:51:10 +0100 Subject: [PATCH 3/3] feat(CAccordion): allow defining custom class names and overriding existing ones --- .../coreui-react/src/components/accordion/CAccordion.tsx | 6 +++--- .../src/components/accordion/CAccordionBody.tsx | 6 +++--- .../src/components/accordion/CAccordionButton.tsx | 9 +++++++-- .../src/components/accordion/CAccordionHeader.tsx | 8 +++++--- .../src/components/accordion/CAccordionItem.tsx | 8 +++++--- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/coreui-react/src/components/accordion/CAccordion.tsx b/packages/coreui-react/src/components/accordion/CAccordion.tsx index ebc8b37f..5504f915 100644 --- a/packages/coreui-react/src/components/accordion/CAccordion.tsx +++ b/packages/coreui-react/src/components/accordion/CAccordion.tsx @@ -89,7 +89,7 @@ export const CAccordion = forwardRef( ) => { const [_activeItemKey, setActiveKey] = useState(activeItemKey) - const _classNames = mergeClassNames( + const mergedClassNames = mergeClassNames( ACCORDION_CLASS_NAMES, customClassNames, ) @@ -97,8 +97,8 @@ export const CAccordion = forwardRef( return (
( ({ children, className, customClassNames, ...rest }, ref) => { const { id, visible } = useContext(CAccordionItemContext) - const _classNames = mergeClassNames( + const mergedClassNames = mergeClassNames( ACCORDION_BODY_CLASS_NAMES, customClassNames, ) return ( - -
+ +
{children}
diff --git a/packages/coreui-react/src/components/accordion/CAccordionButton.tsx b/packages/coreui-react/src/components/accordion/CAccordionButton.tsx index 2c6eb097..e6bc38a4 100644 --- a/packages/coreui-react/src/components/accordion/CAccordionButton.tsx +++ b/packages/coreui-react/src/components/accordion/CAccordionButton.tsx @@ -36,12 +36,17 @@ export const CLASS_NAMES = { export const CAccordionButton = forwardRef( ({ children, className, customClassNames, ...rest }, ref) => { const { id, visible, setVisible } = useContext(CAccordionItemContext) - const _classNames = mergeClassNames(CLASS_NAMES, customClassNames) + + const mergedClassNames = mergeClassNames(CLASS_NAMES, customClassNames) return (