Top Level Namespace
- Includes:
- Kramdown::Utils::Html
Defined Under Namespace
Modules: Gzip, Kramdown, KramdownRFC, REXML Classes: ERB, Object
Constant Summary collapse
- ACCEPT_CITE_JSON =
{"Accept" => "application/citeproc+json"}
- KDRFC_VERSION =
try to get this from gemspec.
Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version"
- RE_NL =
/(?:\r\n|\n|\r)/
- RE_SECTION =
/---(?: +(\w+)(-?))? *#{RE_NL}(.*?#{RE_NL})(?=---(?:\s+\w+-?)?\s*#{RE_NL}|\Z)/m
- NMDTAGS =
["{:/nomarkdown}\n\n", "\n\n{::nomarkdown}\n"]
- NORMINFORM =
{ "!" => :normative, "?" => :informative }
- XREF_SECTIONS_RE =
::Kramdown::Parser::RFC2629Kramdown::SECTIONS_RE
- XSR_PREFIX =
"#{XREF_SECTIONS_RE} of "
- XSR_SUFFIX =
", (#{XREF_SECTIONS_RE})| \\((#{XREF_SECTIONS_RE})\\)"
- XREF_TXT =
::Kramdown::Parser::RFC2629Kramdown::XREF_TXT
- XREF_TXT_SUFFIX =
" \\(#{XREF_TXT}\\)"
- XML_RESOURCE_ORG_PREFIX =
Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_PREFIX
- FALLBACK =
read_encodings
- FOLD_MSG =
"NOTE: '\\' line wrapping per RFC 8792".freeze
- UNFOLD_RE =
/\A.*#{FOLD_MSG.sub("\\", "(\\\\\\\\\\\\\\\\?)")}.*\n\r?\n/
- MIN_FOLD_COLUMNS =
FOLD_MSG.size
- FOLD_COLUMNS =
69
- RE_IDENT =
/\A[A-Za-z0-9_]\z/
- SVG_NAMESPACES =
{"svg"=>"http://www.w3.org/2000/svg", "xlink"=>"http://www.w3.org/1999/xlink"}
Instance Method Summary collapse
- #add_quote(s) ⇒ Object
- #autolink_iref_cleanup(d) ⇒ Object
-
#bibtagsys(bib, anchor = nil, stand_alone = true) ⇒ Object
return XML entity name, url, rewrite_anchor flag.
- #boilerplate(key) ⇒ Object
- #do_the_tls_dance ⇒ Object
- #doi_citeproc_to_lit(cite, fuzzy) ⇒ Object
- #doi_fetch_and_convert(doi, fuzzy: false, verbose: false, site: "https://dx.doi.org") ⇒ Object
- #expand_tabs(s, tab_stops = 8) ⇒ Object
- #fix_unterminated_line(s) ⇒ Object
- #fold8792_1(s, columns = FOLD_COLUMNS, left = false, dry = false) ⇒ Object
- #handle_artwork_sourcecode(s, unfold = true) ⇒ Object
- #process_chunk(s, nested, dedent, fold, quote) ⇒ Object
- #process_includes(input) ⇒ Object
- #process_kramdown_options(coding_override = nil, smart_quotes = nil, typographic_symbols = nil, header_kramdown_options = nil) ⇒ Object
- #read_encodings ⇒ Object
-
#remove_indentation(s) ⇒ Object
Note that this doesn’t attempt to handle HT characters.
- #spacify_re(s) ⇒ Object
- #svg_id_cleanup(d) ⇒ Object
-
#trim_empty_lines_around(s) ⇒ Object
this deletes the trailing newline, which may need to be reconstructed.
- #unfold8792(s) ⇒ Object
- #xml_from_sections(input) ⇒ Object
- #yaml_load(input, *args) ⇒ Object
Instance Method Details
#add_quote(s) ⇒ Object
16 17 18 19 |
# File 'lib/kramdown-rfc/command.rb', line 16 def add_quote(s) l = s.lines l.map {|li| "> #{li}"}.join end |
#autolink_iref_cleanup(d) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/kramdown-rfc/autolink-iref-cleanup.rb', line 3 def autolink_iref_cleanup(d) d.root.get_elements("//section[@anchor]").each do |sec| anchor = sec['anchor'] irefs = {} sec.get_elements(".//xref[@target='#{anchor}'][@format='none']").each do |xr| ne = xr.previous_element # 9c87e84 iref now before xref if ne && ne.name == "iref" && (item = ne['item']) irefs[item] = ne['subitem'] # XXX one subitem only ne.remove chi = xr.children chi[1..-1].reverse.each do |ch| xr.parent.insert_after(xr, ch) end xr.replace_with(chi[0]) end end irefs.each do |k, v| sec.insert_after(sec.get_elements("name").first, e = REXML::Element.new("iref", sec)) e.attributes["item"] = k e.attributes["subitem"] = v e.attributes["primary"] = 'true' end end end |
#bibtagsys(bib, anchor = nil, stand_alone = true) ⇒ Object
return XML entity name, url, rewrite_anchor flag
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/kramdown-rfc/command.rb', line 478 def (bib, anchor=nil, stand_alone=true) if bib =~ /\Arfc(\d+)/i rfc4d = "%04d" % $1.to_i [bib.upcase, "#{XML_RESOURCE_ORG_PREFIX}/bibxml/reference.RFC.#{rfc4d}.xml"] elsif $options.v3 && bib =~ /\A(bcp|std)(\d+)/i n4d = "%04d" % $2.to_i [bib.upcase, "#{XML_RESOURCE_ORG_PREFIX}/bibxml-rfcsubseries-new/reference.#{$1.upcase}.#{n4d}.xml"] elsif bib =~ /\A([-A-Z0-9]+)\./ && (xro = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_MAP[$1]) dir, _ttl, rewrite_anchor = xro bib1 = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(bib) if anchor && bib1 != anchor if rewrite_anchor a = %{?anchor=#{anchor}} else if !stand_alone warn "*** selecting a custom anchor '#{anchor}' for '#{bib1}' requires stand_alone mode" warn " the output will need manual editing to correct this" end end end [bib1, "#{XML_RESOURCE_ORG_PREFIX}/#{dir}/reference.#{bib}.xml#{a}"] end end |
#boilerplate(key) ⇒ Object
70 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/kramdown-rfc/command.rb', line 70 def boilerplate(key) ret = '' case key.downcase when /\Abcp14(info)?(\+)?(-tagged)?\z/i if $1 ret << <<RFC8174ise Although this document is not an IETF Standards Track publication, it adopts the conventions for normative language to provide clarity of instructions to the implementer. RFC8174ise end ret << <<RFC8174 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they appear in all capitals, as shown here. RFC8174 if $2 ret << <<PLUS These words may also appear in this document in lower case as plain English words, absent their normative meanings. PLUS end if $3 ($options.v3_used ||= []) << "** need --v3 to tag bcp14" ret << <<TAGGED *[MUST]: <bcp14> *[MUST NOT]: <bcp14> *[REQUIRED]: <bcp14> *[SHALL]: <bcp14> *[SHALL NOT]: <bcp14> *[SHOULD]: <bcp14> *[SHOULD NOT]: <bcp14> *[RECOMMENDED]: <bcp14> *[NOT RECOMMENDED]: <bcp14> *[MAY]: <bcp14> *[OPTIONAL]: <bcp14> TAGGED end ret when /\Arfc\s*7942(info)?\z/i if $1 ret << <<INFO (Boilerplate as per {{Section 2.1 of RFC7942}}:) INFO end ret << <<RFC7942 This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in {{?RFC7942}}. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist. According to {{?RFC7942}}, "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit". RFC7942 else warn "** Unknown boilerplate key: #{key}" "{::boilerplate #{key}}" end end |
#do_the_tls_dance ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/kramdown-rfc/command.rb', line 146 def do_the_tls_dance begin require 'openssl' File.open(OpenSSL::X509::DEFAULT_CERT_FILE) do end # This guards against having an unreadable cert file (yes, that appears to happen a lot). rescue if Dir[File.join(OpenSSL::X509::DEFAULT_CERT_DIR, "*.pem")].empty? # This guards against having no certs at all, not against missing the right one for IETF. # Oh well. warn "** Configuration problem with OpenSSL certificate store." warn "** You may want to examine #{OpenSSL::X509::DEFAULT_CERT_FILE}" warn "** and #{OpenSSL::X509::DEFAULT_CERT_DIR}." warn "** Activating suboptimal workaround." warn "** Occasionally run `certified-update` to maintain that workaround." require 'certified' end end end |
#doi_citeproc_to_lit(cite, fuzzy) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/kramdown-rfc/doi.rb', line 32 def doi_citeproc_to_lit(cite, fuzzy) lit = {} ser = lit["seriesinfo"] = {} refcontent = [] lit["title"] = cite["title"] if (st = cite["subtitle"]) && Array === st # defensive st.delete('') if st != [] lit["title"] << ": " << st.join("; ") end end if = cite["author"] lit["author"] = .map do |au| lau = {} if (f = au["family"]) if (g = au["given"]) lau["name"] = "#{g} #{f}" lau["ins"] = "#{g[0]}. #{f}" else lau["name"] = "#{f}" # lau["ins"] = "#{g[0]}. #{f}" end end if (f = au["affiliation"]) && Array === f names = f.map { |affn| if Hash === affn && (n = affn["name"]) && String === n n end }.compact if names.size > 0 lau["org"] = names.join("; ") end end lau end end if iss = cite["issued"] if dp = iss["date-parts"] if Integer === (dp = dp[0])[0] lit["date"] = ["%04d" % dp[0], *dp[1..-1].map {|p| "%02d" % p}].join("-") end end end if !lit.key?("date") && fuzzy && (iss = cite["created"]) if dp = iss["date-parts"] if Integer === (dp = dp[0])[0] lit["date"] = ["%04d" % dp[0], *dp[1..-1].map {|p| "%02d" % p}].join("-") end end end if (ct = cite["container-title"]) && ct != [] info = [] if v = cite["volume"] vi = "vol. #{v}" if (v = cite["journal-issue"]) && (issue = v["issue"]) vi << ", no. #{issue}" end info << vi end if p = cite["page"] info << "pp. #{p}" end rhs = info.join(", ") if info != [] ser[ct] = rhs else spl = ct.split(" ") ser[spl[0..-2].join(" ")] = spl[-1] end end if pub = cite["publisher"] refcontent << pub # info = [] # if t = cite["type"] # info << t # end # rhs = info.join(", ") # if info != [] # ser[pub] = rhs # else # spl = pub.split(" ") # ser[spl[0..-2].join(" ")] = spl[-1] # end end ["DOI", "ISBN"].each do |st| if a = cite[st] ser[st] = a end end if refcontent != [] lit["refcontent"] = refcontent.join(", ") end lit end |
#doi_fetch_and_convert(doi, fuzzy: false, verbose: false, site: "https://dx.doi.org") ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/kramdown-rfc/doi.rb', line 7 def doi_fetch_and_convert(doi, fuzzy: false, verbose: false, site: "https://dx.doi.org") doipath = doi.sub(/^([0-9.]+)_/) {"#$1/"} # convert initial _ back to / # warn "** SUB #{doi} #{doipath}" if doi != doipath begin cite = JSON.parse(URI("#{site}/#{doipath}").open(ACCEPT_CITE_JSON).read) puts cite.to_yaml if verbose doi_citeproc_to_lit(cite, fuzzy) rescue OpenURI::HTTPError => e begin site = "https://dl.acm.org" percent_escaped = doipath.gsub("/", "%2F") path = "#{site}/action/exportCiteProcCitation?targetFile=custom-bibtex&format=bibTex&dois=#{percent_escaped}" op = URI(path).open # first get a cookie, ignore result # warn [:META, op.meta].inspect cook = op.['set-cookie'].split('; ', 2)[0] cite = JSON.parse(URI(path).open("Cookie" => cook).read) cite = cite["items"].first[doipath] puts cite.to_yaml if verbose doi_citeproc_to_lit(cite, fuzzy) rescue raise e end end end |
#expand_tabs(s, tab_stops = 8) ⇒ Object
517 518 519 520 521 |
# File 'lib/kramdown-rfc/command.rb', line 517 def (s, tab_stops = 8) s.gsub(/([^\t\n]*)\t/) do $1 + " " * (tab_stops - ($1.size % tab_stops)) end end |
#fix_unterminated_line(s) ⇒ Object
13 14 15 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 13 def fix_unterminated_line(s) s.sub(/[^\n]\z/) { "#$&\n" } # XXX end |
#fold8792_1(s, columns = FOLD_COLUMNS, left = false, dry = false) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 47 def fold8792_1(s, columns = FOLD_COLUMNS, left = false, dry = false) if s.index("\t") warn "*** HT (\"TAB\") in text to be folded. Giving up." return s end if columns < MIN_FOLD_COLUMNS columns = if columns == 0 FOLD_COLUMNS else warn "*** folding to #{MIN_FOLD_COLUMNS}, not #{columns}" MIN_FOLD_COLUMNS end end lines = s.lines.map(&:chomp) did_fold = false ix = 0 while li = lines[ix] col = columns if li[col].nil? if li[-1] == "\\" lines[ix..ix] = [li << "\\", ""] ix += 1 end ix += 1 else did_fold = true min_indent = left || 0 col -= 1 # space for "\\" while li[col] == " " # can't start new line with " " col -= 1 end if col <= min_indent warn "*** Cannot RFC8792-fold1 to #{columns} cols #{"with indent #{left}" if left} |#{li.inspect}|" else if RE_IDENT === li[col] # Don't split IDs col2 = col while col2 > min_indent && RE_IDENT === li[col2-1] col2 -= 1 end if col2 > min_indent col = col2 end end rest = li[col..-1] indent = left || columns - rest.size if !left && li[-1] == "\\" indent -= 1 # leave space for next round end if indent > 0 rest = " " * indent + rest end lines[ix..ix] = [li[0...col] << "\\", rest] end ix += 1 end end if did_fold msg = FOLD_MSG.dup if !dry && columns >= msg.size + 4 delta = columns - msg.size - 2 # 2 spaces half = delta/2 msg = "#{"=" * half} #{msg} #{"=" * (delta - half)}" end lines[0...0] = [msg, ""] lines.map{|x| x << "\n"}.join else s end end |
#handle_artwork_sourcecode(s, unfold = true) ⇒ Object
17 18 19 20 21 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 17 def handle_artwork_sourcecode(s, unfold = true) s = trim_empty_lines_around(s) s = unfold8792(s) if unfold fix_unterminated_line(s) end |
#process_chunk(s, nested, dedent, fold, quote) ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/kramdown-rfc/command.rb', line 21 def process_chunk(s, nested, dedent, fold, quote) process_includes(s) if nested s = remove_indentation(s) if dedent s = fold8792_1(s, *fold) if fold s = add_quote(s) if quote s end |
#process_includes(input) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/kramdown-rfc/command.rb', line 29 def process_includes(input) input.gsub!(/^\{::include((?:-[a-z0-9]+)*)\s+(.*?)\}/) { include_flags = $1 fn = [$2] chunks = false nested = false dedent = false fold = false quote = false include_flags.split("-") do |flag| case flag when "" when "nested" nested = true when "quote" quote = true when "dedent" dedent = true when /\Afold(\d*)(left(\d*))?(dry)?\z/ fold = [$1.to_i, # col 0 for '' ($3.to_i if $2), # left 0 for '', nil if no "left" $4] # dry when "all", "last" fn = fn.flat_map{|n| Dir[n]} fn = [fn.last] if flag == "last" chunks = fn.map{ |f| ret = process_chunk(File.read(f), nested, dedent, fold, quote) nested = false; dedent = false; fold = false; quote = false ret } else warn "** unknown include flag #{flag}" end end chunks = fn.map{|f| File.read(f)} unless chunks # no all/last chunks = chunks.map {|ch| process_chunk(ch, nested, dedent, fold, quote)} chunks.join.chomp } end |
#process_kramdown_options(coding_override = nil, smart_quotes = nil, typographic_symbols = nil, header_kramdown_options = nil) ⇒ Object
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 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/kramdown-rfc/command.rb', line 189 def (coding_override = nil, smart_quotes = nil, typographic_symbols = nil, = nil) ascii_target = coding_override && coding_override =~ /ascii/ suppress_typography = ascii_target || $options.v3 entity_output = ascii_target ? :numeric : :as_char; = {input: 'RFC2629Kramdown', entity_output: entity_output, link_defs: {}} if smart_quotes.nil? && suppress_typography smart_quotes = false end if smart_quotes == false smart_quotes = ["'".ord, "'".ord, '"'.ord, '"'.ord] end case smart_quotes when Array [:smart_quotes] = smart_quotes when nil, true # nothin else warn "*** Can't deal with smart_quotes value #{smart_quotes.inspect}" end if typographic_symbols.nil? && suppress_typography typographic_symbols = false end if typographic_symbols == false typographic_symbols = Hash[::Kramdown::Parser::Kramdown::TYPOGRAPHIC_SYMS.map { |k, v| if Symbol === v [v.intern, k] end }.compact] end # warn [:TYPOGRAPHIC_SYMBOLS, typographic_symbols].to_yaml case typographic_symbols when Hash [:typographic_symbols] = typographic_symbols when nil, true # nothin else warn "*** Can't deal with typographic_symbols value #{typographic_symbols.inspect}" end if .merge! end $global_markdown_options = # For nested calls in bibref annotation processing and xref text end |
#read_encodings ⇒ Object
506 507 508 509 510 511 512 513 |
# File 'lib/kramdown-rfc/command.rb', line 506 def read_encodings encfilename = File. '../../../data/encoding-fallbacks.txt', __FILE__ encfile = File.read(encfilename, coding: "UTF-8") Hash[encfile.lines.map{|l| l.chomp!; x, s = l.split(" ", 2) [x.hex.chr(Encoding::UTF_8), s || " "]}] end |
#remove_indentation(s) ⇒ Object
Note that this doesn’t attempt to handle HT characters
3 4 5 6 7 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 3 def remove_indentation(s) l = s.lines indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min l.map {|li| li.sub(/^ {0,#{indent}}/, "")}.join end |
#spacify_re(s) ⇒ Object
249 250 251 |
# File 'lib/kramdown-rfc/command.rb', line 249 def spacify_re(s) s.gsub(' ', '[\u00A0\s]+') end |
#svg_id_cleanup(d) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/kramdown-rfc/svg-id-cleanup.rb', line 6 def svg_id_cleanup(d) gensym = "gensym000" REXML::XPath.each(d.root, "//svg:svg", SVG_NAMESPACES) do |x| gensym = gensym.succ # warn "*** SVG" # warn "*** SVG: #{x.to_s.size}" found_as_id = Set[] found_as_href = Set[] REXML::XPath.each(x, ".//*[@id]", SVG_NAMESPACES) do |y| # warn "*** ID: #{y}" name = y.attributes["id"] if found_as_id === name warn "*** duplicate ID #{name}" end found_as_id.add(name) y.attributes["id"] = "#{name}-#{gensym}" end REXML::XPath.each(x, ".//*[@xlink:href]", SVG_NAMESPACES) do |y| # warn "*** HREF: #{y}" name = y.attributes["href"] name1 = name[1..-1] if !found_as_id === name1 warn "*** unknown HREF #{name}" end found_as_href.add(name1) y.attributes["xlink:href"] = "#{name}-#{gensym}" end found_as_id -= found_as_href warn "*** warning: unused ID: #{found_as_id.to_a.join(", ")}" unless found_as_id.empty? end rescue => detail warn "*** Can't clean SVG: #{detail}" end |
#trim_empty_lines_around(s) ⇒ Object
this deletes the trailing newline, which may need to be reconstructed
9 10 11 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 9 def trim_empty_lines_around(s) # this deletes the trailing newline, which may need to be reconstructed s.sub(/\A(\r?\n)*/, '').sub(/(\r?\n)*\z/, '') end |
#unfold8792(s) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/kramdown-rfc/rfc8792.rb', line 26 def unfold8792(s) if s =~ UNFOLD_RE indicator = $1 s = $' sub = case indicator when "\\" s.gsub!(/\\\n[ \t]*/, '') when "\\\\" s.gsub!(/\\\n[ \t]*\\/, '') else fail "indicator" # Cannot happen end warn "** encountered RFC 8792 header without folded lines" unless sub end s end |
#xml_from_sections(input) ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/kramdown-rfc/command.rb', line 255 def xml_from_sections(input) unless ENV["KRAMDOWN_NO_SOURCE"] require 'kramdown-rfc/gzip-clone' require 'base64' compressed_input = Gzip.compress_m0(input) $source = Base64.encode64(compressed_input) end sections = input.scan(RE_SECTION) # resulting in an array; each section is [section-label, nomarkdown-flag, section-text] line = 1 # skip "---" sections.each do |section| section << line line += 1 + section[2].lines.count end # warn "#{line-1} lines" # the first section is a YAML with front matter parameters (don't put a label here) # We put back the "---" plus gratuitous blank lines to hack the line number in errors yaml_in = input[/---\s*/] << sections.shift[2] ps = KramdownRFC::ParameterSet.new(yaml_load(yaml_in, [Date], [], true)) if v = ps[:v] warn "*** unsupported RFCXML version #{v}" if v != 3 if $options.v2 warn "*** command line --v2 wins over document's 'v: #{v}'" else $options.v3 = true $options.v = 3 ps.default!(:stand_alone, true) ps.default!(:ipr, "trust200902") ps.default!(:pi, {"toc" => true, "sortrefs" => true, "symrefs" => true}) end end if o = ps[:'autolink-iref-cleanup'] $options.autolink_iref_cleanup = o end if o = ps[:'svg-id-cleanup'] $options.svg_id_cleanup = o end coding_override = ps.has(:coding) smart_quotes = ps[:smart_quotes] || ps[:"smart-quotes"] typographic_symbols = ps[:typographic_symbols] = ps[:kramdown_options] = (coding_override, smart_quotes, typographic_symbols, ) # all the other sections are put in a Hash, possibly concatenated from parts there sechash = Hash.new{ |h,k| h[k] = ""} snames = [] # a stack of section names sections.each do |sname, nmdflag, text, line| # warn [:SNAME, sname, nmdflag, text[0..10]].inspect nmdin, nmdout = { "-" => ["", ""], # stay in nomarkdown "" => NMDTAGS, # pop out temporarily }[nmdflag || ""] if sname snames << sname # "--- label" -> push label (now current) else snames.pop # just "---" -> pop label (previous now current) end sechash[snames.last] << "#{nmdin}<?line #{line}?>\n#{text}#{nmdout}" end ref_replacements = { } anchor_to_bibref = { } displayref = {} [:ref, :normative, :informative].each do |sn| if refs = ps.has(sn) warn "*** bad section #{sn}: #{refs.inspect}" unless refs.respond_to? :each refs.each do |k, v| if v.respond_to? :to_str if (v) # enable "foo: RFC4711" as a custom anchor definition anchor_to_bibref[k] = v.to_str end ref_replacements[v.to_str] = k end if Hash === v if aliasname = v.delete("-") ref_replacements[aliasname] = k end if bibref = v.delete("=") anchor_to_bibref[k] = bibref end if dr = v.delete("display") displayref[k.gsub("/", "_")] = dr end end end end end open_refs = ps[:ref] || { } # consumed norm_ref = { } # convenience replacement of {{-coap}} with {{I-D.ietf-core-coap}} # collect normative/informative tagging {{!RFC2119}} {{?RFC4711}} sechash.each do |k, v| next if k == "fluff" v.gsub!(/{{(#{ spacify_re(XSR_PREFIX) })?([\w.\/_\-]+@)?(?:([?!])(-)?|(-))([\w._\-]+)(?:=([\w.\/_\-]+))?(#{ XREF_TXT_SUFFIX })?(#{ spacify_re(XSR_SUFFIX) })?}}/) do |match| xsr_prefix = $1 subref = $2 norminform = $3 replacing = $4 || $5 word = $6 bibref = $7 xrt_suffix = $8 xsr_suffix = $9 if replacing if new = ref_replacements[word] word = new else warn "*** no alias replacement for {{-#{word}}}" word = "-#{word}" end end # now, word is the anchor if bibref if old = anchor_to_bibref[word] if bibref != old warn "*** conflicting definitions for xref #{word}: #{old} != #{bibref}" end else anchor_to_bibref[word] = bibref end end # things can be normative in one place and informative in another -> normative # collect norm/inform above and assign it by priority here if norminform norm_ref[word] ||= norminform == '!' # one normative ref is enough end "{{#{xsr_prefix}#{subref}#{word}#{xrt_suffix}#{xsr_suffix}}}" end end [:normative, :informative].each do |k| ps.rest[k.to_s] ||= { } end norm_ref.each do |k, v| # could check bibtagsys here: needed if open_refs is nil or string target = ps.has(v ? :normative : :informative) warn "*** overwriting #{k}" if target.has_key?(k) target[k] = open_refs[k] # add reference to normative/informative end # note that unused items from ref are considered OK, therefore no check for that here # also should allow norm/inform check of other references # {{?coap}} vs. {{!coap}} vs. {{-coap}} (undecided) # or {{?-coap}} vs. {{!-coap}} vs. {{-coap}} (undecided) # could require all references to be decided by a global flag overlap = [:normative, :informative].map { |s| (ps.has(s) || { }).keys }.reduce(:&) unless overlap.empty? warn "*** #{overlap.join(', ')}: both normative and informative" end stand_alone = ps[:stand_alone] [:normative, :informative].each do |sn| if refs = ps[sn] refs.each do |k, v| href = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(k) [:link_defs][k] = ["##{href}", nil] # allow [RFC2119] in addition to {{RFC2119}} bibref = anchor_to_bibref[k] || k bts, url = (bibref, k, stand_alone) ann = v.delete("annotation") || v.delete("ann") if Hash === v if bts && (!v || v == {} || v.respond_to?(:to_str)) if stand_alone a = %{{: anchor="#{k}"}} a[-1...-1] = %{ ann="#{escape_html(ann, :attribute)}"} if ann sechash[sn.to_s] << %{\n#{NMDTAGS[0]}\n![:include:](#{bts})#{a}\n#{NMDTAGS[1]}\n} else warn "*** please use standalone mode for adding annotations to references" if ann bts.gsub!('/', '_') (ps.rest["bibxml"] ||= []) << [bts, url] sechash[sn.to_s] << %{&#{bts};\n} # ??? end else unless v && Hash === v warn "*** don't know how to expand ref #{k}" next end if bts && !v.delete("override") warn "*** warning: explicit settings completely override canned bibxml in reference #{k}" end v["ann"] = ann if ann sechash[sn.to_s] << KramdownRFC::ref_to_xml(href, v) end end end end erbfilename = File. '../../../data/kramdown-rfc2629.erb', __FILE__ erbfile = File.read(erbfilename, coding: "UTF-8") erb = ERB.trim_new(erbfile, '-') # remove redundant nomarkdown pop outs/pop ins as they confuse kramdown input = erb.result(binding).gsub(%r"{::nomarkdown}\s*{:/nomarkdown}"m, "") ps.warn_if_leftovers sechash.delete("fluff") # fluff is a "commented out" section if !sechash.empty? # any sections unused by the ERb file? warn "*** sections left #{sechash.keys.inspect}!" end [input, , coding_override] end |
#yaml_load(input, *args) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/kramdown-rfc/command.rb', line 172 def yaml_load(input, *args) begin if YAML.respond_to?(:safe_load) begin YAML.safe_load(input, *args) rescue ArgumentError YAML.safe_load(input, permitted_classes: args[0], permitted_symbols: args[1], aliases: args[2]) end else YAML.load(input) end rescue Psych::SyntaxError => e warn "*** YAML syntax error: #{e}" exit 65 # EX_DATAERR end end |