# CommonMarkWriter
The `CommonMarkWriter` is responsible for serializing AST nodes to CommonMark-compliant text. It's the main component that transforms your abstract syntax tree into readable Markdown.
## Creating a Writer
There are several ways to create a `CommonMarkWriter`:
```rust
use cmark_writer::writer::CommonMarkWriter;
use cmark_writer::options::WriterOptions;
// Default writer with standard options
let writer = CommonMarkWriter::new();
// Writer with custom options
let options = WriterOptions::builder()
.soft_break("\n")
.hard_break(" \n")
.build();
let writer = CommonMarkWriter::with_options(options);
```
## Basic Usage
The basic workflow for using a writer involves:
1. Creating a writer instance
2. Writing nodes to it
3. Extracting the resulting Markdown string
```rust
use cmark_writer::{Node, CommonMarkWriter};
// Create document
let document = Node::Document(vec![
Node::heading(1, vec![Node::Text("Hello".to_string())]),
Node::Paragraph(vec![Node::Text("World".to_string())])
]);
// Write document to CommonMarkWriter
let mut writer = CommonMarkWriter::new();
writer.write(&document).expect("Failed to write document");
// Get resulting Markdown as a string
let markdown = writer.into_string();
println!("{}", markdown);
// Output:
// # Hello
//
// World
```
## Writing Methods
### Writing Nodes
```rust
use cmark_writer::{Node, CommonMarkWriter};
let mut writer = CommonMarkWriter::new();
// Write a single node
let paragraph = Node::Paragraph(vec![Node::Text("Hello world".to_string())]);
writer.write(¶graph).expect("Failed to write paragraph");
// Get the result
let markdown = writer.into_string(); // "Hello world\n"
```
### Writing Raw Text
In addition to nodes, you can write raw text directly:
```rust
use cmark_writer::CommonMarkWriter;
let mut writer = CommonMarkWriter::new();
writer.write_str("Hello ").unwrap();
writer.write_str("world!").unwrap();
let result = writer.into_string(); // "Hello world!"
```
## Customizing Output
The writer's behavior is controlled by `WriterOptions`. You can customize various aspects of the output format:
```rust
use cmark_writer::{CommonMarkWriter, options::WriterOptionsBuilder};
// Create custom options
let options = WriterOptionsBuilder::new()
.list_marker('*') // Use * for unordered lists
.code_fence_char('~') // Use ~~~ for code fences
.build();
let writer = CommonMarkWriter::with_options(options);
```
For details on available options, see the [WriterOptions documentation](./options).
## Error Handling
Writing operations return a `WriteResult<T>` which is a type alias for `Result<T, WriteError>`. This allows for proper error handling:
```rust
use cmark_writer::{Node, CommonMarkWriter};
let node = Node::Document(vec![/* ... */]);
let mut writer = CommonMarkWriter::new();
match writer.write(&node) {
Ok(_) => {
let markdown = writer.into_string();
// Use the generated Markdown...
},
Err(error) => {
eprintln!("Failed to write document: {}", error);
// Handle the error...
}
}
```
## Working with Custom Nodes
The writer implements the `CustomNodeWriter` trait, which allows custom nodes to write their content:
```rust
use cmark_writer::{custom_node, ast::{CustomNode, CustomNodeWriter}};
#[custom_node]
#[derive(Debug, Clone, PartialEq)]
struct ColoredText {
text: String,
color: String,
}
impl CustomNode for ColoredText {
fn write(&self, writer: &mut dyn CustomNodeWriter) -> WriteResult<()> {
writer.write_str("<span style=\"color:")?;
writer.write_str(&self.color)?;
writer.write_str("\">")?;
writer.write_str(&self.text)?;
writer.write_str("</span>")?;
Ok(())
}
// Other required trait methods...
}
```
## Display Implementation
The `Node` struct implements the `Display` trait using `CommonMarkWriter` internally, allowing for easy conversion to strings:
```rust
use cmark_writer::Node;
use std::fmt;
let node = Node::heading(1, vec![Node::Text("Title".to_string())]);
// Use Display implementation
let markdown = format!("{}", node); // "# Title\n"
```
## Thread Safety
`CommonMarkWriter` is not thread-safe by default. If you need to share a writer between threads, you'll need to implement appropriate synchronization.