Compare commits
7
Commits
64c8679044
..
v0.0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d17209bc8 | ||
|
|
a84d7b0b8f | ||
|
|
022c52eef6 | ||
|
|
f3e566364f | ||
|
|
ee07c747b9 | ||
|
|
e937552913 | ||
|
|
26e0d59cf1 |
@@ -2,8 +2,10 @@
|
||||
|
||||
module Notare
|
||||
module Builder
|
||||
def p(text = nil, style: nil, &block)
|
||||
para = Nodes::Paragraph.new(style: resolve_style(style))
|
||||
def p(text = nil, style: nil, spacing_before: nil, spacing_after: nil, &block)
|
||||
para = Nodes::Paragraph.new(style: resolve_style(style),
|
||||
spacing_before: spacing_before,
|
||||
spacing_after: spacing_after)
|
||||
if block
|
||||
with_target(para, &block)
|
||||
elsif text
|
||||
|
||||
+14
-9
@@ -4,16 +4,21 @@ module Notare
|
||||
class Document
|
||||
include Builder
|
||||
|
||||
attr_reader :nodes, :styles, :table_styles, :hyperlinks
|
||||
DEFAULT_FONT = "Arial"
|
||||
DEFAULT_SIZE = 12
|
||||
|
||||
def self.create(path, &block)
|
||||
doc = new
|
||||
attr_reader :nodes, :styles, :table_styles, :hyperlinks, :default_font, :default_size
|
||||
|
||||
def self.create(path, default_font: DEFAULT_FONT, default_size: DEFAULT_SIZE, &block)
|
||||
doc = new(default_font: default_font, default_size: default_size)
|
||||
block.call(doc)
|
||||
doc.save(path)
|
||||
doc
|
||||
end
|
||||
|
||||
def initialize
|
||||
def initialize(default_font: DEFAULT_FONT, default_size: DEFAULT_SIZE)
|
||||
@default_font = default_font
|
||||
@default_size = default_size
|
||||
@nodes = []
|
||||
@format_stack = []
|
||||
@current_target = nil
|
||||
@@ -51,7 +56,7 @@ module Notare
|
||||
end
|
||||
|
||||
def lists
|
||||
@nodes.select { |n| n.is_a?(Nodes::List) }
|
||||
@nodes.grep(Nodes::List)
|
||||
end
|
||||
|
||||
def uses_lists?
|
||||
@@ -101,12 +106,12 @@ module Notare
|
||||
|
||||
def register_built_in_styles
|
||||
# Headings (spacing_before ensures they're rendered as paragraph styles)
|
||||
define_style :heading1, size: 24, bold: true, spacing_before: 240, spacing_after: 120
|
||||
define_style :heading2, size: 18, bold: true, spacing_before: 200, spacing_after: 100
|
||||
define_style :heading1, size: 20, bold: true, spacing_before: 240, spacing_after: 120
|
||||
define_style :heading2, size: 16, bold: true, spacing_before: 200, spacing_after: 100
|
||||
define_style :heading3, size: 14, bold: true, spacing_before: 160, spacing_after: 80
|
||||
define_style :heading4, size: 12, bold: true, spacing_before: 120, spacing_after: 60
|
||||
define_style :heading5, size: 11, bold: true, italic: true, spacing_before: 100, spacing_after: 40
|
||||
define_style :heading6, size: 10, bold: true, italic: true, spacing_before: 80, spacing_after: 40
|
||||
define_style :heading5, size: 12, bold: true, italic: true, spacing_before: 100, spacing_after: 40
|
||||
define_style :heading6, size: 12, italic: true, spacing_before: 80, spacing_after: 40
|
||||
|
||||
# Other built-in styles
|
||||
define_style :title, size: 26, bold: true, align: :center
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
module Notare
|
||||
module Nodes
|
||||
class Paragraph < Base
|
||||
attr_reader :runs, :style
|
||||
attr_reader :runs, :style, :spacing_before, :spacing_after
|
||||
|
||||
def initialize(runs = [], style: nil)
|
||||
def initialize(runs = [], style: nil, spacing_before: nil, spacing_after: nil)
|
||||
super()
|
||||
@runs = runs
|
||||
@style = style
|
||||
@spacing_before = spacing_before
|
||||
@spacing_after = spacing_after
|
||||
end
|
||||
|
||||
def add_run(run)
|
||||
|
||||
@@ -59,7 +59,12 @@ module Notare
|
||||
end
|
||||
|
||||
def styles_xml
|
||||
Xml::StylesXml.new(@document.styles, @document.table_styles).to_xml
|
||||
Xml::StylesXml.new(
|
||||
@document.styles,
|
||||
@document.table_styles,
|
||||
default_font: @document.default_font,
|
||||
default_size: @document.default_size
|
||||
).to_xml
|
||||
end
|
||||
|
||||
def numbering_xml
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Notare
|
||||
VERSION = "0.0.6"
|
||||
VERSION = "0.0.9"
|
||||
end
|
||||
|
||||
@@ -52,9 +52,18 @@ module Notare
|
||||
|
||||
def render_paragraph(xml, para)
|
||||
xml["w"].p do
|
||||
if para.style
|
||||
has_style = para.style
|
||||
has_spacing = para.spacing_before || para.spacing_after
|
||||
|
||||
if has_style || has_spacing
|
||||
xml["w"].pPr do
|
||||
xml["w"].pStyle("w:val" => para.style.style_id)
|
||||
xml["w"].pStyle("w:val" => para.style.style_id) if has_style
|
||||
if has_spacing
|
||||
spacing_attrs = {}
|
||||
spacing_attrs["w:before"] = para.spacing_before.to_s if para.spacing_before
|
||||
spacing_attrs["w:after"] = para.spacing_after.to_s if para.spacing_after
|
||||
xml["w"].spacing(spacing_attrs)
|
||||
end
|
||||
end
|
||||
end
|
||||
para.runs.each { |run| render_run(xml, run) }
|
||||
|
||||
@@ -16,11 +16,8 @@ module Notare
|
||||
xml.numbering("xmlns:w" => NAMESPACE) do
|
||||
xml.parent.namespace = xml.parent.namespace_definitions.find { |ns| ns.prefix == "w" }
|
||||
|
||||
@lists.each do |list|
|
||||
render_abstract_num(xml, list)
|
||||
|
||||
render_num(xml, list)
|
||||
end
|
||||
render_abstract_nums(xml)
|
||||
render_nums(xml)
|
||||
end
|
||||
end
|
||||
builder.to_xml
|
||||
@@ -28,6 +25,14 @@ module Notare
|
||||
|
||||
private
|
||||
|
||||
def render_abstract_nums(xml)
|
||||
@lists.each { |list| render_abstract_num(xml, list) }
|
||||
end
|
||||
|
||||
def render_nums(xml)
|
||||
@lists.each { |list| render_num(xml, list) }
|
||||
end
|
||||
|
||||
def render_abstract_num(xml, list)
|
||||
xml["w"].abstractNum("w:abstractNumId" => list.num_id.to_s) do
|
||||
9.times do |level|
|
||||
|
||||
@@ -18,9 +18,11 @@ module Notare
|
||||
right: "right"
|
||||
}.freeze
|
||||
|
||||
def initialize(styles, table_styles = {})
|
||||
def initialize(styles, table_styles = {}, default_font: nil, default_size: nil)
|
||||
@styles = styles
|
||||
@table_styles = table_styles
|
||||
@default_font = default_font
|
||||
@default_size = default_size
|
||||
end
|
||||
|
||||
def to_xml
|
||||
@@ -28,6 +30,8 @@ module Notare
|
||||
xml.styles("xmlns:w" => NAMESPACE) do
|
||||
xml.parent.namespace = xml.parent.namespace_definitions.find { |ns| ns.prefix == "w" }
|
||||
|
||||
render_doc_defaults(xml) if @default_font || @default_size
|
||||
|
||||
@styles.each_value do |style|
|
||||
render_style(xml, style)
|
||||
end
|
||||
@@ -44,6 +48,28 @@ module Notare
|
||||
|
||||
private
|
||||
|
||||
def render_doc_defaults(xml)
|
||||
xml["w"].docDefaults do
|
||||
xml["w"].rPrDefault do
|
||||
xml["w"].rPr do
|
||||
if @default_font
|
||||
xml["w"].rFonts(
|
||||
"w:ascii" => @default_font,
|
||||
"w:hAnsi" => @default_font,
|
||||
"w:eastAsia" => @default_font,
|
||||
"w:cs" => @default_font
|
||||
)
|
||||
end
|
||||
if @default_size
|
||||
half_points = (@default_size * 2).to_i
|
||||
xml["w"].sz("w:val" => half_points.to_s)
|
||||
xml["w"].szCs("w:val" => half_points.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_style(xml, style)
|
||||
style_type = style.paragraph_properties? ? "paragraph" : "character"
|
||||
|
||||
|
||||
@@ -69,6 +69,6 @@ class DocumentTest < Minitest::Test
|
||||
doc.table { doc.tr { doc.td "Cell" } }
|
||||
|
||||
assert_equal 2, doc.lists.count
|
||||
assert(doc.lists.all? { |l| l.is_a?(Notare::Nodes::List) })
|
||||
assert(doc.lists.all?(Notare::Nodes::List))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,6 +115,10 @@ class ListTest < Minitest::Test
|
||||
assert_includes doc_xml, "List 1 Item 1"
|
||||
assert_includes doc_xml, "List 2 Item 1"
|
||||
assert_includes doc_xml, "Separator paragraph"
|
||||
|
||||
numbering_xml = Nokogiri::XML(xml_files["word/numbering.xml"])
|
||||
child_names = numbering_xml.root.element_children.map(&:name)
|
||||
assert_equal %w[abstractNum abstractNum num num], child_names
|
||||
end
|
||||
|
||||
def test_mixed_list_types
|
||||
|
||||
Reference in New Issue
Block a user