# 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 | Style | Properties | |-------|------------| | `:title` | 26pt, bold, centered | | `:subtitle` | 15pt, italic, gray (#666666) | | `:quote` | italic, gray (#666666), indented | | `:code` | Courier New, 10pt | | `:heading1` | 24pt, bold | | `:heading2` | 18pt, bold | | `:heading3` | 14pt, bold | | `:heading4` | 12pt, bold | | `:heading5` | 11pt, bold, italic | | `:heading6` | 10pt, bold, italic | Note: `h1` through `h6` methods use the corresponding heading styles automatically. ```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 ``` #### Table Styles Define reusable table styles with borders, shading, cell margins, and alignment: ```ruby Notare::Document.create("output.docx") do |doc| # Define a custom table style doc.define_table_style :fancy, borders: { style: "double", color: "0066CC", size: 6 }, shading: "E6F2FF", cell_margins: 100, align: :center # Apply the style to a table doc.table(style: :fancy) do doc.tr do doc.td "Product" doc.td "Price" end doc.tr do doc.td "Widget" doc.td "$10.00" end end end ``` #### Table Style Properties | Property | Description | Example | |----------|-------------|---------| | `borders` | Border configuration | `{ style: "single", color: "000000", size: 4 }` | | `shading` | Background color (hex) | `"EEEEEE"` | | `cell_margins` | Cell padding (twips) | `100` or `{ top: 50, bottom: 50, left: 100, right: 100 }` | | `align` | Table alignment | `:left`, `:center`, `:right` | **Border styles:** `single`, `double`, `dotted`, `dashed`, `triple`, `none` **Border configuration options:** ```ruby # All borders the same borders: { style: "single", color: "000000", size: 4 } # Per-edge borders borders: { top: { style: "double", color: "FF0000", size: 8 }, bottom: { style: "single", color: "000000", size: 4 }, left: { style: "none" }, right: { style: "none" }, insideH: { style: "dotted", color: "CCCCCC", size: 2 }, insideV: { style: "dotted", color: "CCCCCC", size: 2 } } # No borders borders: :none ``` #### Built-in Table Styles | Style | Description | |-------|-------------| | `:grid` | Standard black single-line borders | | `:borderless` | No borders | ```ruby doc.table(style: :borderless) do doc.tr { doc.td "No borders here" } end ``` #### Column Sizing Control table column widths with layout modes and explicit sizing. **Auto-layout** - columns adjust to fit content: ```ruby doc.table(layout: :auto) do doc.tr do doc.td "Short" doc.td "This column expands to fit longer content" end end ``` **Fixed column widths** - specify widths for all columns: ```ruby # Inches doc.table(columns: %w[2in 3in 1.5in]) do doc.tr do doc.td "2 inches" doc.td "3 inches" doc.td "1.5 inches" end end # Centimeters doc.table(columns: %w[5cm 10cm]) do doc.tr { doc.td "5cm"; doc.td "10cm" } end # Percentages doc.table(columns: %w[25% 50% 25%]) do doc.tr { doc.td "Quarter"; doc.td "Half"; doc.td "Quarter" } end ``` **Per-cell widths** - set width on individual cells: ```ruby doc.table do doc.tr do doc.td("Narrow", width: "1in") doc.td("Wide", width: "4in") end end ``` **Combined layout and columns:** ```ruby doc.table(layout: :fixed, columns: %w[2in 2in 2in]) do doc.tr do doc.td "A" doc.td "B" doc.td "C" end end ``` **Width formats:** | Format | Example | Description | |--------|---------|-------------| | Inches | `"2in"` | Fixed width in inches | | Centimeters | `"5cm"` | Fixed width in centimeters | | Percentage | `"50%"` | Percentage of table width | ### 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 | | `define_table_style(name, **props)` | Define a custom table 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(style:, layout:, columns:) { }` | Table with optional style, layout (`:auto`/`:fixed`), and column widths | | `tr { }` | Table row | | `td(text, width:)` | Table cell with text and optional width | | `td(width:) { }` | Table cell with block content and optional width | | `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).