All checks were successful
CI Pipeline / build (pull_request) Successful in 13s
462 lines
9.3 KiB
Markdown
462 lines
9.3 KiB
Markdown
# Notare
|
|
|
|
A Ruby gem for creating docx files with a simple DSL
|
|
|
|
## Installation
|
|
|
|
Add this line to your application's Gemfile:
|
|
|
|
```ruby
|
|
gem 'notare'
|
|
```
|
|
|
|
And then execute:
|
|
|
|
$ bundle install
|
|
|
|
Or install it yourself as:
|
|
|
|
$ gem install notare
|
|
|
|
## Usage
|
|
|
|
### Basic Example
|
|
|
|
```ruby
|
|
require 'notare'
|
|
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.p "Hello World"
|
|
end
|
|
```
|
|
|
|
### Paragraphs
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
# Simple paragraph
|
|
doc.p "This is a paragraph."
|
|
|
|
# Paragraph with multiple text runs
|
|
doc.p do
|
|
doc.text "First part. "
|
|
doc.text "Second part."
|
|
end
|
|
end
|
|
```
|
|
|
|
### Text Formatting
|
|
|
|
Formatting uses nested blocks. Nesting combines formatting styles.
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.p do
|
|
doc.text "Normal text "
|
|
doc.b { doc.text "bold" }
|
|
doc.text " and "
|
|
doc.i { doc.text "italic" }
|
|
doc.text " and "
|
|
doc.u { doc.text "underlined" }
|
|
doc.text " and "
|
|
doc.s { doc.text "strikethrough" }
|
|
end
|
|
|
|
# Nested formatting (bold + italic)
|
|
doc.p do
|
|
doc.b do
|
|
doc.i { doc.text "bold and italic" }
|
|
end
|
|
end
|
|
|
|
# Show edits (strikethrough old, bold new)
|
|
doc.p do
|
|
doc.s { doc.text "old text" }
|
|
doc.text " "
|
|
doc.b { doc.text "new text" }
|
|
end
|
|
end
|
|
```
|
|
|
|
### Headings
|
|
|
|
Use `h1` through `h6` for document headings:
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.h1 "Document Title"
|
|
doc.h2 "Chapter 1"
|
|
doc.h3 "Section 1.1"
|
|
doc.h4 "Subsection"
|
|
doc.h5 "Minor heading"
|
|
doc.h6 "Smallest heading"
|
|
|
|
# Headings with formatted content
|
|
doc.h2 do
|
|
doc.text "Chapter with "
|
|
doc.i { doc.text "emphasis" }
|
|
end
|
|
end
|
|
```
|
|
|
|
### Styles
|
|
|
|
Notare includes built-in styles and supports custom style definitions.
|
|
|
|
#### Built-in Styles
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.p "This is a title", style: :title
|
|
doc.p "A subtitle", style: :subtitle
|
|
doc.p "A quotation", style: :quote
|
|
doc.p "puts 'code'", style: :code
|
|
end
|
|
```
|
|
|
|
#### Custom Styles
|
|
|
|
Define your own styles with text and paragraph properties:
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
# Define custom styles
|
|
doc.define_style :warning,
|
|
bold: true,
|
|
color: "FF0000",
|
|
size: 14
|
|
|
|
doc.define_style :note,
|
|
italic: true,
|
|
color: "0066CC",
|
|
font: "Georgia"
|
|
|
|
doc.define_style :centered,
|
|
align: :center,
|
|
size: 12
|
|
|
|
# Apply to paragraphs
|
|
doc.p "Warning message!", style: :warning
|
|
doc.p "Centered text", style: :centered
|
|
|
|
# Apply to text runs
|
|
doc.p do
|
|
doc.text "Normal text, "
|
|
doc.text "important!", style: :warning
|
|
doc.text ", and "
|
|
doc.text "a note", style: :note
|
|
end
|
|
end
|
|
```
|
|
|
|
#### Style Properties
|
|
|
|
**Text properties:**
|
|
- `bold: true/false`
|
|
- `italic: true/false`
|
|
- `underline: true/false`
|
|
- `strike: true/false` - strikethrough
|
|
- `highlight: "yellow"` - text highlight (see colors below)
|
|
- `color: "FF0000"` (hex RGB)
|
|
- `size: 14` (points)
|
|
- `font: "Arial"` (font family)
|
|
|
|
**Highlight colors:** `black`, `blue`, `cyan`, `darkBlue`, `darkCyan`, `darkGray`, `darkGreen`, `darkMagenta`, `darkRed`, `darkYellow`, `green`, `lightGray`, `magenta`, `red`, `white`, `yellow`
|
|
|
|
**Paragraph properties:**
|
|
- `align: :left / :center / :right / :justify`
|
|
- `indent: 720` (twips, 1 inch = 1440 twips)
|
|
- `spacing_before: 240` (twips)
|
|
- `spacing_after: 240` (twips)
|
|
|
|
### Lists
|
|
|
|
#### Bullet Lists
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.ul do
|
|
doc.li "First item"
|
|
doc.li "Second item"
|
|
doc.li { doc.b { doc.text "Bold item" } }
|
|
end
|
|
end
|
|
```
|
|
|
|
#### Numbered Lists
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.ol do
|
|
doc.li "First"
|
|
doc.li "Second"
|
|
doc.li "Third"
|
|
end
|
|
end
|
|
```
|
|
|
|
#### Nested Lists
|
|
|
|
Lists can be nested inside list items. Mixed types (bullets inside numbered or vice versa) are supported.
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.ol do
|
|
doc.li "First item"
|
|
doc.li "Second item" do
|
|
doc.ul do
|
|
doc.li "Nested bullet A"
|
|
doc.li "Nested bullet B"
|
|
end
|
|
end
|
|
doc.li "Third item"
|
|
end
|
|
|
|
# Deeply nested
|
|
doc.ul do
|
|
doc.li "Level 0"
|
|
doc.li "Has children" do
|
|
doc.ul do
|
|
doc.li "Level 1"
|
|
doc.li "Goes deeper" do
|
|
doc.ul do
|
|
doc.li "Level 2"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### Tables
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.table do
|
|
doc.tr do
|
|
doc.td "Header 1"
|
|
doc.td "Header 2"
|
|
end
|
|
doc.tr do
|
|
doc.td "Cell 1"
|
|
doc.td { doc.b { doc.text "Bold cell" } }
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### Images
|
|
|
|
Images can be added to paragraphs, table cells, and list items. Supports PNG and JPEG formats.
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
# Simple image (uses native dimensions)
|
|
doc.p do
|
|
doc.image "photo.png"
|
|
end
|
|
|
|
# Image with explicit dimensions (inches, cm, or pixels)
|
|
doc.p do
|
|
doc.image "logo.png", width: "2in", height: "1in"
|
|
end
|
|
|
|
# Specify only width (height auto-calculated to maintain aspect ratio)
|
|
doc.p do
|
|
doc.image "banner.jpg", width: "5cm"
|
|
end
|
|
|
|
# Image with text in the same paragraph
|
|
doc.p do
|
|
doc.text "Company Logo: "
|
|
doc.image "logo.png", width: "0.5in", height: "0.5in"
|
|
end
|
|
|
|
# Image in a table cell
|
|
doc.table do
|
|
doc.tr do
|
|
doc.td "Product"
|
|
doc.td do
|
|
doc.image "product.jpg", width: "1in", height: "1in"
|
|
end
|
|
end
|
|
end
|
|
|
|
# Image in a list item
|
|
doc.ul do
|
|
doc.li do
|
|
doc.image "icon.png", width: "16px", height: "16px"
|
|
doc.text " List item with icon"
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### Line Breaks
|
|
|
|
Use `br` for soft line breaks within a paragraph (text continues in the same paragraph but on a new line):
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.p do
|
|
doc.text "Line one"
|
|
doc.br
|
|
doc.text "Line two (same paragraph)"
|
|
doc.br
|
|
doc.text "Line three"
|
|
end
|
|
|
|
# Useful for addresses
|
|
doc.p do
|
|
doc.b { doc.text "Address:" }
|
|
doc.br
|
|
doc.text "123 Main Street"
|
|
doc.br
|
|
doc.text "Anytown, ST 12345"
|
|
end
|
|
end
|
|
```
|
|
|
|
### Page Breaks
|
|
|
|
Use `page_break` to force content to start on a new page:
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
doc.h1 "Chapter 1"
|
|
doc.p "Content of chapter 1..."
|
|
|
|
doc.page_break
|
|
|
|
doc.h1 "Chapter 2"
|
|
doc.p "This starts on a new page."
|
|
end
|
|
```
|
|
|
|
### Hyperlinks
|
|
|
|
Add clickable links with `link`:
|
|
|
|
```ruby
|
|
Notare::Document.create("output.docx") do |doc|
|
|
# Link with custom text
|
|
doc.p do
|
|
doc.text "Visit "
|
|
doc.link "https://example.com", "our website"
|
|
doc.text " for more info."
|
|
end
|
|
|
|
# Link showing the URL as text
|
|
doc.p do
|
|
doc.text "URL: "
|
|
doc.link "https://example.com"
|
|
end
|
|
|
|
# Link with formatted content
|
|
doc.p do
|
|
doc.link "https://github.com" do
|
|
doc.b { doc.text "GitHub" }
|
|
end
|
|
end
|
|
|
|
# Links in lists
|
|
doc.ul do
|
|
doc.li do
|
|
doc.link "https://ruby-lang.org", "Ruby"
|
|
end
|
|
doc.li do
|
|
doc.link "https://rubyonrails.org", "Rails"
|
|
end
|
|
end
|
|
|
|
# Email links
|
|
doc.p do
|
|
doc.text "Contact: "
|
|
doc.link "mailto:hello@example.com", "hello@example.com"
|
|
end
|
|
end
|
|
```
|
|
|
|
### Complete Example
|
|
|
|
```ruby
|
|
Notare::Document.create("report.docx") do |doc|
|
|
doc.p "Monthly Report"
|
|
|
|
doc.p do
|
|
doc.text "This report contains "
|
|
doc.b { doc.text "important" }
|
|
doc.text " information."
|
|
end
|
|
|
|
doc.p "Key Points:"
|
|
|
|
doc.ul do
|
|
doc.li "Revenue increased by 15%"
|
|
doc.li "Customer satisfaction improved"
|
|
doc.li { doc.i { doc.text "See appendix for details" } }
|
|
end
|
|
|
|
doc.p "Summary Table:"
|
|
|
|
doc.table do
|
|
doc.tr do
|
|
doc.td "Metric"
|
|
doc.td "Value"
|
|
end
|
|
doc.tr do
|
|
doc.td "Revenue"
|
|
doc.td "$1.2M"
|
|
end
|
|
doc.tr do
|
|
doc.td "Growth"
|
|
doc.td { doc.b { doc.text "15%" } }
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
## API Reference
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `p(text, style:)` | Create a paragraph with text and optional style |
|
|
| `p(style:) { }` | Create a paragraph with block content and optional style |
|
|
| `text(value, style:)` | Add text with optional style to the current context |
|
|
| `h1(text)` - `h6(text)` | Create headings (level 1-6) |
|
|
| `b { }` | Bold formatting |
|
|
| `i { }` | Italic formatting |
|
|
| `u { }` | Underline formatting |
|
|
| `s { }` | Strikethrough formatting |
|
|
| `br` | Line break (soft break within paragraph) |
|
|
| `page_break` | Page break (force new page) |
|
|
| `link(url, text)` | Hyperlink with custom text |
|
|
| `link(url) { }` | Hyperlink with block content |
|
|
| `define_style(name, **props)` | Define a custom style |
|
|
| `ul { }` | Bullet list (can be nested) |
|
|
| `ol { }` | Numbered list (can be nested) |
|
|
| `li(text)` | List item with text |
|
|
| `li { }` | List item with block content |
|
|
| `li(text) { }` | List item with text and nested content |
|
|
| `table { }` | Table |
|
|
| `tr { }` | Table row |
|
|
| `td(text)` | Table cell with text |
|
|
| `td { }` | Table cell with block content |
|
|
| `image(path, width:, height:)` | Insert image (PNG/JPEG). Dimensions: `"2in"`, `"5cm"`, `"100px"`, or integer pixels |
|
|
|
|
## Development
|
|
|
|
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
|
|
|
|
```bash
|
|
bundle install
|
|
bundle exec rake test # Run tests
|
|
bundle exec rake rubocop # Run linter
|
|
bundle exec rake # Run both
|
|
```
|
|
|
|
## License
|
|
|
|
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|