Class: MTProto::Markdown::Renderer
- Inherits:
-
Object
- Object
- MTProto::Markdown::Renderer
- Defined in:
- lib/mtproto/markdown.rb
Overview
entities -> MarkdownV2 markup. Escapes literal markup characters and wraps each entity's UTF-16 range with its markers. Entities are opened outer-first and closed inner-first so proper nesting round-trips. Works in UTF-16 unit space.
Constant Summary collapse
- SPECIAL =
'_*[]()~`>#+-=|{}.!\\'- WRAP =
{ bold: '*', italic: '_', underline: '__', strike: '~', spoiler: '||' }.freeze
Instance Method Summary collapse
-
#initialize(text, entities) ⇒ Renderer
constructor
A new instance of Renderer.
- #render ⇒ Object
Constructor Details
Instance Method Details
#render ⇒ Object
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 |
# File 'lib/mtproto/markdown.rb', line 343 def render opens = Hash.new { |h, k| h[k] = [] } closes = Hash.new { |h, k| h[k] = [] } @entities.each_with_index do |e, i| opens[e.offset] << [e, i] closes[e.offset + e.length] << [e, i] end verbatim = ranges_of(%i[code pre]) # content here is literal — never escaped quotes = ranges_of(%i[blockquote]) # rendered as a '>' line prefix out = +'' pos = 0 line_start = true loop do # Close inner-first, the exact mirror of the open order (outer-first), so # entities that end together don't emit crossed markers. Ties broken by the # reverse of the open tiebreak. closes[pos].sort_by { |(e, i)| [e.length, -i] }.each { |(e, _)| out << close_marker(e) } out << '>' if line_start && in_range?(quotes, pos) opens[pos].sort_by { |(e, i)| [-e.length, i] }.each { |(e, _)| out << open_marker(e) } break if pos >= @units.length u = @units[pos] if high_surrogate?(u) && pos + 1 < @units.length out << pair_to_s(u, @units[pos + 1]) # an astral char never needs escaping pos += 2 line_start = false else ch = unit_to_s(u) out << render_char(ch, in_range?(verbatim, pos)) line_start = ch == "\n" pos += 1 end end out end |