A React component for rendering TAML (Terminal ANSI Markup Language) as styled JSX elements.
TAML (Terminal ANSI Markup Language) is a lightweight markup language for styling terminal output with ANSI escape codes. For the complete specification, visit the TAML Specification Repository.
graph TD
B["@taml/parser"] --> A["@taml/ast"]
C["@taml/react"] --> A
C --> B
D["@taml/docusaurus"] --> C
F["@taml/cli"] --> E["@taml/encoder"]
E -.-> A
E -.-> B
style C fill:#e1f5fe,stroke:#01579b,stroke-width:2px
- @taml/ast - Foundation package providing AST node types, visitor patterns, and tree traversal utilities for TAML documents.
- @taml/parser - Robust parser that converts TAML markup strings into typed AST nodes with comprehensive error handling and validation.
- @taml/encoder - Converts raw ANSI escape sequences into clean TAML markup for further processing and manipulation.
- @taml/cli - Command-line tool for converting ANSI escape sequences to TAML format in batch operations.
- @taml/react - React component that renders TAML markup as styled JSX elements with full TypeScript support and performance optimization.
- @taml/docusaurus - Docusaurus theme that automatically detects and renders TAML code blocks in documentation sites.
- ๐จ Complete TAML Support: Renders all 37 TAML tags (colors, backgrounds, text styles)
- โก Performance Optimized: Built-in memoization and efficient rendering
- ๐ง TypeScript Ready: Full type safety with comprehensive TypeScript definitions
- ๐ฏ Zero Dependencies: Only requires React as a peer dependency
- ๐งช Well Tested: Comprehensive test suite with high coverage
- ๐ฆ Tree Shakable: Optimized for modern bundlers
- ๐ญ CSS Classes: Uses semantic CSS classes for easy customization
npm install @taml/reactyarn add @taml/reactpnpm add @taml/reactbun add @taml/reactThis package includes TypeScript declarations out of the box. No additional setup is required for TypeScript projects.
// ESM
import { Taml } from "@taml/react";
// CommonJS
const { Taml } = require("@taml/react");import { Taml } from '@taml/react';
import '@taml/react/styles.css';
function App() {
return (
<div>
<Taml>{"<red>Error:</red> Something went wrong"}</Taml>
<Taml>{"<green>Success:</green> Operation completed"}</Taml>
<Taml>{"<bold><blue>Info:</blue></bold> Additional details"}</Taml>
</div>
);
}Important: The <Taml> component expects TAML markup as a string, not JSX elements.
<Taml>{"<red>Error:</red> Something went wrong"}</Taml>
<Taml>{"<bold><green>Success!</green></bold>"}</Taml><Taml><red>Error:</red> Something went wrong</Taml>
<Taml><bold><green>Success!</green></bold></Taml>The TAML tags like <red>, <bold>, etc. are markup syntax that gets parsed from the string, not React components.
The main component for rendering TAML markup.
| Prop | Type | Default | Description |
|---|---|---|---|
children |
string |
required | TAML markup string to parse and render |
className |
string |
undefined |
Additional CSS classes to apply to the root element |
onError |
(error: Error) => void |
undefined |
Callback function called when parsing fails |
fallback |
ReactNode |
undefined |
Fallback content to display when parsing fails |
<Taml
className="terminal-output"
onError={(error) => console.error('TAML Error:', error)}
fallback={<span>Invalid TAML</span>}
>
{"<red>Error message</red>"}
</Taml><black>,<red>,<green>,<yellow><blue>,<magenta>,<cyan>,<white>
<brightBlack>,<brightRed>,<brightGreen>,<brightYellow><brightBlue>,<brightMagenta>,<brightCyan>,<brightWhite>
- Standard:
<bgBlack>,<bgRed>,<bgGreen>, etc. - Bright:
<bgBrightBlack>,<bgBrightRed>,<bgBrightGreen>, etc.
<bold>,<dim>,<italic>,<underline>,<strikethrough>
Each TAML tag is rendered as a <span> element with corresponding CSS classes:
- Root wrapper:
.taml - Colors:
.taml-red,.taml-green,.taml-blue, etc. - Bright colors:
.taml-bright-red,.taml-bright-green, etc. - Backgrounds:
.taml-bg-red,.taml-bg-green, etc. - Bright backgrounds:
.taml-bg-bright-red,.taml-bg-bright-green, etc. - Text styles:
.taml-bold,.taml-italic,.taml-underline, etc.
import { Taml } from '@taml/react';
import '@taml/react/styles.css';
// Simple colored text
<Taml>{"<red>Error:</red> File not found"}</Taml>
// Nested formatting
<Taml>{"<bold><red>Critical:</red></bold> System failure"}</Taml>
// Background colors
<Taml>{"<bgYellow><black> WARNING </black></bgYellow>"}</Taml>function LogViewer({ logs }) {
return (
<div className="log-container">
{logs.map((entry, index) => (
<div key={index}>
<Taml>{entry}</Taml>
</div>
))}
</div>
);
}
// Usage
const logs = [
"<dim>2024-12-07 10:30:15</dim> <blue>[INFO]</blue> Application started",
"<dim>2024-12-07 10:30:16</dim> <green>[SUCCESS]</green> Database connected",
"<dim>2024-12-07 10:30:45</dim> <yellow>[WARN]</yellow> High memory usage",
"<dim>2024-12-07 10:31:02</dim> <red>[ERROR]</red> Connection failed",
];function TerminalOutput() {
return (
<div className="terminal">
<Taml>{"<green>user@computer</green>:<blue>~/project</blue>$ npm test"}</Taml>
<br />
<Taml>{"<bold><blue>Running tests...</blue></bold>"}</Taml>
<br />
<Taml>{"<green>โ</green> All tests passed"}</Taml>
</div>
);
}function SafeTamlRenderer({ content }) {
const handleError = (error) => {
console.error('Failed to parse TAML:', error.message);
};
return (
<Taml
onError={handleError}
fallback={<span className="error">Invalid TAML content</span>}
>
{content}
</Taml>
);
}The package includes default CSS styles that map TAML tags to appropriate colors and formatting. Import the stylesheet:
import '@taml/react/styles.css';You can override the default styles or add your own:
/* Override default colors */
.taml-red {
color: #ff4444;
}
/* Add custom terminal styling */
.terminal .taml {
font-family: 'Courier New', monospace;
background: #1e1e1e;
color: #ffffff;
padding: 1rem;
border-radius: 4px;
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
.taml-white {
color: #ffffff;
}
.taml-black {
color: #808080;
}
}For dynamic theming, you can use CSS custom properties:
.taml {
--taml-red: #ff0000;
--taml-green: #00ff00;
--taml-blue: #0000ff;
}
.taml-red {
color: var(--taml-red);
}The package exports utility functions for advanced use cases:
import {
generateClassName,
combineClassNames,
renderTamlNode
} from '@taml/react';
import { parseAml } from '@taml/parser';
// Generate CSS class name from TAML tag
const className = generateClassName('brightRed'); // 'taml-bright-red'
// Combine multiple class names
const combined = combineClassNames('taml', 'custom', undefined); // 'taml custom'
// Parse TAML to AST (import from @taml/parser)
const ast = parseAml('<red>Hello</red>');
// Render AST node to React element
const element = renderTamlNode(ast);The component includes built-in performance optimizations:
- Memoization: Parsed results are cached for identical input strings
- Efficient rendering: Minimal React element creation
- Tree shaking: Only import what you need
import { clearRenderCache, getCacheStats } from '@taml/react';
// Clear the render cache if needed
clearRenderCache();
// Get cache statistics
const stats = getCacheStats();
console.log(`Cache size: ${stats.size}/${stats.maxSize}`);Full TypeScript support with comprehensive type definitions:
import type { TamlProps, TamlTag } from '@taml/react';
import type { TamlNode } from '@taml/ast';
// Component props are fully typed - children MUST be a string
const props: TamlProps = {
children: "<red>Error</red>", // โ
String literal
className: 'custom',
onError: (error: Error) => console.error(error),
fallback: <span>Fallback</span>
};
// This would cause a TypeScript error:
// const invalidProps: TamlProps = {
// children: <red>Error</red>, // โ JSX element - TypeScript error
// };
// TAML tags are type-checked
const validTag: TamlTag = 'red'; // โ
const invalidTag: TamlTag = 'purple'; // โ TypeScript error
// AST node types are imported from @taml/ast
const node: TamlNode = { /* ... */ };// โ Wrong - This treats <red> as a JSX component
<Taml><red>Error</red></Taml>
// โ
Correct - This treats <red> as TAML markup
<Taml>{"<red>Error</red>"}</Taml>// โ Wrong - This passes the literal string "<red>Error</red>"
<Taml>"<red>Error</red>"</Taml>
// โ
Correct - This passes the string content to be parsed
<Taml>{"<red>Error</red>"}</Taml>// โ Wrong - Mixing TAML strings with JSX elements
<Taml>{"<red>Error:</red>"} <span>Additional info</span></Taml>
// โ
Correct - Keep TAML content as pure strings
<Taml>{"<red>Error:</red> Additional info"}</Taml>
// Or use separate elements:
<div>
<Taml>{"<red>Error:</red>"}</Taml>
<span> Additional info</span>
</div>- Modern browsers with ES2022 support
- React 16.8+ (hooks support required)
- TypeScript 5.0+ (for TypeScript users)
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/suin/taml-react.git
cd taml-react
# Install dependencies
bun install
# Run tests
bun test
# Build the project
bun run build
# Lint and format
bun run lint
bun run formatThe project uses Bun for testing with comprehensive test coverage:
# Run all tests
bun test
# Run tests in watch mode
bun test --watch
# Run specific test file
bun test Taml.test.tsxMIT License - see LICENSE file for details.
Part of the TAML ecosystem - Visit the TAML Specification for more information about the Terminal ANSI Markup Language.