mathias234 75b3a163c7
All checks were successful
CI Pipeline / build (pull_request) Successful in 13s
Implement nested lists
2025-12-02 15:00:39 +01:00
2025-12-02 14:43:53 +01:00
2025-12-02 11:01:19 +01:00
2025-12-02 15:00:39 +01:00
2025-12-02 15:00:39 +01:00
2025-12-02 15:00:39 +01:00
2025-12-02 10:23:52 +01:00
2025-12-02 13:21:13 +01:00
2025-12-02 10:23:52 +01:00
2025-12-02 10:23:52 +01:00
2025-12-02 13:43:02 +01:00
2025-12-02 10:23:52 +01:00
2025-12-02 15:00:39 +01:00
2025-12-02 10:00:41 +00:00

Notare

A Ruby gem for creating docx files with a simple DSL

Installation

Add this line to your application's Gemfile:

gem 'notare'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install notare

Usage

Basic Example

require 'notare'

Notare::Document.create("output.docx") do |doc|
  doc.p "Hello World"
end

Paragraphs

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.

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:

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

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:

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

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

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.

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

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.

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):

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:

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

Add clickable links with link:

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

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.

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.

Description
No description provided
Readme 281 KiB
Languages
Ruby 100%