Class: KramdownRFC::KDRFC

Inherits:
Object show all
Defined in:
lib/kramdown-rfc/kdrfc-processor.rb

Constant Summary collapse

KDRFC_PREPEND =

)))

[ENV["KDRFC_PREPEND"]].compact
KDRFC_XML2RFC_FLAGS =
Array(ENV["KDRFC_XML2RFC_FLAGS"]&.split(","))
IDNITS_WEBSERVICE =

curl -s author-tools.ietf.org/api/idnits -X POST -F file=@draft-ietf-core-comi.txt -F hidetext=true

ENV["KRAMDOWN_IDNITS_WEBSERVICE"] ||
'https://author-tools.ietf.org/api/idnits'
XML2RFC_WEBSERVICE =

curl author-tools.ietf.org/api/render/text -X POST -F “file=@…”

ENV["KRAMDOWN_XML2RFC_WEBSERVICE"] ||
'https://author-tools.ietf.org/api/render/'
MODE_AS_FORMAT =
{
    "--text" => "text",
    "--html" => "html",
    "--v2v3" => "xml",
    "--pdf" => "pdf",
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeKDRFC

Returns a new instance of KDRFC.



14
15
16
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 14

def initialize
  @options = OpenStruct.new
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



12
13
14
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 12

def options
  @options
end

Instance Method Details

#checked_json(t) ⇒ Object



141
142
143
144
145
146
147
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 141

def checked_json(t)
  begin
    JSON.load(t)
  rescue => e
    raise IOError.new("*** JSON result: #{e.detailed_message}, #{diag}")
  end
end

#filename_ct(fn, ext) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 41

def filename_ct(fn, ext)
  bn = File.basename(fn, ".*")
  if r = ENV["KRAMDOWN_RFC_DOCREV"]
    bn << "-#{r}"
  end
  {filename: "#{bn}.#{ext}",
   content_type: "text/plain"}
end

#persistent_httpObject



149
150
151
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 149

def persistent_http
  $http ||= Net::HTTP::Persistent.new name: 'kramdown-rfc'
end

#process(fn) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 225

def process(fn)
  case fn
  when /(.*)\.xml\z/
    if @options.xml_only
      warn "*** You already have XML"
    else                        # FIXME: copy/paste
      process_the_xml(fn, $1)
    end
  when /(.*)\.mk?d\z/
    xml = "#$1.xml"
    process_mkd(fn, xml)
    process_the_xml(xml, $1) unless @options.xml_only
  when /(.*)\.txt\z/
    run_idnits(fn) if @options.idnits
  else
    raise ArgumentError.new("Unknown file type: #{fn}")
  end
end

#process_mkd(input, output) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 28

def process_mkd(input, output)
  warn "* converting locally from markdown #{input} to xml #{output}" if @options.verbose
  o, s = Open3.capture2(*KDRFC_PREPEND, "kramdown-rfc2629", *v3_flag?, input)
  if s.success?
    File.open(output, "w") do |fo|
      fo.print(o)
    end
    warn "* #{output} written" if @options.verbose
  else
    raise IOError.new("*** kramdown-rfc failed, status #{s.exitstatus}")
  end
end

#process_the_xml(fn, base) ⇒ Object



216
217
218
219
220
221
222
223
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 216

def process_the_xml(fn, base)
  process_xml(fn, "#{base}.prepped.xml", "--preptool") if @options.prep
  process_xml(fn, "#{base}.v2v3.xml", "--v2v3") if @options.v2v3
  process_xml(fn, "#{base}.txt") if @options.txt || @options.idnits
  process_xml(fn, "#{base}.html", "--html") if @options.html
  process_xml(fn, "#{base}.pdf", "--pdf") if @options.pdf
  run_idnits("#{base}.txt") if @options.idnits
end

#process_xml(*args) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 106

def process_xml(*args)
  if @options.remote
    process_xml_remotely(*args)
  else
    process_xml_locally(*args)
  end
end

#process_xml_locally(input, output, *flags) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 114

def process_xml_locally(input, output, *flags)
  warn "* converting locally from xml #{input} to txt #{output}" if @options.verbose
  begin
    o, s = Open3.capture2(*KDRFC_PREPEND, "xml2rfc", *v3_flag?, *flags, *KDRFC_XML2RFC_FLAGS, input)
    puts o
    if s.success?
      warn "* #{output} written" if @options.verbose
    else
      raise IOError.new("*** xml2rfc failed, status #{s.exitstatus} (possibly try with -r)")
    end
  rescue Errno::ENOENT
    warn "*** falling back to remote xml2rfc processing (web service)" # if @options.verbose
    process_xml_remotely(input, output, *flags)
  end
end

#process_xml_remotely(input, output, *flags) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 153

def process_xml_remotely(input, output, *flags)

  format = flags[0] || "--text"
  warn "* converting remotely from xml #{input} to #{format} #{output}" if @options.verbose
  maf = MODE_AS_FORMAT[format]
  unless maf
    raise ArgumentError.new("*** don't know how to convert remotely from xml #{input} to #{format} #{output}")
  end
  url = URI(XML2RFC_WEBSERVICE + maf)
  req = Net::HTTP::Post.new(url)
  form = [["file", File.open(input),
           filename_ct(input, "xml")]]
  diag = ["url/form: ", url, form].inspect
  req.set_form(form, 'multipart/form-data')
  warn "* requesting at #{url}" if @options.verbose
  t0 = Time.now
  res = persistent_http.request(url, req)
  warn "* elapsed time: #{Time.now - t0}" if @options.verbose
  case res
  when Net::HTTPBadRequest
    result = checked_json(res.body)
    raise IOError.new("*** Remote Error: #{result["error"]}")
  when Net::HTTPOK
    case res.content_type
    when 'application/json'
      if res.body == ''
        raise IOError.new("*** HTTP response is empty with status #{res.code}, not written")
      end
      # warn "* res.body #{res.body}" if @options.verbose
      result = checked_json(res.body)
      if logs = result["logs"]
        if errors = logs["errors"]
          errors.each do |err|
            warn("*** Error: #{err}")
          end
        end
        if warnings = logs["warnings"]
          warnings.each do |w|
            warn("** Warning: #{w}")
          end
        end
      end
      raise IOError.new("*** No useful result from remote") unless result["url"]
      res = persistent_http.request(URI(result["url"]))
      warn "* result content type #{res.content_type}" if @options.verbose
      if res.body == ''
        raise IOError.new("*** Second HTTP response is empty with status #{res.code}, not written")
      end
      File.open(output, "w") do |fo|
        fo.print(res.body)
      end
      warn "* #{output} written" if @options.verbose
    else
      warning = "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}, #{diag}"
      warning << "\n"
      warning << res.body
      raise IOError.new(warning)
    end
  else
    raise IOError.new("*** HTTP response: #{res.code}, #{diag}")
  end
end

#run_idnits(*args) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 50

def run_idnits(*args)
  if @options.remote
    run_idnits_remotely(*args)
  else
    run_idnits_locally(*args)
  end
end

#run_idnits_locally(txt_fn) ⇒ Object



58
59
60
61
62
63
64
65
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 58

def run_idnits_locally(txt_fn)
  warn "* running idnits locally in txt #{txt_fn}" if @options.verbose
  unless system("idnits", txt_fn)
    warn "*** problem #$? running idnits" if @options.verbose
    warn "*** problem running idnits -- falling back to remote idnits processing"
    run_idnits_remotely(txt_fn)
  end
end

#run_idnits_remotely(txt_fn) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 71

def run_idnits_remotely(txt_fn)
  url = URI(IDNITS_WEBSERVICE)
  req = Net::HTTP::Post.new(url)
  form = [["file", File.open(txt_fn),
           filename_ct(txt_fn, "txt")],
          ["hidetext", "true"]]
  diag = ["url/form: ", url, form].inspect
  req.set_form(form, 'multipart/form-data')
  warn "* requesting idnits at #{url}" if @options.verbose
  t0 = Time.now
  res = persistent_http.request(url, req)
  warn "* elapsed time: #{Time.now - t0}" if @options.verbose
  case res
  when Net::HTTPBadRequest
    result = checked_json(res.body)
    raise IOError.new("*** Remote Error: #{result["error"]}")
  when Net::HTTPOK
    case res.content_type
    when 'text/plain'
      if res.body == ''
        raise IOError.new("*** HTTP response is empty with status #{res.code}, not written")
      end
      puts res.body
    else
      warning = "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}, #{diag}"
      warning << "\n"
      warning << res.body
      raise IOError.new(warning)
    end
  else
    raise IOError.new("*** HTTP response: #{res.code}, #{diag}")
  end
end

#v3_flag?Boolean

Returns:

  • (Boolean)


23
24
25
26
# File 'lib/kramdown-rfc/kdrfc-processor.rb', line 23

def v3_flag?
  [*(@options.v3 ? ["--v3"] : []),
   *(@options.v2 ? ["--v2"] : [])]
end