# markdown-tables
A simple Rust library for formatting data as markdown tables.
## Overview
This library provides a trait-based approach to formatting structured data as markdown tables. It handles column alignment, width calculation, and special character escaping automatically.
## Usage
To use this library, implement the `MarkdownTableRow` trait for your data type:
```rust
use markdown_tables::{MarkdownTableRow, as_table};
struct Person {
name: String,
age: u32,
city: String,
}
impl MarkdownTableRow for Person {
fn column_names() -> Vec<&'static str> {
vec!["Name", "Age", "City"]
}
fn column_values(&self) -> Vec<String> {
vec![
self.name.clone(),
self.age.to_string(),
self.city.clone()
]
}
}
// Create some data
let people = vec![
Person {
name: "Alice".to_string(),
age: 30,
city: "New York".to_string(),
},
Person {
name: "Bob".to_string(),
age: 25,
city: "Los Angeles".to_string(),
},
];
// Format as a table
let table = as_table(&people);
println!("{}", table);
```
This will output:
```
| Alice | 30 | New York |
| Bob | 25 | Los Angeles |
```
## Features
- **Automatic column width calculation**: Columns are sized to fit their content
- **Pipe character escaping**: Pipe characters (`|`) in data are automatically escaped
- **Empty table handling**: Empty vectors produce an empty string
- **Unicode support**: Handles Unicode characters (though alignment may not be perfect for wide characters)
## API
### `MarkdownTableRow` trait
Types that implement this trait can be formatted as rows in a markdown table.
- `column_names()` - Returns the names of the columns (used for the header row)
- `column_values(&self)` - Returns the values for this row
### `as_table<T: MarkdownTableRow>(table: &[T]) -> String`
Formats a slice of items as a markdown table. Returns an empty string if the slice is empty.
## Examples
### Basic Usage
```rust
#[derive(Debug)]
struct Product {
id: u32,
name: String,
price: f64,
}
impl MarkdownTableRow for Product {
fn column_names() -> Vec<&'static str> {
vec!["ID", "Product", "Price"]
}
fn column_values(&self) -> Vec<String> {
vec![
self.id.to_string(),
self.name.clone(),
format!("${:.2}", self.price),
]
}
}
```
### Handling Special Characters
Pipe characters in data are automatically escaped:
```rust
let data = vec![
Person {
name: "Alice | Bob".to_string(),
age: 30,
city: "New York | NY".to_string(),
},
];
// Output will have escaped pipes: Alice \| Bob
```
## Limitations
- The library uses character count for width calculation, which may not perfectly align columns containing emoji or other wide Unicode characters
- No support for column alignment options (all columns are left-aligned)
- No support for multi-line cells (newlines are preserved but may break table formatting)