Project rename
All checks were successful
CI Pipeline / build (push) Successful in 12s

This commit is contained in:
2025-12-02 13:21:13 +01:00
parent 29ebb9a8d1
commit dec346254c
36 changed files with 114 additions and 114 deletions

162
lib/notare/builder.rb Normal file
View File

@@ -0,0 +1,162 @@
# frozen_string_literal: true
module Notare
module Builder
def p(text = nil, style: nil, &block)
para = Nodes::Paragraph.new(style: resolve_style(style))
if block
with_target(para, &block)
elsif text
para.add_run(Nodes::Run.new(text, **current_formatting))
end
@nodes << para
end
def text(value, style: nil)
formatting = current_formatting.merge(style: resolve_style(style))
@current_target.add_run(Nodes::Run.new(value, **formatting))
end
# Heading shortcuts
def h1(text = nil, &block)
p(text, style: :heading1, &block)
end
def h2(text = nil, &block)
p(text, style: :heading2, &block)
end
def h3(text = nil, &block)
p(text, style: :heading3, &block)
end
def h4(text = nil, &block)
p(text, style: :heading4, &block)
end
def h5(text = nil, &block)
p(text, style: :heading5, &block)
end
def h6(text = nil, &block)
p(text, style: :heading6, &block)
end
def image(path, width: nil, height: nil)
validate_image_path!(path)
img = register_image(path, width: width, height: height)
@current_target.add_run(img)
end
def b(&block)
with_format(:bold, &block)
end
def i(&block)
with_format(:italic, &block)
end
def u(&block)
with_format(:underline, &block)
end
def ul(&block)
list(:bullet, &block)
end
def ol(&block)
list(:number, &block)
end
def li(text = nil, &block)
item = Nodes::ListItem.new([], list_type: @current_list.type, num_id: @current_list.num_id)
if block
with_target(item, &block)
elsif text
item.add_run(Nodes::Run.new(text, **current_formatting))
end
@current_list.add_item(item)
end
def table(&block)
tbl = Nodes::Table.new
previous_table = @current_table
@current_table = tbl
block.call
@current_table = previous_table
@nodes << tbl
end
def tr(&block)
row = Nodes::TableRow.new
previous_row = @current_row
@current_row = row
block.call
@current_row = previous_row
@current_table.add_row(row)
end
def td(text = nil, &block)
cell = Nodes::TableCell.new
if block
with_target(cell, &block)
elsif text
cell.add_run(Nodes::Run.new(text, **current_formatting))
end
@current_row.add_cell(cell)
end
private
def list(type, &block)
@num_id_counter ||= 0
@num_id_counter += 1
list_node = Nodes::List.new(type: type, num_id: @num_id_counter)
previous_list = @current_list
@current_list = list_node
block.call
@current_list = previous_list
@nodes << list_node
end
def with_format(format, &block)
@format_stack ||= []
@format_stack.push(format)
block.call
@format_stack.pop
end
def with_target(target, &block)
previous_target = @current_target
@current_target = target
block.call
@current_target = previous_target
end
def current_formatting
@format_stack ||= []
{
bold: @format_stack.include?(:bold),
italic: @format_stack.include?(:italic),
underline: @format_stack.include?(:underline)
}
end
def validate_image_path!(path)
raise ArgumentError, "Image file not found: #{path}" unless File.exist?(path)
ext = File.extname(path).downcase
return if %w[.png .jpg .jpeg].include?(ext)
raise ArgumentError, "Unsupported image format: #{ext}. Use PNG or JPEG."
end
def resolve_style(style_or_name)
return nil if style_or_name.nil?
return style_or_name if style_or_name.is_a?(Style)
style(style_or_name) || raise(ArgumentError, "Unknown style: #{style_or_name}")
end
end
end