react-scitext
Version:
React component for rendering scientific text with Markdown, LaTeX, and SMILES support
734 lines (528 loc) • 17.9 kB
Markdown
<div align="center">
# React SciText
[](https://badge.fury.io/js/react-scitext)
[](https://github.com/rsmyst/react-scitext/actions)
[](https://www.typescriptlang.org/)
**A powerful React component library for rendering scientific text with mixed content including Markdown, LaTeX math, and SMILES chemical structures.**
[Storybook](https://react-scitext.netlify.app) • [Examples](#examples) • [Getting Started](#installation)
</div>
---
## Features
- **Unified Content Rendering** - Single component handles mixed content types intelligently
- **Smart Math Detection** - Avoids false positives in LaTeX math rendering with intelligent parsing
- **Chemical Structure Support** - Built-in SMILES notation rendering with validation
- **Full Markdown Support** - GitHub Flavored Markdown with syntax highlighting
- **Advanced LaTeX** - Support for environments, equations, lists, and complex structures
- **Security First** - Input validation, sanitization, and XSS prevention
- **Performance Optimized** - Efficient parsing algorithms with minimal re-renders
- **TypeScript Ready** - Comprehensive type definitions and intellisense
- **Accessibility** - ARIA labels, screen reader support, and keyboard navigation
- **Responsive** - Works seamlessly across devices and screen sizes
<img width="500" alt="S_2476" src="https://github.com/user-attachments/assets/0d8aa2d2-9d5d-45fe-9ee4-d12220cc98b9" />
<img width="500" alt="S_2477" src="https://github.com/user-attachments/assets/13b2264f-e9b5-4f8a-98b2-319ed6f4410e" />
<img width="500" alt="S_2478" src="https://github.com/user-attachments/assets/8a2f96e2-944b-4134-b924-d6e3d866de63" />
<img width="500" alt="S_2479" src="https://github.com/user-attachments/assets/61cda6ab-721c-4d16-95b9-ded00776b717" />
<img width="500" alt="S_2480" src="https://github.com/user-attachments/assets/54741b0a-5eba-44d5-817c-821717460828" />
## Installation
```bash
npm install react-scitext
```
**Important:** This package requires React 16.8.0 or higher. Make sure your `react` and `react-dom` versions match to avoid compatibility issues:
```bash
# Install matching versions of React and React-DOM
npm install react@^18.0.0 react-dom@^18.0.0
# Or if you prefer React 17
npm install react@^17.0.0 react-dom@^17.0.0
```
**Required CSS for LaTeX rendering:**
```bash
npm install katex
```
## Quick Start
```tsx
import { RichText } from "react-scitext";
import "katex/dist/katex.min.css"; // Required for LaTeX rendering
function App() {
const content = `
# Scientific Content Example
Mix **markdown** with math $E = mc^2$ and chemistry:
<smiles>c1ccccc1</smiles>
$$\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}$$
\\begin{itemize}
\\item First item with $\\alpha$
\\item Second item with $\\beta$
\\end{itemize}
`;
return <RichText content={content} />;
}
```
## Content Formatting Guidelines
### Markdown Formatting
The component supports GitHub Flavored Markdown with the following formatting guidelines:
#### Headers
Use standard markdown header syntax with proper spacing:
```markdown
# Main Title
## Section Header
### Subsection Header
#### Sub-subsection Header
```
#### Text Formatting
```markdown
**Bold text** for emphasis
_Italic text_ for subtle emphasis
**_Bold and italic_** for strong emphasis
`inline code` for code snippets
~~Strikethrough~~ for deleted text
```
#### Lists
Use consistent spacing and indentation:
```markdown
- Unordered list item 1
- Unordered list item 2
- Nested item 2.1
- Nested item 2.2
1. Ordered list item 1
2. Ordered list item 2
1. Nested numbered item 2.1
2. Nested numbered item 2.2
```
#### Code Blocks
Use triple backticks with language specification:
````markdown
```javascript
function example() {
return "Hello World";
}
```
````
### LaTeX Math Formatting
The component supports multiple LaTeX delimiter styles with intelligent detection:
#### Inline Math
For mathematical expressions within text:
```latex
$E = mc^2$ # Simple expressions
$\frac{a}{b}$ # Fractions
$\alpha + \beta$ # Greek letters
$x^2 + y^2 = z^2$ # Equations
$\sum_{i=1}^{n} x_i$ # Summations
```
#### Alternative Inline Delimiters
```latex
\(E = mc^2\) # Parentheses style
```
#### Block Math
For standalone mathematical expressions:
```latex
$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$
# Or using bracket style:
\[
\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}
\]
```
#### Complex Equations
```latex
$$
\begin{align}
f(x) &= ax^2 + bx + c \\
f'(x) &= 2ax + b \\
f''(x) &= 2a
\end{align}
$$
```
#### Matrices
```latex
$$
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
$$
```
### LaTeX Environment Formatting
The component supports structured LaTeX environments with proper syntax:
#### Lists
```latex
\begin{itemize}
\item First item
\item Second item with math $x^2$
\item Third item
\end{itemize}
\begin{enumerate}
\item Numbered item 1
\item Numbered item 2
\end{enumerate}
```
#### Description Lists
```latex
\begin{description}
\item[Term 1] Description of term 1
\item[Term 2] Description of term 2
\end{description}
```
#### Equations
```latex
\begin{equation}
E = mc^2
\end{equation}
\begin{equation}
\label{eq:quadratic}
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}
\end{equation}
```
### SMILES Chemical Structure Formatting
Chemical structures use SMILES notation within HTML-like tags:
#### Basic Molecules
```html
<smiles>C</smiles>
<!-- Methane -->
<smiles>O</smiles>
<!-- Water -->
<smiles>CC</smiles>
<!-- Ethane -->
<smiles>CCO</smiles>
<!-- Ethanol -->
```
#### Aromatic Compounds
```html
<smiles>c1ccccc1</smiles>
<!-- Benzene -->
<smiles>c1ccc2ccccc2c1</smiles>
<!-- Naphthalene -->
<smiles>c1ccc(cc1)O</smiles>
<!-- Phenol -->
```
#### Complex Molecules
```html
<!-- Caffeine -->
<smiles>CN1C=NC2=C1C(=O)N(C(=O)N2C)C</smiles>
<!-- Aspirin -->
<smiles>CC(=O)OC1=CC=CC=C1C(=O)O</smiles>
<!-- Glucose -->
<smiles>C([C@@H]1[C@H]([C@@H]([C@H](C(O1)O)O)O)O)O</smiles>
```
#### Formatting Guidelines for SMILES
- Use lowercase letters for aromatic atoms: `c1ccccc1` for benzene
- Use uppercase letters for aliphatic atoms: `CCCC` for butane
- Include stereochemistry when relevant: `[C@@H]` for chiral centers
- Use proper ring closure numbers: `c1ccccc1` not `c1cccc1`
- Validate SMILES strings before use with online tools or the built-in validator
### Mixed Content Best Practices
When combining different content types, follow these guidelines:
#### Spacing and Separation
```markdown
# Title
Regular text with **markdown** formatting.
Mathematical expression: $E = mc^2$
Chemical structure:
<smiles>c1ccccc1</smiles>
Block equation:
$$\int_{0}^{1} x^2 dx = \frac{1}{3}$$
\begin{itemize}
\item List item with math $\alpha$
\item List item with chemistry: <smiles>CCO</smiles>
\end{itemize}
```
#### Escaping Special Characters
When you need to display literal characters that have special meaning:
```markdown
Use \$ for literal dollar signs
Use \\ for literal backslashes
Use \< and \> for literal angle brackets
```
#### Variable Detection
The component intelligently distinguishes between simple variables and complex math:
```latex
# Rendered as bold italics (simple variables):
$x$, $y$, $z$, $F_m$, $k_1$
# Rendered as LaTeX math (complex expressions):
$x^2 + y^2 = z^2$
$\frac{a}{b}$
$\{a, b, c\}$
$\alpha + \beta$
```
#### Content Organization
For optimal rendering, organize content in this order:
1. Headers and titles
2. Explanatory text with inline math
3. Chemical structures
4. Block equations
5. Lists and structured content
## Examples
### Basic Usage
```tsx
import { RichText } from 'react-scitext';
// Simple text with inline math
<RichText content="The quadratic formula is $x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}$" />
// Block math equations
<RichText content="$$\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}$$" />
// Chemical structures
<RichText content="Caffeine structure: <smiles>CN1C=NC2=C1C(=O)N(C(=O)N2C)C</smiles>" />
```
### Advanced Usage
```tsx
import { RichText, Smiles } from "react-scitext";
// Complex mixed content
const scientificContent = `
# Research Results
## Chemical Analysis
The compound **caffeine** has the structure:
<smiles>CN1C=NC2=C1C(=O)N(C(=O)N2C)C</smiles>
## Mathematical Model
The reaction rate follows the equation:
$$k = A \\cdot e^{-\\frac{E_a}{RT}}$$
Where:
- $k$ = rate constant
- $A$ = pre-exponential factor
- $E_a$ = activation energy
- $R$ = gas constant
- $T$ = temperature
\\begin{enumerate}
\\item First observation with $\\alpha = 0.05$
\\item Second observation with $\\beta = 0.95$
\\end{enumerate}
`;
function ResearchPaper() {
return (
<div className="research-paper">
<RichText content={scientificContent} />
</div>
);
}
```
### Inline Rendering
```tsx
// Inline math without prose wrapper
<RichText
content="The value of $\\pi$ is approximately 3.14159"
inline={true}
/>
// Disable markdown processing
<RichText
content="Raw text with $variables$ but no formatting"
renderAsMarkdown={false}
/>
```
### Error Handling
```tsx
import { Smiles } from "react-scitext";
function ChemicalStructure() {
const handleError = (error: unknown) => {
console.error("SMILES rendering failed:", error);
// Custom error handling (e.g., fallback UI, logging)
};
return <Smiles code="c1ccccc1" errorCallback={handleError} />;
}
```
## API Reference
### RichText Component
The main component for rendering mixed scientific content.
```tsx
interface RichTextProps {
content: string;
renderAsMarkdown?: boolean;
inline?: boolean;
}
```
| Prop | Type | Default | Description |
| ------------------ | --------- | ------- | ------------------------------------------------ |
| `content` | `string` | - | The content string to render |
| `renderAsMarkdown` | `boolean` | `true` | Whether to process non-LaTeX content as Markdown |
| `inline` | `boolean` | `false` | Whether to render inline without prose wrapper |
#### Examples
```tsx
// Basic usage
<RichText content="Hello **world** with $x^2$!" />
// Inline rendering
<RichText content="Inline $E = mc^2$" inline={true} />
// Plain text mode
<RichText content="No markdown processing" renderAsMarkdown={false} />
```
### Smiles Component
Dedicated component for chemical structure rendering.
```tsx
interface SmilesProps {
code: string;
errorCallback: (error: unknown) => void;
}
```
| Prop | Type | Description |
| --------------- | -------------------------- | ------------------------------------ |
| `code` | `string` | Valid SMILES notation string |
| `errorCallback` | `(error: unknown) => void` | Function called when rendering fails |
#### Examples
```tsx
// Basic chemical structure
<Smiles
code="CCO"
errorCallback={(err) => console.error(err)}
/>
// Complex molecule
<Smiles
code="CC(=O)OC1=CC=CC=C1C(=O)O"
errorCallback={handleError}
/>
```
### Utility Functions
Advanced utility functions for custom implementations:
```tsx
import {
// LaTeX utilities
splitLatex,
isInlineLatexFragment,
isBlockLatexFragment,
validateLatexInput,
sanitizeLatexContent,
// SMILES utilities
validateSmilesCode,
sanitizeSmilesCode,
extractSmilesCode,
// Markdown utilities
validateMarkdownContent,
sanitizeMarkdownContent,
processMixedContent,
} from "react-scitext";
// Example usage
const isValidSmiles = validateSmilesCode(userInput);
const latexParts = splitLatex(text);
const isInline = isInlineLatexFragment(expression);
```
## Smart Content Detection
The library intelligently distinguishes between different content types:
```tsx
// Mathematical expressions (rendered as LaTeX)
$x^2 + y^2 = z^2$ // Complex expression
$\frac{a}{b}$ // Fractions
$\{a, b, c\}$ // Sets
$\alpha + \beta$ // Greek letters
// Simple variables (rendered as bold italics)
$x$, $y$, $z$ // Single letters
$F_m$, $k_1$ // With subscripts
// Not treated as math (avoids false positives)
"Price is $10" // Dollar amounts
"user$variable" // Variable names
```
## Security Features
Built-in security measures for safe rendering:
- **Input Validation**: All content types are validated before rendering
- **Content Sanitization**: Potentially dangerous content is sanitized
- **XSS Prevention**: Protection against cross-site scripting attacks
- **Size Limits**: Prevents DoS attacks through content size limits
- **Safe Rendering**: Uses safe rendering methods for all content types
## Accessibility Features
Comprehensive accessibility support for inclusive user experiences:
- **ARIA Labels**: Proper labeling for all content types (math, chemistry, headings)
- **Screen Reader Support**: Descriptive text for complex visual content
- **Keyboard Navigation**: Focusable headings with proper tab ordering
- **Error Announcements**: Live regions for error messages
- **Semantic HTML**: Proper heading hierarchy and document structure
- **High Contrast Support**: Respects user's contrast preferences
- **Reduced Motion**: Respects user's motion preferences
- **Focus Management**: Visible focus indicators for keyboard users
### Accessibility Features in Detail
#### Mathematical Content
- Math expressions use `role="math"` with descriptive `aria-label`
- Block math is distinguished from inline math for screen readers
- Complex equations include readable descriptions
#### Chemical Structures
- SMILES diagrams use `role="img"` with chemical structure descriptions
- Hidden text provides SMILES notation for screen readers
- Error states are announced to assistive technologies
#### Document Structure
- Headings include proper `aria-level` attributes
- Automatic ID generation for heading navigation
- Semantic HTML5 structure with `role="article"`
#### Error Handling
- Error messages use `role="alert"` with `aria-live="polite"`
- Validation errors are announced without interrupting workflow
- Visual and programmatic error indicators
To ensure full accessibility compliance, the library includes accessibility specific styling.
## Performance
Optimized for handling large documents with mixed content:
- **Efficient Parsing**: Optimized algorithms for content detection
- **Minimal Re-renders**: React optimization prevents unnecessary updates
- **Memory Efficient**: Optimized memory usage for large documents
- **Bundle Size**: Minimal impact on your application bundle
## Development
### Building from Source
```bash
git clone https://github.com/rsmyst/react-scitext.git
cd react-scitext
npm install
npm run build
```
### Available Scripts
```bash
npm run dev # Start development server
npm run build # Build for production
npm run test # Run tests
npm run test:coverage # Run with coverage report
npm run storybook # Start Storybook
```
### Testing
```bash
npm test # Run all tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Generate coverage report
```
### Storybook
Explore components and examples:
```bash
npm run storybook # Start Storybook dev server
```
## Troubleshooting
### Common Issues
**LaTeX not rendering:**
- Ensure `katex/dist/katex.min.css` is imported
- Check that LaTeX syntax is valid
- Verify content is properly escaped
**SMILES structures not displaying:**
- Validate SMILES notation using `validateSmilesCode`
- Check browser console for errors
- Ensure error callback is properly implemented
## Contributing
We welcome contributions!
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
### Development Guidelines
- Follow the existing code style
- Add tests for new features
- Update documentation as needed
- Use conventional commit messages
## License
This project is licensed under a custom license that allows free use for non-commercial purposes including personal, educational, and research use. Commercial use requires explicit permission from the copyright holder.
**For Non-Commercial Use:**
- ✅ Personal projects
- ✅ Educational purposes
- ✅ Research projects
- ✅ Open source contributions
- ✅ Modifications and improvements
**For Commercial Use:**
- ❌ Requires explicit written permission
- 📧 Contact for commercial licensing
See the [LICENSE](LICENSE) file for complete details.
## Acknowledgments
- [KaTeX](https://katex.org/) for LaTeX math rendering
- [react-markdown](https://github.com/remarkjs/react-markdown) for Markdown processing
- [smiles-drawer](https://github.com/reymond-group/smilesDrawer) for chemical structure rendering
- [Storybook](https://storybook.js.org/) for component documentation
## Changelog
### 1.0.0 (Latest)
- Initial release
- Unified content rendering system
- LaTeX math support with smart detection
- SMILES chemical structure support
- GitHub Flavored Markdown support
- Security features and input validation
- Performance optimizations
- Comprehensive TypeScript support
- Complete test suite and documentation
- Storybook integration with examples
---
<div align="center">
**Made with ❤️ for the scientific community**
[Star us on GitHub](https://github.com/rsmyst/react-scitext) • [View on npm](https://www.npmjs.com/package/react-scitext) • [Report Issues](https://github.com/rsmyst/react-scitext/issues)
</div>