JSDoc theme that provides TypeScript support, component documentation with live previews, and enhanced categorization features
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Live preview system for React and Vue components with automatic prop extraction and interactive examples.
Extracts metadata from React components including props, types, and default values.
/**
* Parses React component and extracts metadata
* @param {string} filePath - Path to the React component file
* @param {Object} doclet - JSDoc doclet containing component information
* @returns {ComponentMetadata} Component metadata with props and display information
*/
function parseReact(filePath: string, doclet: Object): ComponentMetadata;
interface ComponentMetadata {
/** Component display name */
displayName: string;
/** Path to component file */
filePath: string;
/** Component props information */
props: PropInfo[];
/** Component type (react or vue) */
type: 'react' | 'vue';
/** Vue-specific slots (only for Vue components) */
slots?: SlotInfo[];
}
interface PropInfo {
/** Property name */
name: string;
/** Property description from PropTypes or JSDoc */
description?: string;
/** Property type (string, number, boolean, etc.) */
type: string;
/** Whether the property is required */
required: boolean;
/** Default value if specified */
defaultValue?: string;
}Usage Example:
const { parseReact } = require('better-docs/component');
// Document a React component with @component tag
/**
* Button component with customizable styling
* @component
* @example
* return <Button variant="primary" size="large">Click me</Button>
*/
const Button = ({ variant = 'default', size = 'medium', children, onClick }) => {
return (
<button
className={`btn btn-${variant} btn-${size}`}
onClick={onClick}
>
{children}
</button>
);
};
Button.propTypes = {
variant: PropTypes.oneOf(['default', 'primary', 'secondary']),
size: PropTypes.oneOf(['small', 'medium', 'large']),
children: PropTypes.node.isRequired,
onClick: PropTypes.func
};Extracts metadata from Vue components including props, slots, and component options.
/**
* Parses Vue component and extracts metadata
* @param {string} filePath - Path to the Vue component file
* @param {Object} doclet - JSDoc doclet containing component information
* @returns {ComponentMetadata} Component metadata with props, slots, and display information
*/
function parseVue(filePath: string, doclet: Object): ComponentMetadata;
interface SlotInfo {
/** Slot name */
name: string;
/** Slot description */
description?: string;
}Usage Example:
<script>
/**
* Card component with header and footer slots
* @component
* @example
* <Card title="My Card">
* <template #header>Custom Header</template>
* <p>Card content goes here</p>
* <template #footer>Card footer</template>
* </Card>
*/
export default {
name: 'Card',
props: {
title: {
type: String,
required: true,
default: 'Default Title'
},
variant: {
type: String,
default: 'default',
validator: value => ['default', 'primary', 'secondary'].includes(value)
}
}
}
</script>JSDoc event handlers for processing component documentation.
interface ComponentHandlers {
/**
* Processes Vue single-file components before parsing
* @param {Object} e - Parse event
*/
beforeParse(e: ParseEvent): void;
/**
* Processes doclets to handle @component tags
* @param {Object} docletEvent - Doclet event with component information
*/
newDoclet(docletEvent: DocletEvent): void;
}
interface ParseEvent {
filename: string;
source: string;
componentInfo?: ComponentInfo;
}
interface DocletEvent {
doclet: {
tags?: Array<{
title: string;
value?: string;
}>;
component?: ComponentMetadata;
kind?: string;
memberof?: string;
undocumented?: boolean;
};
}
interface ComponentInfo {
displayName: string;
props?: Object;
slots?: Object;
}Provides iframe-based rendering and code editing for React component previews.
/**
* React wrapper component factory for live previews
* @param {Object} props - Component props including example code and unique ID
* @returns {React.Component} Wrapper component instance
*/
function ReactWrapper(props: WrapperProps): React.Component;
interface WrapperProps {
/** Unique identifier for the component instance */
uniqId: string;
/** Example code to render */
example?: string;
}
class Wrapper extends React.Component {
constructor(props: WrapperProps);
/**
* Executes JavaScript code for component rendering
* @param {string} source - JavaScript source code
*/
executeScript(source: string): void;
/**
* Handles code changes in the editor
* @param {string} code - Updated code
*/
handleChange(code: string): void;
/**
* Computes iframe height based on content
*/
computeHeight(): void;
/**
* Toggles code editor visibility
* @param {Event} event - Click event
*/
toggleEditor(event: Event): void;
render(): React.Element;
}Provides component rendering and code editing for Vue component previews.
/**
* Vue wrapper component definition for live previews
*/
interface VueWrapper {
/** Vue component template */
template: string;
/** Component props definition */
props: {
defaultCode: StringConstructor;
};
/** Component data factory */
data(): {
code: string;
userComponent: Object;
isActive: boolean;
};
/** Child components */
components: {
editor: Object;
};
/** Lifecycle and utility methods */
methods: {
toggleEditor(): void;
editorInit(): void;
renderComponent(originalCode?: string): Object;
};
}/**
* Alert component for displaying messages
* @component
* @example <caption>Basic alert</caption>
* return <Alert type="info">This is an informational message</Alert>
*
* @example <caption>Error alert</caption>
* return <Alert type="error">Something went wrong!</Alert>
*
* @example <caption>Custom styling</caption>
* return (
* <Alert
* type="success"
* dismissible={true}
* onDismiss={() => console.log('Alert dismissed')}
* >
* Operation completed successfully!
* </Alert>
* )
*/
const Alert = ({ type, children, dismissible, onDismiss }) => {
return (
<div className={`alert alert-${type}`}>
{children}
{dismissible && (
<button onClick={onDismiss} className="alert-close">×</button>
)}
</div>
);
};
Alert.propTypes = {
type: PropTypes.oneOf(['info', 'success', 'warning', 'error']).isRequired,
children: PropTypes.node.isRequired,
dismissible: PropTypes.bool,
onDismiss: PropTypes.func
};<script>
/**
* Progress bar component
* @component
* @example <caption>Basic progress bar</caption>
* <ProgressBar :value="50" :max="100" />
*
* @example <caption>With custom styling</caption>
* <ProgressBar
* :value="75"
* :max="100"
* color="success"
* :show-percentage="true"
* />
*
* @example <caption>Multiple progress bars</caption>
* {
* template: `
* <div>
* <ProgressBar :value="30" label="CPU Usage" />
* <ProgressBar :value="60" label="Memory Usage" color="warning" />
* <ProgressBar :value="90" label="Disk Usage" color="danger" />
* </div>
* `
* }
*/
export default {
name: 'ProgressBar',
props: {
value: {
type: Number,
required: true
},
max: {
type: Number,
default: 100
},
color: {
type: String,
default: 'primary',
validator: value => ['primary', 'success', 'warning', 'danger'].includes(value)
},
showPercentage: {
type: Boolean,
default: false
},
label: {
type: String
}
}
}
</script>You can use multiple documented components together in examples:
/**
* Modal dialog component
* @component
* @example <caption>Modal with alert inside</caption>
* return (
* <Modal isOpen={true} title="Confirm Action">
* <Alert type="warning">
* Are you sure you want to delete this item?
* </Alert>
* <Button variant="danger">Delete</Button>
* <Button variant="secondary">Cancel</Button>
* </Modal>
* )
*/
const Modal = ({ isOpen, title, children, onClose }) => {
if (!isOpen) return null;
return (
<div className="modal-overlay">
<div className="modal">
<div className="modal-header">
<h3>{title}</h3>
<button onClick={onClose}>×</button>
</div>
<div className="modal-body">
{children}
</div>
</div>
</div>
);
};Enable component documentation in JSDoc configuration:
{
"tags": {
"allowUnknownTags": ["component"]
},
"plugins": [
"node_modules/better-docs/component"
],
"templates": {
"better-docs": {
"component": {
"wrapper": "./path/to/wrapper-component.js",
"entry": [
"import 'babel-polyfill';",
"import 'bulma/css/bulma.css';"
]
}
}
}
}For React components that need specific context (Redux, Router, etc.):
// wrapper-component.js
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';
const WrapperComponent = ({ children }) => {
return (
<Provider store={store}>
<BrowserRouter>
<div className="component-preview">
{children}
</div>
</BrowserRouter>
</Provider>
);
};
export default WrapperComponent;The component plugin requires: