133 lines
4.1 KiB
Ruby
133 lines
4.1 KiB
Ruby
module Docx
|
|
class Document
|
|
include OpenXml::Docx::Elements
|
|
|
|
def initialize
|
|
end
|
|
|
|
def generate
|
|
yield(self)
|
|
|
|
tmpfile = Tempfile.new("#{Time.current.to_f}.xlsx", Rails.root.join("tmp"))
|
|
_document.save(tmpfile.path)
|
|
tmpfile.path
|
|
end
|
|
|
|
def heading1(text)
|
|
paragraph = create_paragraph(text)
|
|
paragraph.paragraph_style = "Heading 1"
|
|
_document.document << paragraph
|
|
end
|
|
|
|
def heading2(text)
|
|
paragraph = create_paragraph(text)
|
|
paragraph.paragraph_style = "Heading 2"
|
|
_document.document << paragraph
|
|
end
|
|
|
|
def heading3(text)
|
|
paragraph = create_paragraph(text)
|
|
paragraph.paragraph_style = "Heading 3"
|
|
_document.document << paragraph
|
|
end
|
|
|
|
def paragraph(text)
|
|
html = Nokogiri::HTML5.fragment(text)
|
|
html.search(".trix-content").each do |node|
|
|
node.children.each do |child|
|
|
Rails.logger.debug { "content kids: #{child.class}: #{child.name} (#{child.children.size}): #{child.text}" }
|
|
case child
|
|
when Nokogiri::XML::Text
|
|
paragraph = create_paragraph(child.text)
|
|
_document.document << paragraph
|
|
when Nokogiri::XML::Element
|
|
case child.name
|
|
when "h1"
|
|
paragraph = create_paragraph(child.text)
|
|
paragraph.paragraph_style = "Heading 3"
|
|
when "div"
|
|
paragraph = Paragraph.new
|
|
paragraph.paragraph_style = "Body Text"
|
|
child.children.each do |node|
|
|
Rails.logger.debug { "div kids: #{node.class}: #{node.name} (#{node.children.size}): #{node.text}" }
|
|
case node.name
|
|
when "strong"
|
|
paragraph << create_run(node.text, bold: true)
|
|
when "em"
|
|
paragraph << create_run(node.text, italic: true)
|
|
when "del"
|
|
paragraph << create_run(node.text, strike_through: true)
|
|
when "br"
|
|
paragraph << create_run("\n")
|
|
else
|
|
paragraph << create_run(node.text)
|
|
end
|
|
end
|
|
when "ul"
|
|
# paragraph = Paragraph.new
|
|
# paragraph.paragraph_style = "Body Text"
|
|
# # Create an abstract numbering that describes a bulleted list:
|
|
# abstract_numbering = AbstractNumbering.new(0)
|
|
|
|
# # Each numbering can have multiple levels. Define the first level as a bulleted list:
|
|
# level_0 = Level.new
|
|
# level_0.level = 0
|
|
# level_0.start = 1
|
|
# level_0.number_format = :bullet
|
|
# # This is the default bullet Word uses
|
|
# level_0.level_text = "\u00B7".encode("UTF-8")
|
|
# level_0.alignment = :left
|
|
# level_0.character_style.font.ascii = "Symbol"
|
|
# level_0.character_style.font.high_ansi = "Symbol"
|
|
# level_0.character_style.font.hint = :default
|
|
# level_0.paragraph_style.indentation.left = 720
|
|
# level_0.paragraph_style.indentation.hanging = 360
|
|
# abstract_numbering << level_0
|
|
|
|
# _document.numbering << abstract_numbering
|
|
when "ol"
|
|
else
|
|
paragraph = create_paragraph(child.text)
|
|
paragraph.paragraph_style = "Body Text"
|
|
end
|
|
|
|
_document.document << paragraph
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def create_run(content, bold: false, italic: false, strike_through: false)
|
|
text = Text.new(content)
|
|
text.space = :preserve
|
|
run = Run.new
|
|
run.bold = bold
|
|
run.italics = italic
|
|
run.strikethrough = strike_through
|
|
run << text
|
|
run
|
|
end
|
|
|
|
def create_paragraph(content)
|
|
text = case content
|
|
when String
|
|
Text.new(content)
|
|
when ActionText::RichText
|
|
Text.new(content.to_plain_text)
|
|
else
|
|
Text.new(content.to_s)
|
|
end
|
|
run = Run.new
|
|
run << text
|
|
paragraph = Paragraph.new
|
|
paragraph << run
|
|
paragraph
|
|
end
|
|
|
|
def _document
|
|
@_document ||= OpenXml::Docx::Package.new
|
|
end
|
|
end
|
|
end
|