isodoc 0.4.0 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +5 -0
- data/isodoc.gemspec +1 -0
- data/lib/isodoc.rb +4 -0
- data/lib/isodoc/blocks.rb +26 -10
- data/lib/isodoc/cleanup.rb +21 -20
- data/lib/isodoc/html.rb +58 -2
- data/lib/isodoc/inline.rb +32 -149
- data/lib/isodoc/iso2wordhtml.rb +11 -3
- data/lib/isodoc/metadata.rb +93 -30
- data/lib/isodoc/notes.rb +218 -0
- data/lib/isodoc/postprocessing.rb +21 -20
- data/lib/isodoc/references.rb +18 -14
- data/lib/isodoc/section.rb +10 -10
- data/lib/isodoc/utils.rb +0 -8
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/xref_gen.rb +5 -4
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92ad102a0e0bc53916aaec5d7a4f23d71828f3d4
|
4
|
+
data.tar.gz: 7dbbd1969e0e1714c9074ac455a335939f634335
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b570dec93a170716366cf0d433d20dc614026ebe2224b02e659216fccf006b1680a1126e763a953f8d61c8154a0c9b133dfd989b05e25e675b5b3aa1f10d980
|
7
|
+
data.tar.gz: b9499b701f2eaca4a27d71ff85ff27926bd58e43a2b255dd429180eaf8b8c72704f8ba3768b2eb894f41128136f887308e6f2a29e89c000b7f02cf2dcb391e51
|
data/README.adoc
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
= isodoc
|
2
2
|
|
3
|
+
|
4
|
+
image:https://img.shields.io/gem/v/isodoc.svg["Gem Version", link="https://rubygems.org/gems/isodoc"]
|
5
|
+
image:https://img.shields.io/travis/riboseinc/asciidoctor-iso/master.svg["Build Status", link="https://travis-ci.org/riboseinc/isodoc"]
|
6
|
+
image:https://codeclimate.com/github/riboseinc/isodoc/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/riboseinc/isodoc"]
|
7
|
+
|
3
8
|
This Gem converts documents in the https://github.com/riboseinc/isodoc-models[ISODoc document model] into HTML and Microsoft Word.
|
4
9
|
|
5
10
|
The Gem is a class called with a hash of file locations:
|
data/isodoc.gemspec
CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_dependency "thread_safe"
|
38
38
|
spec.add_dependency "uuidtools"
|
39
39
|
spec.add_dependency "html2doc"
|
40
|
+
spec.add_dependency "liquid"
|
40
41
|
|
41
42
|
spec.add_development_dependency "bundler", "~> 1.15"
|
42
43
|
spec.add_development_dependency "byebug", "~> 9.1"
|
data/lib/isodoc.rb
CHANGED
@@ -20,6 +20,7 @@ require_relative "isodoc/blocks"
|
|
20
20
|
require_relative "isodoc/lists"
|
21
21
|
require_relative "isodoc/table"
|
22
22
|
require_relative "isodoc/inline"
|
23
|
+
require_relative "isodoc/notes"
|
23
24
|
require_relative "isodoc/xref_gen"
|
24
25
|
require_relative "isodoc/html"
|
25
26
|
require "pp"
|
@@ -50,9 +51,11 @@ module IsoDoc
|
|
50
51
|
@sourcecode = false
|
51
52
|
@anchors = {}
|
52
53
|
@meta = {}
|
54
|
+
init_metadata
|
53
55
|
@footnotes = []
|
54
56
|
@comments = []
|
55
57
|
@in_footnote = false
|
58
|
+
@in_comment = false
|
56
59
|
@in_table = false
|
57
60
|
@in_figure = false
|
58
61
|
@seen_footnote = Set.new
|
@@ -64,6 +67,7 @@ module IsoDoc
|
|
64
67
|
docxml.root.default_namespace = ""
|
65
68
|
result = noko do |xml|
|
66
69
|
xml.html do |html|
|
70
|
+
html.parent.add_namespace("epub", "http://www.idpf.org/2007/ops")
|
67
71
|
html_header(html, docxml, filename, dir)
|
68
72
|
make_body(html, docxml)
|
69
73
|
end
|
data/lib/isodoc/blocks.rb
CHANGED
@@ -80,6 +80,16 @@ module IsoDoc
|
|
80
80
|
@in_figure = false
|
81
81
|
end
|
82
82
|
|
83
|
+
def example_parse(node, out)
|
84
|
+
name = node.at(ns("./name"))
|
85
|
+
out.div **attr_code(id: node["id"], class: "figure") do |div|
|
86
|
+
node.children.each do |n|
|
87
|
+
parse(n, div) unless n.name == "name"
|
88
|
+
end
|
89
|
+
figure_name_parse(node, div, name) if name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
83
93
|
def sourcecode_name_parse(node, div, name)
|
84
94
|
div.p **{ class: "FigureTitle", align: "center" } do |p|
|
85
95
|
p.b do |b|
|
@@ -109,13 +119,18 @@ module IsoDoc
|
|
109
119
|
def admonition_parse(node, out)
|
110
120
|
name = node["type"]
|
111
121
|
out.div **{ class: "Admonition" } do |t|
|
112
|
-
t.
|
122
|
+
t.title { |b| b << name.upcase } if name
|
113
123
|
node.children.each do |n|
|
114
124
|
parse(n, t)
|
115
125
|
end
|
116
126
|
end
|
117
127
|
end
|
118
128
|
|
129
|
+
def formula_where(dl, out)
|
130
|
+
out.p { |p| p << "where" }
|
131
|
+
parse(dl, out)
|
132
|
+
end
|
133
|
+
|
119
134
|
def formula_parse(node, out)
|
120
135
|
dl = node.at(ns("./dl"))
|
121
136
|
out.div **attr_code(id: node["id"], class: "formula") do |div|
|
@@ -123,17 +138,15 @@ module IsoDoc
|
|
123
138
|
insert_tab(div, 1)
|
124
139
|
div << "(#{get_anchors()[node['id']][:label]})"
|
125
140
|
end
|
126
|
-
|
127
|
-
out.p { |p| p << "where" }
|
128
|
-
parse(dl, out)
|
129
|
-
end
|
141
|
+
formula_where(dl, out) if dl
|
130
142
|
end
|
131
143
|
|
132
144
|
def para_attrs(node)
|
133
145
|
classtype = nil
|
134
146
|
classtype = "Note" if @note
|
135
|
-
classtype = "MsoFootnoteText" if in_footnote
|
136
|
-
|
147
|
+
# classtype = "MsoFootnoteText" if in_footnote
|
148
|
+
classtype = "MsoCommentText" if in_comment
|
149
|
+
attrs = { class: classtype, id: node["id"] }
|
137
150
|
unless node["align"].nil?
|
138
151
|
attrs[:align] = node["align"] unless node["align"] == "justify"
|
139
152
|
attrs[:style] = "text-align:#{node["align"]}"
|
@@ -152,15 +165,18 @@ module IsoDoc
|
|
152
165
|
end
|
153
166
|
|
154
167
|
def quote_attribution(node, out)
|
155
|
-
author = node.at(ns("./author
|
168
|
+
author = node.at(ns("./author"))
|
156
169
|
source = node.at(ns("./source"))
|
157
|
-
|
170
|
+
out.p **{ class: "QuoteAttribution" } do |p|
|
171
|
+
p << "— #{author.text}, " if author
|
172
|
+
eref_parse(source, p)
|
173
|
+
end
|
158
174
|
end
|
159
175
|
|
160
176
|
def quote_parse(node, out)
|
161
177
|
attrs = para_attrs(node)
|
162
178
|
attrs[:class] = "Quote"
|
163
|
-
out.
|
179
|
+
out.div **attr_code(attrs) do |p|
|
164
180
|
node.children.each do
|
165
181
|
|n| parse(n, p) unless ["author", "source"].include? n.name
|
166
182
|
end
|
data/lib/isodoc/cleanup.rb
CHANGED
@@ -11,9 +11,18 @@ module IsoDoc
|
|
11
11
|
inline_header_cleanup(docxml)
|
12
12
|
figure_cleanup(docxml)
|
13
13
|
table_cleanup(docxml)
|
14
|
+
admonition_cleanup(docxml)
|
14
15
|
docxml
|
15
16
|
end
|
16
17
|
|
18
|
+
def admonition_cleanup(docxml)
|
19
|
+
docxml.xpath("//div[@class = 'Admonition'][title]").each do |d|
|
20
|
+
title = d.at("./title")
|
21
|
+
n = title.next_element
|
22
|
+
n&.children&.first&.add_previous_sibling(title.text + "—")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
17
26
|
def figure_get_or_make_dl(t)
|
18
27
|
dl = t.at(".//dl")
|
19
28
|
if dl.nil?
|
@@ -29,8 +38,8 @@ module IsoDoc
|
|
29
38
|
|
30
39
|
def figure_aside_process(f, aside, key)
|
31
40
|
# get rid of footnote link, it is in diagram
|
32
|
-
f.at("./a[@class='
|
33
|
-
fnref = f.at(".//a[@class='
|
41
|
+
f.at("./a[@class='TableFootnoteRef']").remove
|
42
|
+
fnref = f.at(".//a[@class='TableFootnoteRef']")
|
34
43
|
dt = key.add_child("<dt></dt>").first
|
35
44
|
dd = key.add_child("<dd></dd>").first
|
36
45
|
fnref.parent = dt
|
@@ -64,26 +73,15 @@ module IsoDoc
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
67
|
-
def comment_cleanup(docxml)
|
68
|
-
docxml.xpath('//div/span[@style="MsoCommentReference"]').
|
69
|
-
each do |x|
|
70
|
-
prev = x.previous_element
|
71
|
-
x.parent = prev unless prev.nil?
|
72
|
-
end
|
73
|
-
docxml
|
74
|
-
end
|
75
|
-
|
76
76
|
def footnote_cleanup(docxml)
|
77
|
-
docxml.xpath('//
|
78
|
-
|
79
|
-
n = x.next_element
|
80
|
-
n&.children&.first&.add_previous_sibling(x.remove)
|
77
|
+
docxml.xpath('//a[@epub:type = "footnote"]/sup').each_with_index do |x, i|
|
78
|
+
x.content = (i + 1).to_s
|
81
79
|
end
|
82
80
|
docxml
|
83
81
|
end
|
84
82
|
|
85
83
|
def merge_fnref_into_fn_text(a)
|
86
|
-
fn = a.at('.//a[@class="
|
84
|
+
fn = a.at('.//a[@class="TableFootnoteRef"]')
|
87
85
|
n = fn.next_element
|
88
86
|
n&.children&.first&.add_previous_sibling(fn.remove)
|
89
87
|
end
|
@@ -113,7 +111,6 @@ module IsoDoc
|
|
113
111
|
t.add_child("<tfoot></tfoot>")
|
114
112
|
tfoot = t.at(".//tfoot")
|
115
113
|
else
|
116
|
-
# nuke its bottom border
|
117
114
|
tfoot.xpath(".//td | .//th").each { |td| remove_bottom_border(td) }
|
118
115
|
end
|
119
116
|
tfoot
|
@@ -135,10 +132,14 @@ module IsoDoc
|
|
135
132
|
docxml.xpath("//table[div[@class = 'Note']]").each do |t|
|
136
133
|
tfoot = table_get_or_make_tfoot(t)
|
137
134
|
insert_here = new_fullcolspan_row(t, tfoot)
|
138
|
-
t.xpath("div[@class = 'Note']").each
|
139
|
-
d.parent = insert_here
|
140
|
-
end
|
135
|
+
t.xpath("div[@class = 'Note']").each { |d| d.parent = insert_here }
|
141
136
|
end
|
137
|
+
# preempt html2doc putting MsoNormal there
|
138
|
+
docxml.xpath("//p[not(self::*[@class])]"\
|
139
|
+
"[ancestor::*[@class = 'Note']]").each do |p|
|
140
|
+
p["class"] = "Note"
|
141
|
+
end
|
142
|
+
|
142
143
|
end
|
143
144
|
|
144
145
|
def table_cleanup(docxml)
|
data/lib/isodoc/html.rb
CHANGED
@@ -2,13 +2,18 @@ module IsoDoc
|
|
2
2
|
class Convert
|
3
3
|
|
4
4
|
def toHTML(result, filename)
|
5
|
-
result =
|
6
|
-
result =
|
5
|
+
# result = html_cleanup(Nokogiri::HTML(result)).to_xml
|
6
|
+
result = from_xhtml(html_cleanup(to_xhtml(result)))
|
7
|
+
result = populate_template(result, :html)
|
7
8
|
File.open("#{filename}.html", "w") do |f|
|
8
9
|
f.write(result)
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
13
|
+
def html_cleanup(x)
|
14
|
+
footnote_backlinks(move_images(html_footnote_filter(htmlPreface(htmlstyle(x)))))
|
15
|
+
end
|
16
|
+
|
12
17
|
def htmlPreface(docxml)
|
13
18
|
cover = Nokogiri::HTML(File.read(@htmlcoverpage, encoding: "UTF-8"))
|
14
19
|
d = docxml.at('//div[@class="WordSection1"]')
|
@@ -39,5 +44,56 @@ module IsoDoc
|
|
39
44
|
end
|
40
45
|
docxml
|
41
46
|
end
|
47
|
+
|
48
|
+
def update_footnote_filter(docxml, x, i, seen)
|
49
|
+
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || return
|
50
|
+
if seen[fn.text]
|
51
|
+
x.at("./sup").content = seen[fn.text][:num].to_s
|
52
|
+
fn.remove unless x["href"] == seen[fn.text][:href]
|
53
|
+
x["href"] = seen[fn.text][:href]
|
54
|
+
else
|
55
|
+
seen[fn.text] = { num: i, href: x["href"] }
|
56
|
+
x.at("./sup").content = i.to_s
|
57
|
+
i += 1
|
58
|
+
end
|
59
|
+
[i, seen]
|
60
|
+
end
|
61
|
+
|
62
|
+
def html_footnote_filter(docxml)
|
63
|
+
seen = {}
|
64
|
+
i = 1
|
65
|
+
docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
|
66
|
+
i, seen = update_footnote_filter(docxml, x, i, seen)
|
67
|
+
end
|
68
|
+
docxml
|
69
|
+
end
|
70
|
+
|
71
|
+
def footnote_backlinks(docxml)
|
72
|
+
seen = {}
|
73
|
+
docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
|
74
|
+
next if seen[x["href"]]
|
75
|
+
seen[x["href"]] = true
|
76
|
+
sup = x.at("./sup").text
|
77
|
+
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
|
78
|
+
x["id"] || x["id"] = "_footnote#{i + 1}"
|
79
|
+
fn.elements.first.children.first.
|
80
|
+
add_previous_sibling("<a href='##{x['id']}'>#{sup}) </a>")
|
81
|
+
end
|
82
|
+
docxml
|
83
|
+
end
|
84
|
+
|
85
|
+
def move_images(docxml)
|
86
|
+
system "rm -r _images; mkdir _images"
|
87
|
+
docxml.xpath("//*[local-name() = 'img']").each do |i|
|
88
|
+
matched = /\.(?<suffix>\S+)$/.match i["src"]
|
89
|
+
uuid = UUIDTools::UUID.random_create.to_s
|
90
|
+
new_full_filename = File.join("_images", "#{uuid}.#{matched[:suffix]}")
|
91
|
+
# presupposes that the image source is local
|
92
|
+
system "cp #{i['src']} #{new_full_filename}"
|
93
|
+
i["src"] = new_full_filename
|
94
|
+
i["width"], i["height"] = Html2Doc.image_resize(i, 800, 1200)
|
95
|
+
end
|
96
|
+
docxml
|
97
|
+
end
|
42
98
|
end
|
43
99
|
end
|
data/lib/isodoc/inline.rb
CHANGED
@@ -2,11 +2,6 @@ require "uuidtools"
|
|
2
2
|
|
3
3
|
module IsoDoc
|
4
4
|
class Convert
|
5
|
-
|
6
|
-
def in_footnote
|
7
|
-
@in_footnote
|
8
|
-
end
|
9
|
-
|
10
5
|
def section_break(body)
|
11
6
|
body.br **{ clear: "all", class: "section" }
|
12
7
|
end
|
@@ -30,35 +25,46 @@ module IsoDoc
|
|
30
25
|
|
31
26
|
def get_linkend(node)
|
32
27
|
linkend = node["target"] || node["citeas"]
|
33
|
-
|
28
|
+
get_anchors().has_key?(node["target"]) &&
|
34
29
|
linkend = get_anchors()[node["target"]][:xref]
|
35
|
-
end
|
36
30
|
if node["citeas"].nil? && get_anchors().has_key?(node["bibitemid"])
|
37
31
|
linkend = get_anchors()[node["bibitemid"]][:xref]
|
38
32
|
end
|
33
|
+
linkend += eref_localities(node.xpath(ns("./locality")))
|
39
34
|
text = node.children.select { |c| c.text? && !c.text.empty? }
|
40
35
|
linkend = text.join(" ") unless text.nil? || text.empty?
|
41
36
|
# so not <origin bibitemid="ISO7301" citeas="ISO 7301">
|
42
|
-
# <locality type="section">3.1</locality></origin>
|
37
|
+
# <locality type="section"><reference>3.1</reference></locality></origin>
|
43
38
|
linkend
|
44
39
|
end
|
45
40
|
|
46
41
|
def xref_parse(node, out)
|
47
42
|
linkend = get_linkend(node)
|
48
|
-
out.a **{ "href": node["target"] } { |l| l << linkend }
|
43
|
+
out.a **{ "href": "#" + node["target"] } { |l| l << linkend }
|
44
|
+
end
|
45
|
+
|
46
|
+
def eref_localities(r)
|
47
|
+
ret = ""
|
48
|
+
r.each do |r|
|
49
|
+
if r["type"] == "whole"
|
50
|
+
ret += ", Whole of text"
|
51
|
+
else
|
52
|
+
ret += ", #{r["type"].capitalize}"
|
53
|
+
ref = r.at(ns("./reference"))
|
54
|
+
ret += " #{ref.text}" if ref
|
55
|
+
end
|
56
|
+
end
|
57
|
+
ret
|
49
58
|
end
|
50
59
|
|
51
60
|
def eref_parse(node, out)
|
52
61
|
linkend = get_linkend(node)
|
53
|
-
section = node.at(ns("./locality"))
|
54
|
-
section.nil? or
|
55
|
-
linkend += ", #{section["type"].capitalize} #{section.text}"
|
56
62
|
if node["type"] == "footnote"
|
57
63
|
out.sup do |s|
|
58
|
-
s.a **{ "href": node["bibitemid"] } { |l| l << linkend }
|
64
|
+
s.a **{ "href": "#" + node["bibitemid"] } { |l| l << linkend }
|
59
65
|
end
|
60
66
|
else
|
61
|
-
out.a **{ "href": node["bibitemid"] } { |l| l << linkend }
|
67
|
+
out.a **{ "href": "#" + node["bibitemid"] } { |l| l << linkend }
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
@@ -68,144 +74,21 @@ module IsoDoc
|
|
68
74
|
else
|
69
75
|
node.text
|
70
76
|
end
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def pagebreak_parse(node, out)
|
77
|
-
attrs = { clear: all, class: "pagebreak" }
|
78
|
-
out.br **attrs
|
79
|
-
end
|
80
|
-
|
81
|
-
def error_parse(node, out)
|
82
|
-
text = node.to_xml.gsub(/</, "<").gsub(/>/, ">")
|
83
|
-
out.para do |p|
|
84
|
-
p.b **{ role: "strong" } { |e| e << text }
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def footnotes(div)
|
89
|
-
return if @footnotes.empty?
|
90
|
-
div.div **{ style: "mso-element:footnote-list" } do |div1|
|
91
|
-
@footnotes.each do |fn|
|
92
|
-
div1.parent << fn
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def footnote_attributes(fn, is_footnote)
|
98
|
-
style = nil
|
99
|
-
style = "mso-footnote-id:ftn#{fn}" if is_footnote
|
100
|
-
{ style: style,
|
101
|
-
href: "#_ftn#{fn}",
|
102
|
-
name: "_ftnref#{fn}",
|
103
|
-
title: "",
|
104
|
-
class: "zzFootnote" }
|
105
|
-
end
|
106
|
-
|
107
|
-
def make_footnote_link(a, fnid, fnref, is_footnote)
|
108
|
-
a.span **{ class: "MsoFootnoteReference" } do |s|
|
109
|
-
if is_footnote
|
110
|
-
s.span **{ style: "mso-special-character:footnote" }
|
111
|
-
else
|
112
|
-
s.a **{href: fnid} { a << fnref }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def make_footnote_target(a, fnid, fnref, is_footnote)
|
118
|
-
a.span **{ class: "MsoFootnoteReference" } do |s|
|
119
|
-
if is_footnote
|
120
|
-
s.span **{ style: "mso-special-character:footnote" }
|
121
|
-
else
|
122
|
-
s.a **{name: fnid} { a << fnref }
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def make_footnote_text(node, fnid, fnref, is_footnote)
|
128
|
-
attrs = { style: "mso-element:footnote", id: "ftn#{fnid}" }
|
129
|
-
attrs[:style] = nil unless is_footnote
|
130
|
-
noko do |xml|
|
131
|
-
xml.div **attr_code(attrs) do |div|
|
132
|
-
div.a **footnote_attributes(fnid, is_footnote) do |a|
|
133
|
-
make_footnote_target(a, fnid, fnref, is_footnote)
|
134
|
-
insert_tab(a, 1) unless is_footnote
|
135
|
-
end
|
136
|
-
node.children.each { |n| parse(n, div) }
|
137
|
-
end
|
138
|
-
end.join("\n")
|
139
|
-
end
|
140
|
-
|
141
|
-
def get_table_ancestor_id(node)
|
142
|
-
table = node.ancestors("table") || node.ancestors("figure")
|
143
|
-
return UUIDTools::UUID.random_create.to_s if table.empty?
|
144
|
-
table.last["id"]
|
145
|
-
end
|
146
|
-
|
147
|
-
def table_footnote_parse(node, out)
|
148
|
-
fn = node["reference"]
|
149
|
-
tid = get_table_ancestor_id(node)
|
150
|
-
out.a **footnote_attributes(tid + fn, false) do |a|
|
151
|
-
make_footnote_link(a, tid + fn, fn, false)
|
152
|
-
end
|
153
|
-
# do not output footnote text if we have already seen it for this table
|
154
|
-
return if @seen_footnote.include?(tid + fn)
|
155
|
-
@in_footnote = true
|
156
|
-
out.aside { |a| a << make_footnote_text(node, tid + fn, fn, false) }
|
157
|
-
@in_footnote = false
|
158
|
-
@seen_footnote << (tid + fn)
|
159
|
-
end
|
160
|
-
|
161
|
-
def footnote_parse(node, out)
|
162
|
-
return table_footnote_parse(node, out) if @in_table || @in_figure
|
163
|
-
fn = node["reference"]
|
164
|
-
out.a **footnote_attributes(fn, true) do |a|
|
165
|
-
make_footnote_link(a, nil, nil, true)
|
166
|
-
end
|
167
|
-
@in_footnote = true
|
168
|
-
@footnotes << make_footnote_text(node, fn, fn, true)
|
169
|
-
@in_footnote = false
|
170
|
-
end
|
171
|
-
|
172
|
-
def comments(div)
|
173
|
-
return if @comments.empty?
|
174
|
-
div.div **{ style: "mso-element:comment-list" } do |div1|
|
175
|
-
@comments.each do |fn|
|
176
|
-
div1.parent << fn
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def make_comment_link(out, fn, date, from)
|
182
|
-
out.span **{ style: "MsoCommentReference" } do |s1|
|
183
|
-
s1.span **{ lang: "EN-GB", style: "font-size:9.0pt"} do |s2|
|
184
|
-
s2.a **{ style: "mso-comment-reference:SMC_#{fn};"\
|
185
|
-
"mso-comment-date:#{date}" } if from
|
186
|
-
s2.span **{ style: "mso-special-character:comment" } do |s|
|
187
|
-
s << " "
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
77
|
+
out.span **{ class: "stem" } do |span|
|
78
|
+
span.parent.add_child ooml
|
191
79
|
end
|
80
|
+
end
|
192
81
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
div.p **{ class: "MsoCommentText" } do |p|
|
198
|
-
make_comment_link(p, fn, node["date"], false)
|
199
|
-
node.children.each { |n| parse(n, p) }
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end.join("\n")
|
203
|
-
end
|
82
|
+
def pagebreak_parse(node, out)
|
83
|
+
attrs = { clear: all, class: "pagebreak" }
|
84
|
+
out.br **attrs
|
85
|
+
end
|
204
86
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
87
|
+
def error_parse(node, out)
|
88
|
+
text = node.to_xml.gsub(/</, "<").gsub(/>/, ">")
|
89
|
+
out.para do |p|
|
90
|
+
p.b **{ role: "strong" } { |e| e << text }
|
209
91
|
end
|
92
|
+
end
|
210
93
|
end
|
211
94
|
end
|
data/lib/isodoc/iso2wordhtml.rb
CHANGED
@@ -22,8 +22,7 @@ module IsoDoc
|
|
22
22
|
|
23
23
|
def make_body1(body, docxml)
|
24
24
|
body.div **{ class: "WordSection1" } do |div1|
|
25
|
-
# placeholder
|
26
|
-
div1.p { |p| p << " " }
|
25
|
+
div1.p { |p| p << " " } # placeholder
|
27
26
|
end
|
28
27
|
section_break(body)
|
29
28
|
end
|
@@ -31,6 +30,7 @@ module IsoDoc
|
|
31
30
|
def make_body2(body, docxml)
|
32
31
|
body.div **{ class: "WordSection2" } do |div2|
|
33
32
|
info docxml, div2
|
33
|
+
div2.p { |p| p << " " } # placeholder
|
34
34
|
end
|
35
35
|
section_break(body)
|
36
36
|
end
|
@@ -49,6 +49,7 @@ module IsoDoc
|
|
49
49
|
subtitle isoxml, out
|
50
50
|
id isoxml, out
|
51
51
|
author isoxml, out
|
52
|
+
bibdate isoxml, out
|
52
53
|
version isoxml, out
|
53
54
|
foreword isoxml, out
|
54
55
|
introduction isoxml, out
|
@@ -77,11 +78,16 @@ module IsoDoc
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def text_parse(node, out)
|
81
|
+
return if node.nil? || node.text.nil?
|
80
82
|
text = node.text
|
81
|
-
text.gsub
|
83
|
+
text = text.gsub("\n", "<br/>").gsub(" ", " ") if in_sourcecode
|
82
84
|
out << text
|
83
85
|
end
|
84
86
|
|
87
|
+
def bookmark_parse(node, out)
|
88
|
+
out.a **attr_code(id: node["id"])
|
89
|
+
end
|
90
|
+
|
85
91
|
def parse(node, out)
|
86
92
|
if node.text?
|
87
93
|
text_parse(node, out)
|
@@ -96,6 +102,7 @@ module IsoDoc
|
|
96
102
|
when "smallcap" then smallcap_parse(node, out)
|
97
103
|
when "br" then out.br
|
98
104
|
when "hr" then out.hr
|
105
|
+
when "bookmark" then bookmark_parse(node, out)
|
99
106
|
when "pagebreak" then pagebreak_parse(node, out)
|
100
107
|
when "callout" then callout_parse(node, out)
|
101
108
|
when "stem" then stem_parse(node, out)
|
@@ -119,6 +126,7 @@ module IsoDoc
|
|
119
126
|
when "formula" then formula_parse(node, out)
|
120
127
|
when "table" then table_parse(node, out)
|
121
128
|
when "figure" then figure_parse(node, out)
|
129
|
+
when "example" then example_parse(node, out)
|
122
130
|
when "image" then image_parse(node["src"], out, nil)
|
123
131
|
when "sourcecode" then sourcecode_parse(node, out)
|
124
132
|
when "annotation" then annotation_parse(node, out)
|
data/lib/isodoc/metadata.rb
CHANGED
@@ -3,6 +3,19 @@ require "htmlentities"
|
|
3
3
|
module IsoDoc
|
4
4
|
class Convert
|
5
5
|
|
6
|
+
def init_metadata
|
7
|
+
@meta = {
|
8
|
+
tc: "XXXX",
|
9
|
+
sc: "XXXX",
|
10
|
+
wg: "XXXX",
|
11
|
+
editorialgroup: [],
|
12
|
+
secretariat: "XXXX",
|
13
|
+
}
|
14
|
+
%w{published accessed created activated obsoleted}.each do |w|
|
15
|
+
@meta["#{w}date".to_sym] = "XXX"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
6
19
|
def get_metadata
|
7
20
|
@meta
|
8
21
|
end
|
@@ -11,22 +24,64 @@ module IsoDoc
|
|
11
24
|
@meta[key] = value
|
12
25
|
end
|
13
26
|
|
14
|
-
def author(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def author(xml, _out)
|
28
|
+
tc(xml)
|
29
|
+
sc(xml)
|
30
|
+
wg(xml)
|
31
|
+
secretariat(xml)
|
32
|
+
agency(xml)
|
33
|
+
end
|
34
|
+
|
35
|
+
def tc(xml)
|
36
|
+
tc_num = xml.at(ns("//editorialgroup/technical-committee/@number"))
|
37
|
+
tc_type = xml.at(ns("//editorialgroup/technical-committee/@type"))&.
|
38
|
+
text || "TC"
|
39
|
+
if tc_num
|
40
|
+
tcid = "#{tc_type} #{tc_num.text}"
|
41
|
+
set_metadata(:tc, tcid)
|
42
|
+
set_metadata(:editorialgroup, get_metadata[:editorialgroup] << tcid)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def sc(xml)
|
47
|
+
sc_num = xml.at(ns("//editorialgroup/subcommittee/@number"))
|
48
|
+
sc_type = xml.at(ns("//editorialgroup/subcommittee/@type"))&.text || "SC"
|
49
|
+
if sc_num
|
50
|
+
scid = "#{sc_type} #{sc_num.text}"
|
51
|
+
set_metadata(:sc, scid)
|
52
|
+
set_metadata(:editorialgroup, get_metadata[:editorialgroup] << scid)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def wg(xml)
|
57
|
+
wg_num = xml.at(ns("//editorialgroup/workgroup/@number"))
|
58
|
+
wg_type = xml.at(ns("//editorialgroup/workgroup/@type"))&.text || "WG"
|
59
|
+
if wg_num
|
60
|
+
wgid = "#{wg_type} #{wg_num.text}"
|
61
|
+
set_metadata(:wg, wgid)
|
62
|
+
set_metadata(:editorialgroup, get_metadata[:editorialgroup] << wgid)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def secretariat(xml)
|
67
|
+
sec = xml.at(ns("//editorialgroup/secretariat"))
|
68
|
+
set_metadata(:secretariat, sec.text) if sec
|
69
|
+
end
|
70
|
+
|
71
|
+
def bibdate(isoxml, _out)
|
72
|
+
isoxml.xpath(ns("//bibdata/date")).each do |d|
|
73
|
+
set_metadata("#{d["type"]}date".to_sym, d.text)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def agency(xml)
|
78
|
+
agency = ""
|
79
|
+
pub = xml.xpath(ns("//bibdata/contributor"\
|
80
|
+
"[xmlns:role/@type = 'publisher']/"\
|
81
|
+
"organization/name")).each do |org|
|
82
|
+
agency = org.text == "ISO" ? "ISO/#{agency}" : "#{agency}#{org.text}/"
|
83
|
+
end
|
84
|
+
set_metadata(:agency, agency.sub(%r{/$}, ""))
|
30
85
|
end
|
31
86
|
|
32
87
|
def id(isoxml, _out)
|
@@ -66,33 +121,41 @@ module IsoDoc
|
|
66
121
|
set_metadata(:draftinfo, draftinfo(draft, revdate))
|
67
122
|
end
|
68
123
|
|
124
|
+
def part_label(lang)
|
125
|
+
case lang
|
126
|
+
when "en" then "Part"
|
127
|
+
when "fr" then "Part"
|
128
|
+
end
|
129
|
+
end
|
69
130
|
|
70
|
-
def compose_title(main, intro, part,
|
131
|
+
def compose_title(main, intro, part, partnum, lang)
|
71
132
|
c = HTMLEntities.new
|
72
133
|
main = c.encode(main.text, :hexadecimal)
|
73
134
|
intro &&
|
74
135
|
main = "#{c.encode(intro.text, :hexadecimal)} — #{main}"
|
75
|
-
part
|
76
|
-
|
77
|
-
"#{
|
136
|
+
if part
|
137
|
+
suffix = c.encode(part.text, :hexadecimal)
|
138
|
+
suffix = "#{part_label(lang)} #{partnum}: " + suffix if partnum
|
139
|
+
main = "#{main} — #{suffix}"
|
140
|
+
end
|
78
141
|
main
|
79
142
|
end
|
80
143
|
|
81
144
|
def title(isoxml, _out)
|
82
|
-
intro = isoxml.at(ns("//title[@language='en']
|
83
|
-
main = isoxml.at(ns("//title[@language='en']
|
84
|
-
part = isoxml.at(ns("//title[@language='en']
|
85
|
-
partnumber = isoxml.at(ns("//
|
86
|
-
main = compose_title(main, intro, part, partnumber)
|
145
|
+
intro = isoxml.at(ns("//title-intro[@language='en']"))
|
146
|
+
main = isoxml.at(ns("//title-main[@language='en']"))
|
147
|
+
part = isoxml.at(ns("//title-part[@language='en']"))
|
148
|
+
partnumber = isoxml.at(ns("//project-number/@part"))
|
149
|
+
main = compose_title(main, intro, part, partnumber, "en")
|
87
150
|
set_metadata(:doctitle, main)
|
88
151
|
end
|
89
152
|
|
90
153
|
def subtitle(isoxml, _out)
|
91
|
-
intro = isoxml.at(ns("//title[@language='fr']
|
92
|
-
main = isoxml.at(ns("//title[@language='fr']
|
93
|
-
part = isoxml.at(ns("//title[@language='fr']
|
94
|
-
partnumber = isoxml.at(ns("//
|
95
|
-
main = compose_title(main, intro, part, partnumber)
|
154
|
+
intro = isoxml.at(ns("//title-intro[@language='fr']"))
|
155
|
+
main = isoxml.at(ns("//title-main[@language='fr']"))
|
156
|
+
part = isoxml.at(ns("//title-part[@language='fr']"))
|
157
|
+
partnumber = isoxml.at(ns("//project-number/@part"))
|
158
|
+
main = compose_title(main, intro, part, partnumber, "fr")
|
96
159
|
set_metadata(:docsubtitle, main)
|
97
160
|
end
|
98
161
|
end
|
data/lib/isodoc/notes.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require "uuidtools"
|
2
|
+
|
3
|
+
module IsoDoc
|
4
|
+
class Convert
|
5
|
+
def in_footnote
|
6
|
+
@in_footnote
|
7
|
+
end
|
8
|
+
|
9
|
+
def in_comment
|
10
|
+
@in_comment
|
11
|
+
end
|
12
|
+
|
13
|
+
def footnotes(div)
|
14
|
+
return if @footnotes.empty?
|
15
|
+
@footnotes.each { |fn| div.parent << fn }
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_table_footnote_link(out, fnid, fnref)
|
19
|
+
attrs = { href: "##{fnid}", class: "TableFootnoteRef" }
|
20
|
+
out.a **attrs do |a|
|
21
|
+
a << fnref
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_table_footnote_target(out, fnid, fnref)
|
26
|
+
attrs = { id: fnid, class: "TableFootnoteRef" }
|
27
|
+
out.a **attrs do |a|
|
28
|
+
a << fnref
|
29
|
+
insert_tab(a, 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def make_table_footnote_text(node, fnid, fnref)
|
34
|
+
attrs = { id: "ftn#{fnid}" }
|
35
|
+
noko do |xml|
|
36
|
+
xml.div **attr_code(attrs) do |div|
|
37
|
+
make_table_footnote_target(div, fnid, fnref)
|
38
|
+
node.children.each { |n| parse(n, div) }
|
39
|
+
end
|
40
|
+
end.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
def make_generic_footnote_text(node, fnid, fn_ref)
|
44
|
+
noko do |xml|
|
45
|
+
xml.aside **{ id: "ftn#{fnid}" } do |div|
|
46
|
+
node.children.each { |n| parse(n, div) }
|
47
|
+
end
|
48
|
+
end.join("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_table_ancestor_id(node)
|
52
|
+
table = node.ancestors("table") || node.ancestors("figure")
|
53
|
+
return UUIDTools::UUID.random_create.to_s if table.empty?
|
54
|
+
table.last["id"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def table_footnote_parse(node, out)
|
58
|
+
fn = node["reference"]
|
59
|
+
tid = get_table_ancestor_id(node)
|
60
|
+
make_table_footnote_link(out, tid + fn, fn)
|
61
|
+
# do not output footnote text if we have already seen it for this table
|
62
|
+
return if @seen_footnote.include?(tid + fn)
|
63
|
+
@in_footnote = true
|
64
|
+
out.aside { |a| a << make_table_footnote_text(node, tid + fn, fn) }
|
65
|
+
@in_footnote = false
|
66
|
+
@seen_footnote << (tid + fn)
|
67
|
+
end
|
68
|
+
|
69
|
+
def footnote_parse(node, out)
|
70
|
+
return table_footnote_parse(node, out) if @in_table || @in_figure
|
71
|
+
fn = node["reference"]
|
72
|
+
out.a **{"epub:type": "footnote", href: "#ftn#{fn}" } do |a|
|
73
|
+
a.sup { |sup| sup << fn }
|
74
|
+
end
|
75
|
+
return if @seen_footnote.include?(fn)
|
76
|
+
@in_footnote = true
|
77
|
+
@footnotes << make_generic_footnote_text(node, fn, fn)
|
78
|
+
@in_footnote = false
|
79
|
+
@seen_footnote << fn
|
80
|
+
end
|
81
|
+
|
82
|
+
def comments(div)
|
83
|
+
return if @comments.empty?
|
84
|
+
div.div **{ style: "mso-element:comment-list" } do |div1|
|
85
|
+
@comments.each { |fn| div1.parent << fn }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def review_note_parse(node, out)
|
90
|
+
fn = @comments.length + 1
|
91
|
+
make_comment_link(out, fn, node)
|
92
|
+
@in_comment = true
|
93
|
+
@comments << make_comment_text(node, fn)
|
94
|
+
@in_comment = false
|
95
|
+
end
|
96
|
+
|
97
|
+
# add in from and to links to move the comment into place
|
98
|
+
def make_comment_link(out, fn, node)
|
99
|
+
out.span **{ style: "MsoCommentReference", target: fn,
|
100
|
+
class: "commentLink", from: node['from'],
|
101
|
+
to: node['to']} do |s1|
|
102
|
+
s1.span **{ lang: "EN-GB", style: "font-size:9.0pt"} do |s2|
|
103
|
+
s2.a **{ style: "mso-comment-reference:SMC_#{fn};"\
|
104
|
+
"mso-comment-date:#{node['date']}"}
|
105
|
+
s2.span **{ style: "mso-special-character:comment",
|
106
|
+
target: fn } # do |s|
|
107
|
+
#s << " "
|
108
|
+
#end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def make_comment_target(out)
|
114
|
+
out.span **{ style: "MsoCommentReference" } do |s1|
|
115
|
+
s1.span **{ lang: "EN-GB", style: "font-size:9.0pt"} do |s2|
|
116
|
+
s2.span **{ style: "mso-special-character:comment" } # do |s|
|
117
|
+
# s << " "
|
118
|
+
# end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def make_comment_text(node, fn)
|
124
|
+
noko do |xml|
|
125
|
+
xml.div **{ style: "mso-element:comment", id: fn } do |div|
|
126
|
+
div.span **{ style: %{mso-comment-author:"#{node["reviewer"]}"} }
|
127
|
+
make_comment_target(div)
|
128
|
+
node.children.each { |n| parse(n, div) }
|
129
|
+
end
|
130
|
+
end.join("\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
def comment_cleanup(docxml)
|
134
|
+
move_comment_link_to_from(docxml)
|
135
|
+
reorder_comments_by_comment_link(docxml)
|
136
|
+
embed_comment_in_comment_list(docxml)
|
137
|
+
end
|
138
|
+
|
139
|
+
COMMENT_IN_COMMENT_LIST =
|
140
|
+
'//div[@style="mso-element:comment-list"]//'\
|
141
|
+
'span[@style="MsoCommentReference"]'
|
142
|
+
|
143
|
+
def embed_comment_in_comment_list(docxml)
|
144
|
+
docxml.xpath(COMMENT_IN_COMMENT_LIST).each do |x|
|
145
|
+
n = x.next_element
|
146
|
+
n&.children&.first&.add_previous_sibling(x.remove)
|
147
|
+
end
|
148
|
+
docxml
|
149
|
+
end
|
150
|
+
|
151
|
+
def move_comment_link_to_from1(x, fromlink, docxml)
|
152
|
+
x.remove
|
153
|
+
link = x.at(".//a")
|
154
|
+
fromlink.replace(x)
|
155
|
+
link.children = fromlink
|
156
|
+
end
|
157
|
+
|
158
|
+
def comment_attributes(docxml, x)
|
159
|
+
fromlink = docxml.at("//*[@id='#{x["from"]}']")
|
160
|
+
return(nil) if fromlink.nil?
|
161
|
+
tolink = docxml.at("//*[@id='#{x["to"]}']") || fromlink
|
162
|
+
target = docxml.at("//*[@id='#{x["target"]}']")
|
163
|
+
{ from: fromlink, to: tolink, target: target }
|
164
|
+
end
|
165
|
+
|
166
|
+
def wrap_comment_cont(from, target)
|
167
|
+
s = from.replace("<span style='mso-comment-continuation:#{target}'>")
|
168
|
+
s.first.children = from
|
169
|
+
end
|
170
|
+
|
171
|
+
def skip_comment_wrap(from)
|
172
|
+
from["style"] != "mso-special-character:comment"
|
173
|
+
end
|
174
|
+
|
175
|
+
def insert_comment_cont(from, to, target, docxml)
|
176
|
+
# includes_to = from.at(".//*[@id='#{to}']")
|
177
|
+
while !from.nil? && from["id"] != to
|
178
|
+
following = from.xpath("./following::*")
|
179
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{to}']")
|
180
|
+
while !incl_to.nil? && !from.nil? && skip_comment_wrap(from)
|
181
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{to}']")
|
182
|
+
end
|
183
|
+
wrap_comment_cont(from, target) if !from.nil?
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def move_comment_link_to_from(docxml)
|
188
|
+
docxml.xpath('//span[@style="MsoCommentReference"][@from]').each do |x|
|
189
|
+
attrs = comment_attributes(docxml, x) || next
|
190
|
+
move_comment_link_to_from1(x, attrs[:from], docxml)
|
191
|
+
insert_comment_cont(attrs[:from], x["to"], x["target"], docxml)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def get_comments_from_text(docxml, link_order)
|
196
|
+
comments = []
|
197
|
+
docxml.xpath("//div[@style='mso-element:comment']").each do |c|
|
198
|
+
next unless c["id"] && !link_order[c["id"]].nil?
|
199
|
+
comments << { text: c.remove.to_s, id: c["id"] }
|
200
|
+
end
|
201
|
+
comments.sort! { |a, b| link_order[a[:id]] <=> link_order[b[:id]] }
|
202
|
+
comments
|
203
|
+
end
|
204
|
+
|
205
|
+
COMMENT_TARGET_XREFS =
|
206
|
+
"//span[@style='mso-special-character:comment']/@target"
|
207
|
+
|
208
|
+
def reorder_comments_by_comment_link(docxml)
|
209
|
+
link_order = {}
|
210
|
+
docxml.xpath(COMMENT_TARGET_XREFS).each_with_index do |target, i|
|
211
|
+
link_order[target.value] = i
|
212
|
+
end
|
213
|
+
comments = get_comments_from_text(docxml, link_order)
|
214
|
+
list = docxml.at("//*[@style='mso-element:comment-list']") or return
|
215
|
+
list.children = comments.map { |c| c[:text] }.join("\n")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "html2doc"
|
2
2
|
require "htmlentities"
|
3
3
|
require "nokogiri"
|
4
|
+
require "liquid"
|
4
5
|
require "pp"
|
5
6
|
|
6
7
|
module IsoDoc
|
@@ -15,7 +16,7 @@ module IsoDoc
|
|
15
16
|
|
16
17
|
def toWord(result, filename, dir)
|
17
18
|
result = from_xhtml(wordCleanup(to_xhtml(result)))
|
18
|
-
result = populate_template(result)
|
19
|
+
result = populate_template(result, :word)
|
19
20
|
Html2Doc.process(result, filename, @wordstylesheet, "header.html",
|
20
21
|
dir, ['`', '`'])
|
21
22
|
end
|
@@ -45,33 +46,24 @@ module IsoDoc
|
|
45
46
|
d.children.first.add_previous_sibling intro.to_xml(encoding: 'US-ASCII')
|
46
47
|
end
|
47
48
|
|
48
|
-
def populate_template(docxml)
|
49
|
+
def populate_template(docxml, _format)
|
49
50
|
meta = get_metadata
|
50
51
|
docxml.
|
51
|
-
gsub(/DOCYEAR/, meta[:docyear]).
|
52
|
-
gsub(/DOCNUMBER/, meta[:docnumber]).
|
53
|
-
gsub(/TCNUM/, meta[:tc]).
|
54
|
-
gsub(/SCNUM/, meta[:sc]).
|
55
|
-
gsub(/WGNUM/, meta[:wg]).
|
56
|
-
gsub(/DOCTITLE/, meta[:doctitle]).
|
57
|
-
gsub(/DOCSUBTITLE/, meta[:docsubtitle]).
|
58
|
-
gsub(/SECRETARIAT/, meta[:secretariat]).
|
59
|
-
gsub(/[ ]?DRAFTINFO/, meta[:draftinfo]).
|
60
52
|
gsub(/\[TERMREF\]\s*/, "[SOURCE: ").
|
61
53
|
gsub(/\s*\[\/TERMREF\]\s*/, "]").
|
62
54
|
gsub(/\s*\[ISOSECTION\]/, ", ").
|
63
|
-
gsub(/\s*\[MODIFICATION\]/, ", modified — ")
|
64
|
-
|
55
|
+
gsub(/\s*\[MODIFICATION\]/, ", modified — ")
|
56
|
+
template = Liquid::Template.parse(docxml)
|
57
|
+
template.render(meta.map { |k, v| [k.to_s, v] }.to_h)
|
65
58
|
end
|
66
59
|
|
67
60
|
def generate_header(filename, dir)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
gsub(/DOCNUMBER/, get_metadata()[:docnumber])
|
61
|
+
template = Liquid::Template.parse(File.read(@header, encoding: "UTF-8"))
|
62
|
+
meta = get_metadata
|
63
|
+
meta[:filename] = filename
|
64
|
+
params = meta.map { |k, v| [k.to_s, v] }.to_h
|
73
65
|
File.open("header.html", "w") do |f|
|
74
|
-
f.write(
|
66
|
+
f.write(template.render(params))
|
75
67
|
end
|
76
68
|
end
|
77
69
|
|
@@ -138,8 +130,17 @@ module IsoDoc
|
|
138
130
|
TOC
|
139
131
|
|
140
132
|
def header_strip(h)
|
141
|
-
h.to_s.gsub(%r{<br/>}, " ").
|
133
|
+
h = h.to_s.gsub(%r{<br/>}, " ").
|
142
134
|
sub(/<h[12][^>]*>/, "").sub(%r{</h[12]>}, "")
|
135
|
+
h1 = to_xhtml_fragment(h)
|
136
|
+
#h1.xpath(".//*[@style = 'MsoCommentReference']").each do |x|
|
137
|
+
h1.xpath(".//*").each do |x|
|
138
|
+
if x.name == "span" && x['style'] == "MsoCommentReference"
|
139
|
+
x.children.remove
|
140
|
+
x.content = ""
|
141
|
+
end
|
142
|
+
end
|
143
|
+
from_xhtml(h1)
|
143
144
|
end
|
144
145
|
|
145
146
|
def makeWordToC(docxml)
|
data/lib/isodoc/references.rb
CHANGED
@@ -2,20 +2,18 @@ module IsoDoc
|
|
2
2
|
class Convert
|
3
3
|
def iso_bibitem_ref_code(b)
|
4
4
|
isocode = b.at(ns("./docidentifier"))
|
5
|
-
isodate = b.at(ns("./
|
5
|
+
isodate = b.at(ns("./date[@type = 'published']"))
|
6
6
|
reference = "ISO #{isocode.text}"
|
7
7
|
reference += ": #{isodate.text}" if isodate
|
8
8
|
reference
|
9
9
|
end
|
10
10
|
|
11
11
|
def date_note_process(b, ref)
|
12
|
-
date_note = b.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
footnote_parse(date_note.first, ref)
|
18
|
-
end
|
12
|
+
date_note = b.at(ns("./note[text()][contains(.,'ISO DATE:')]"))
|
13
|
+
return if date_note.nil?
|
14
|
+
date_note.content = date_note.content.gsub(/ISO DATE: /, "")
|
15
|
+
date_note.children.first.replace("<p>#{date_note.content}</p>")
|
16
|
+
footnote_parse(date_note, ref)
|
19
17
|
end
|
20
18
|
|
21
19
|
def iso_bibitem_entry(list, b, ordinal, biblio)
|
@@ -28,7 +26,7 @@ module IsoDoc
|
|
28
26
|
ref << iso_bibitem_ref_code(b)
|
29
27
|
date_note_process(b, ref)
|
30
28
|
ref << ", " if biblio
|
31
|
-
ref.i { |i| i << " #{b.at(ns('./
|
29
|
+
ref.i { |i| i << " #{b.at(ns('./title')).text}" }
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
@@ -54,18 +52,21 @@ module IsoDoc
|
|
54
52
|
|
55
53
|
def noniso_bibitem(list, b, ordinal, bibliography)
|
56
54
|
ref = b.at(ns("./docidentifier"))
|
57
|
-
para = b.at(ns("./
|
55
|
+
para = b.at(ns("./formattedref"))
|
58
56
|
list.p **attr_code("id": b["id"], class: "Biblio") do |r|
|
59
57
|
ref_entry_code(r, ordinal, ref.text.gsub(/[\[\]]/, ""))
|
60
58
|
para.children.each { |n| parse(n, r) }
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
62
|
+
ISO_PUBLISHER_XPATH =
|
63
|
+
"./contributor[xmlns:role/@type = 'publisher']/organization[name = 'ISO']"
|
64
|
+
|
64
65
|
def split_bibitems(f)
|
65
66
|
iso_bibitem = []
|
66
67
|
non_iso_bibitem = []
|
67
68
|
f.xpath(ns("./bibitem")).each do |x|
|
68
|
-
if x.at(ns(
|
69
|
+
if x.at(ns(ISO_PUBLISHER_XPATH)).nil?
|
69
70
|
non_iso_bibitem << x
|
70
71
|
else
|
71
72
|
iso_bibitem << x
|
@@ -99,12 +100,15 @@ module IsoDoc
|
|
99
100
|
refs = f.elements.select do |e|
|
100
101
|
["reference", "bibitem"].include? e.name
|
101
102
|
end
|
102
|
-
pref = refs.empty?
|
103
|
+
pref = if refs.empty? then self.class::NORM_EMPTY_PREF
|
104
|
+
else
|
105
|
+
self.class::NORM_WITH_REFS_PREF
|
106
|
+
end
|
103
107
|
div.p pref
|
104
108
|
end
|
105
109
|
|
106
110
|
def norm_ref(isoxml, out)
|
107
|
-
q = "
|
111
|
+
q = "./*/references[title = 'Normative References']"
|
108
112
|
f = isoxml.at(ns(q)) or return
|
109
113
|
out.div do |div|
|
110
114
|
clause_name("2.", "Normative References", div, false)
|
@@ -114,7 +118,7 @@ module IsoDoc
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def bibliography(isoxml, out)
|
117
|
-
q = "
|
121
|
+
q = "./*/references[title = 'Bibliography']"
|
118
122
|
f = isoxml.at(ns(q)) or return
|
119
123
|
page_break(out)
|
120
124
|
out.div do |div|
|
data/lib/isodoc/section.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module IsoDoc
|
2
2
|
class Convert
|
3
3
|
def clause_parse(node, out)
|
4
|
-
out.div **attr_code(
|
4
|
+
out.div **attr_code(id: node["id"]) do |s|
|
5
5
|
node.children.each do |c1|
|
6
6
|
if c1.name == "title"
|
7
7
|
if node["inline-header"]
|
@@ -42,7 +42,7 @@ module IsoDoc
|
|
42
42
|
def clause(isoxml, out)
|
43
43
|
isoxml.xpath(ns("//clause[parent::sections]")).each do |c|
|
44
44
|
next if c.at(ns("./title")).text == "Scope"
|
45
|
-
out.div **attr_code(
|
45
|
+
out.div **attr_code(id: c["id"]) do |s|
|
46
46
|
c.elements.each do |c1|
|
47
47
|
if c1.name == "title"
|
48
48
|
clause_name("#{get_anchors()[c['id']][:label]}.",
|
@@ -65,7 +65,7 @@ module IsoDoc
|
|
65
65
|
def annex(isoxml, out)
|
66
66
|
isoxml.xpath(ns("//annex")).each do |c|
|
67
67
|
page_break(out)
|
68
|
-
out.div **attr_code(
|
68
|
+
out.div **attr_code(id: c["id"], class: "Section3" ) do |s|
|
69
69
|
#s1.div **{ class: "annex" } do |s|
|
70
70
|
c.elements.each do |c1|
|
71
71
|
if c1.name == "title" then annex_name(c, c1, s)
|
@@ -80,7 +80,7 @@ module IsoDoc
|
|
80
80
|
|
81
81
|
def scope(isoxml, out)
|
82
82
|
f = isoxml.at(ns("//clause[title = 'Scope']")) || return
|
83
|
-
out.div do |div|
|
83
|
+
out.div **attr_code(id: f["id"]) do |div|
|
84
84
|
clause_name("1.", "Scope", div, false)
|
85
85
|
f.elements.each do |e|
|
86
86
|
parse(e, div) unless e.name == "title"
|
@@ -90,7 +90,7 @@ module IsoDoc
|
|
90
90
|
|
91
91
|
def terms_defs(isoxml, out)
|
92
92
|
f = isoxml.at(ns("//terms")) || return
|
93
|
-
out.div do |div|
|
93
|
+
out.div **attr_code(id: f["id"]) do |div|
|
94
94
|
clause_name("3.", "Terms and Definitions", div, false)
|
95
95
|
f.elements.each do |e|
|
96
96
|
parse(e, div) unless e.name == "title"
|
@@ -100,7 +100,7 @@ module IsoDoc
|
|
100
100
|
|
101
101
|
def symbols_abbrevs(isoxml, out)
|
102
102
|
f = isoxml.at(ns("//symbols-abbrevs")) || return
|
103
|
-
out.div do |div|
|
103
|
+
out.div **attr_code(id: f["id"]) do |div|
|
104
104
|
clause_name("4.", "Symbols and Abbreviations", div, false)
|
105
105
|
f.elements.each do |e|
|
106
106
|
parse(e, div) unless e.name == "title"
|
@@ -109,10 +109,10 @@ module IsoDoc
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def introduction(isoxml, out)
|
112
|
-
f = isoxml.at(ns("//
|
112
|
+
f = isoxml.at(ns("//introduction")) || return
|
113
113
|
title_attr = { class: "IntroTitle" }
|
114
114
|
page_break(out)
|
115
|
-
out.div **{ class: "Section3" } do |div|
|
115
|
+
out.div **{ class: "Section3", id: f["id"] } do |div|
|
116
116
|
div.h1 "Introduction", **attr_code(title_attr)
|
117
117
|
f.elements.each do |e|
|
118
118
|
if e.name == "patent-notice"
|
@@ -125,9 +125,9 @@ module IsoDoc
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def foreword(isoxml, out)
|
128
|
-
f = isoxml.at(ns("//
|
128
|
+
f = isoxml.at(ns("//foreword")) || return
|
129
129
|
page_break(out)
|
130
|
-
out.div do |s|
|
130
|
+
out.div **attr_code(id: f["id"]) do |s|
|
131
131
|
s.h1 **{ class: "ForewordTitle" } { |h1| h1 << "Foreword" }
|
132
132
|
f.elements.each { |e| parse(e, s) unless e.name == "title" }
|
133
133
|
end
|
data/lib/isodoc/utils.rb
CHANGED
@@ -58,14 +58,6 @@ module IsoDoc
|
|
58
58
|
end.to_h
|
59
59
|
end
|
60
60
|
|
61
|
-
NOKOHEAD = <<~HERE
|
62
|
-
<!DOCTYPE html SYSTEM
|
63
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
64
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
65
|
-
<head> <title></title> <meta charset="UTF-8" /> </head>
|
66
|
-
<body> </body> </html>
|
67
|
-
HERE
|
68
|
-
|
69
61
|
def to_xhtml(xml)
|
70
62
|
xml.gsub!(/<\?xml[^>]*>/, "")
|
71
63
|
unless /<!DOCTYPE /.match? xml
|
data/lib/isodoc/version.rb
CHANGED
data/lib/isodoc/xref_gen.rb
CHANGED
@@ -20,7 +20,7 @@ module IsoDoc
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def initial_anchor_names(d)
|
23
|
-
introduction_names(d.at(ns("//
|
23
|
+
introduction_names(d.at(ns("//introduction")))
|
24
24
|
section_names(d.at(ns("//clause[title = 'Scope']")), "1", 1)
|
25
25
|
section_names(d.at(ns(
|
26
26
|
"//references[title = 'Normative References']")), "2", 1)
|
@@ -135,8 +135,9 @@ module IsoDoc
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def introduction_names(clause)
|
138
|
+
return if clause.nil?
|
138
139
|
clause.xpath(ns("./subsection")).each_with_index do |c, i|
|
139
|
-
|
140
|
+
section_names1(c, "0.#{i + 1}", 2)
|
140
141
|
end
|
141
142
|
end
|
142
143
|
|
@@ -186,10 +187,10 @@ module IsoDoc
|
|
186
187
|
end
|
187
188
|
|
188
189
|
def reference_names(ref)
|
189
|
-
isopub = ref.at(ns(
|
190
|
+
isopub = ref.at(ns(ISO_PUBLISHER_XPATH))
|
190
191
|
docid = ref.at(ns("./docidentifier"))
|
191
192
|
return ref_names(ref) unless docid
|
192
|
-
date = ref.at(ns("./
|
193
|
+
date = ref.at(ns("./date[@type = 'published']"))
|
193
194
|
reference = format_ref(docid.text, isopub)
|
194
195
|
reference += ": #{date.text}" if date && isopub
|
195
196
|
@anchors[ref["id"]] = { xref: reference }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isodoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciimath
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: liquid
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: bundler
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -303,6 +317,7 @@ files:
|
|
303
317
|
- lib/isodoc/iso2wordhtml.rb
|
304
318
|
- lib/isodoc/lists.rb
|
305
319
|
- lib/isodoc/metadata.rb
|
320
|
+
- lib/isodoc/notes.rb
|
306
321
|
- lib/isodoc/postprocessing.rb
|
307
322
|
- lib/isodoc/references.rb
|
308
323
|
- lib/isodoc/section.rb
|