#require "html2doc"
#require "liquid"
#module IsoDoc
#class WordConvert < Convert
#module WordConvertModule
#def self.included base
#base.class_eval do
def insert_tab(out, n)
out.span **attr_code(style: "mso-tab-count:#{n}") do |span|
[1..n].each { span << " " }
end
end
def para_attrs(node)
classtype = nil
classtype = "Note" if @note
classtype = "MsoCommentText" if in_comment
classtype = "Sourcecode" if @annotation
attrs = { class: classtype, id: node["id"] }
unless node["align"].nil?
attrs[:align] = node["align"] unless node["align"] == "justify"
attrs[:style] = "text-align:#{node['align']}"
end
attrs
end
def remove_bottom_border(td)
td["style"] =
td["style"].gsub(/border-bottom:[^;]+;/, "border-bottom:0pt;").
gsub(/mso-border-bottom-alt:[^;]+;/, "mso-border-bottom-alt:0pt;")
end
#SW1 = IsoDoc::SW
SW1 = "solid windowtext".freeze
def new_fullcolspan_row(t, tfoot)
# how many columns in the table?
cols = 0
t.at(".//tr").xpath("./td | ./th").each do |td|
cols += (td["colspan"] ? td["colspan"].to_i : 1)
end
style = %{border-top:0pt;mso-border-top-alt:0pt;
border-bottom:#{SW1} 1.5pt;mso-border-bottom-alt:#{SW1} 1.5pt;}
tfoot.add_child("
|
")
tfoot.xpath(".//td").last
end
def make_tr_attr(td, row, totalrows)
style = td.name == "th" ? "font-weight:bold;" : ""
rowmax = td["rowspan"] ? row + td["rowspan"].to_i - 1 : row
style += <<~STYLE
border-top:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
mso-border-top-alt:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
border-bottom:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
mso-border-bottom-alt:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
STYLE
{ rowspan: td["rowspan"], colspan: td["colspan"],
align: td["align"], style: style.gsub(/\n/, "") }
end
def section_break(body)
body.br **{ clear: "all", class: "section" }
end
def page_break(out)
out.br **{
clear: "all",
style: "mso-special-character:line-break;page-break-before:always",
}
end
def dt_parse(dt, term)
if dt.elements.empty?
term.p **attr_code(class: note? ? "Note" : nil,
style: "text-align: left;") do |p|
p << dt.text
end
else
dt.children.each { |n| parse(n, term) }
end
end
def dl_parse(node, out)
out.table **{ class: "dl" } do |v|
node.elements.each_slice(2) do |dt, dd|
v.tr do |tr|
tr.td **{ valign: "top", align: "left" } do |term|
dt_parse(dt, term)
end
tr.td **{ valign: "top" } do |listitem|
dd.children.each { |n| parse(n, listitem) }
end
end
end
end
end
def postprocess(result, filename, dir)
generate_header(filename, dir)
result = from_xhtml(cleanup(to_xhtml(result)))
toWord(result, filename, dir)
end
def toWord(result, filename, dir)
result = from_xhtml(word_cleanup(to_xhtml(result)))
result = populate_template(result, :word)
Html2Doc.process(result, filename: filename, stylesheet: @wordstylesheet,
header_file: "header.html", dir: dir,
asciimathdelims: [@openmathdelim, @closemathdelim],
liststyles: { ul: @ulstyle, ol: @olstyle })
end
def word_cleanup(docxml)
word_preface(docxml)
word_annex_cleanup(docxml)
docxml
end
# force Annex h2 to be p.h2Annex, so it is not picked up by ToC
def word_annex_cleanup(docxml)
docxml.xpath("//h2[ancestor::*[@class = 'Section3']]").each do |h2|
h2.name = "p"
h2["class"] = "h2Annex"
end
end
def word_preface(docxml)
word_cover(docxml) if @wordcoverpage
word_intro(docxml) if @wordintropage
end
def word_cover(docxml)
cover = to_xhtml_fragment(File.read(@wordcoverpage, encoding: "UTF-8"))
docxml.at('//div[@class="WordSection1"]').children.first.previous =
cover.to_xml(encoding: "US-ASCII")
end
def word_intro(docxml)
intro = to_xhtml_fragment(File.read(@wordintropage, encoding: "UTF-8").
sub(/WORDTOC/, make_WordToC(docxml)))
docxml.at('//div[@class="WordSection2"]').children.first.previous =
intro.to_xml(encoding: "US-ASCII")
end
def generate_header(filename, _dir)
return unless @header
template = Liquid::Template.parse(File.read(@header, encoding: "UTF-8"))
meta = get_metadata
meta[:filename] = filename
params = meta.map { |k, v| [k.to_s, v] }.to_h
File.open("header.html", "w") do |f|
f.write(template.render(params))
end
end
def word_toc_entry(toclevel, heading)
bookmark = Random.rand(1000000000)
<<~TOC
#{heading}
.
PAGEREF _Toc#{bookmark} \\h
1
TOC
end
#WORD_TOC_PREFACE = <<~TOC.freeze
WORD_TOC_PREFACE1 = <<~TOC.freeze
TOC
\\o "1-2" \\h \\z \\u
TOC
#WORD_TOC_SUFFIX = <<~TOC.freeze
WORD_TOC_SUFFIX1 = <<~TOC.freeze
TOC
def make_WordToC(docxml)
toc = ""
docxml.xpath("//h1 | //h2[not(ancestor::*[@class = 'Section3'])]").
each do |h|
toc += word_toc_entry(h.name == "h1" ? 1 : 2, header_strip(h))
end
toc.sub(/()/,
#%{\\1#{WORD_TOC_PREFACE}}) + WORD_TOC_SUFFIX
%{\\1#{WORD_TOC_PREFACE1}}) + WORD_TOC_SUFFIX1
end
#end
#end
#end
#end