Module: IsoDoc::WordFunction::Comments

Included in:
IsoDoc::WordConvert
Defined in:
lib/isodoc/word_function/comments.rb

Constant Summary collapse

COMMENT_IN_COMMENT_LIST1 =
'//div[@style="mso-element:comment-list"]//' \
'span[@style="MsoCommentReference"]'.freeze
COMMENT_TARGET_XREFS1 =
"//span[@style='mso-special-character:comment']/@target".freeze

Instance Method Summary collapse

Instance Method Details

#comment_attributes(docxml, span) ⇒ Object



104
105
106
107
108
109
110
111
# File 'lib/isodoc/word_function/comments.rb', line 104

def comment_attributes(docxml, span)
  fromlink = docxml.at("//*[@id='#{span['from']}']")
  return(nil) if fromlink.nil?

  tolink = docxml.at("//*[@id='#{span['to']}']") || fromlink
  target = docxml.at("//*[@id='#{span['target']}']")
  { from: fromlink, to: tolink, target: target }
end

#comment_cleanup(docxml) ⇒ Object



53
54
55
56
57
58
# File 'lib/isodoc/word_function/comments.rb', line 53

def comment_cleanup(docxml)
  number_comments(docxml)
  move_comment_link_to_from(docxml)
  reorder_comments_by_comment_link(docxml)
  embed_comment_in_comment_list(docxml)
end

#comment_id_to_number(docxml) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/isodoc/word_function/comments.rb', line 76

def comment_id_to_number(docxml)
  ids = docxml.xpath("//span[@style='MsoCommentReference']").map do |x|
    x["target"]
  end
  ids.uniq.each_with_index.with_object({}) do |(id, i), m|
    m[id] = i + 1
  end
end


14
15
16
17
18
# File 'lib/isodoc/word_function/comments.rb', line 14

def comment_link_attrs(fnote, node)
  { style: "MsoCommentReference", target: fnote,
    class: "commentLink", from: node["source"],
    to: node["end"] }
end

#comments(docxml, out) ⇒ Object



4
5
6
7
8
9
10
11
12
# File 'lib/isodoc/word_function/comments.rb', line 4

def comments(docxml, out)
  c = docxml.xpath(ns("//fmt-annotation-body"))
  c.empty? and return
  out.div style: "mso-element:comment-list" do |div|
    @in_comment = true
    c.each { |fn| parse(fn, div) }
    @in_comment = false
  end
end

#embed_comment_in_comment_list(docxml) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/isodoc/word_function/comments.rb', line 89

def embed_comment_in_comment_list(docxml)
  docxml.xpath(COMMENT_IN_COMMENT_LIST1).each do |x|
    n = x.next_element
    n&.children&.first&.add_previous_sibling(x.remove)
  end
  docxml
end

#fmt_annotation_body_parse(node, out) ⇒ Object



45
46
47
48
49
50
51
# File 'lib/isodoc/word_function/comments.rb', line 45

def fmt_annotation_body_parse(node, out)
  out.div style: "mso-element:comment", id: node["id"] do |div|
    div.span style: %{mso-comment-author:"#{node['reviewer']}"}
    make_comment_target(div)
    children_parse(node, div)
  end
end

#fmt_annotation_start_parse(node, out) ⇒ Object



20
21
22
# File 'lib/isodoc/word_function/comments.rb', line 20

def fmt_annotation_start_parse(node, out)
  make_comment_link(out, node["target"], node)
end

#get_comments_from_text(docxml, link_order) ⇒ Object



147
148
149
150
151
152
153
154
# File 'lib/isodoc/word_function/comments.rb', line 147

def get_comments_from_text(docxml, link_order)
  comments = docxml.xpath("//div[@style='mso-element:comment']")
    .each_with_object([]) do |c, m|
    c["id"] && !link_order[c["id"]].nil? or next
    m << { text: c.remove.to_s, id: c["id"] }
  end
  comments.sort { |a, b| link_order[a[:id]] <=> link_order[b[:id]] }
end

#insert_comment_cont(from, upto, target) ⇒ Object



