lib/kramdown-rfc/rfc8792.rb
# Note that this doesn't attempt to handle HT characters 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 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 def fix_unterminated_line(s) s.sub(/[^\n]\z/) { "#$&\n" } # XXX end def handle_artwork_sourcecode(s, unfold = true) s = trim_empty_lines_around(s) s = unfold8792(s) if unfold fix_unterminated_line(s) end FOLD_MSG = "NOTE: '\\' line wrapping per RFC 8792".freeze UNFOLD_RE = /\A.*#{FOLD_MSG.sub("\\", "(\\\\\\\\\\\\\\\\?)")}.*\n\r?\n/ 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 MIN_FOLD_COLUMNS = FOLD_MSG.size FOLD_COLUMNS = 69 RE_IDENT = /\A[A-Za-z0-9_]\z/ 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