128
129
130
131
132
133
134
135
136
137
# File 'lib/isodoc/word_function/comments.rb', line 128

def insert_comment_cont(from, upto, target)
  while !from.nil? && from["id"] != upto
    following = from.xpath("./following::*")
    (from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
    while !incl_to.nil? && !from.nil? && skip_comment_wrap(from)
      (from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
    end
    wrap_comment_cont(from, target) if !from.nil?
  end
end

TODO: CONSOLIDATE add in from and to links to move the comment into place



26
27
28
29
30
31
32
33
34
35
# File 'lib/isodoc/word_function/comments.rb', line 26

def make_comment_link(out, fnote, node)
  out.span(**comment_link_attrs(fnote, node)) do |s1|
    s1.span lang: "EN-GB", style: "font-size:9.0pt" do |s2|
      s2.a style: "mso-comment-reference:SMC_#{fnote};" \
                      "mso-comment-date:#{node['date'].gsub(/[:-]+/,
                                                            '')}"
      s2.span style: "mso-special-character:comment", target: fnote
    end
  end
end

#make_comment_target(out) ⇒ Object



37
38
39
40
41
42
43
# File 'lib/isodoc/word_function/comments.rb', line 37

def make_comment_target(out)
  out.span style: "MsoCommentReference" do |s1|
    s1.span lang: "EN-GB", style: "font-size:9.0pt" do |s2|
      s2.span style: "mso-special-character:comment"
    end
  end
end


139
140
141
142
143
144
145
# File 'lib/isodoc/word_function/comments.rb', line 139

def move_comment_link_to_from(docxml)
  docxml.xpath('//span[@style="MsoCommentReference"][@from]').each do |x|
    attrs = comment_attributes(docxml, x) || next
    move_comment_link_to_from1(x, attrs[:from])
    insert_comment_cont(attrs[:from], x["to"], x["target"])
  end
end


97
98
99
100
101
102
# File 'lib/isodoc/word_function/comments.rb', line 97

def move_comment_link_to_from1(tolink, fromlink)
  tolink.remove
  link = tolink.at(".//a")
  fromlink.replace(tolink)
  link.children = fromlink
end

#number_comments(docxml) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/isodoc/word_function/comments.rb', line 60

def number_comments(docxml)
  map = comment_id_to_number(docxml)
  docxml.xpath("//span[@style='MsoCommentReference' or " \
  "'mso-special-character:comment']").each do |x|
    x["target"] &&= map[x["target"]]
  end
  docxml.xpath("//div[@style='mso-element:comment']").each do |x|
    x["id"] = map[x["id"]]
  end
  docxml.xpath("//a[@style]").each do |x|
    m = /mso-comment-reference:SMC_([^;]+);/.match(x["style"]) or next
    x["style"] = x["style"].sub(/mso-comment-reference:SMC_#{m[1]}/,
                                "mso-comment-reference:SMC_#{map[m[1]]}")
  end
end


159
160
161
162
163
164
165
166
167
# File 'lib/isodoc/word_function/comments.rb', line 159

def reorder_comments_by_comment_link(docxml)
  link_order = {}
  docxml.xpath(COMMENT_TARGET_XREFS1).each_with_index do |target, i|
    link_order[target.value] = i
  end
  comments = get_comments_from_text(docxml, link_order)
  list = docxml.at("//*[@style='mso-element:comment-list']") || return
  list.children = comments.map { |c| c[:text] }.join("\n")
end

#skip_comment_wrap(from) ⇒ Object



124
125
126
# File 'lib/isodoc/word_function/comments.rb', line 124

def skip_comment_wrap(from)
  from["style"] != "mso-special-character:comment"
end

#wrap_comment_cont(from, target) ⇒ Object



113
114
115
116
117
118
119
120
121
122
# File 'lib/isodoc/word_function/comments.rb', line 113

def wrap_comment_cont(from, target)
  if %w(ol ul li div p).include?(from.name)
    from.children.each do |c|
      wrap_comment_cont(c, target)
    end
  else
    s = from.replace("<span style='mso-comment-continuation:#{target}'>")
    s.first.children = from
  end
end