Class: Markbridge::Processors::DiscourseMarkdown::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/markbridge/processors/discourse_markdown/scanner.rb

Overview

Single-pass scanner for Discourse Markdown that extracts specific constructs (mentions, polls, events, uploads) while preserving all other content unchanged.

The scanner respects code blocks (fenced, indented, and inline) and will not extract constructs that appear within code.

Examples:

Basic usage

scanner = Scanner.new
result = scanner.scan("Hello @gerhard!")
result.nodes.first # => AST::Mention

With custom tag library for rendering

scanner = Scanner.new(tag_library: my_library)
result = scanner.scan(input)
result.markdown # => "Hello <<MENTION:1>>!"

With mention type resolver

scanner = Scanner.new(mention_resolver: ->(name) {
  groups.include?(name) ? :group : :user
})
result = scanner.scan("@Testers and @gerhard")
result.nodes[0].type # => :group
result.nodes[1].type # => :user

Constant Summary collapse

DEFAULT_DETECTORS =

Default detectors in priority order

[
  Detectors::Poll,
  Detectors::Event,
  Detectors::Upload,
  Detectors::Mention,
].freeze
TRIGGER_CHARS =

Characters that can start a construct (for fast bailout)

Set.new(["@", "[", "!"]).freeze

Instance Method Summary collapse

Constructor Details

#initialize(detectors: DEFAULT_DETECTORS, tag_library: nil, mention_resolver: nil) ⇒ Scanner

Returns a new instance of Scanner.

Parameters:

  • detectors (Array<Class>) (defaults to: DEFAULT_DETECTORS)

    detector classes to use (instantiated automatically)

  • tag_library (Renderers::Discourse::TagLibrary, nil) (defaults to: nil)

    tag library for rendering placeholders

  • mention_resolver (#call, nil) (defaults to: nil)

    callable that takes a name and returns :user or :group



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/markbridge/processors/discourse_markdown/scanner.rb', line 49

def initialize(detectors: DEFAULT_DETECTORS, tag_library: nil, mention_resolver: nil)
  @detector_instances = build_detectors(detectors, mention_resolver)
  @tag_library = tag_library
  @code_tracker = nil
  @result = nil
  @nodes = nil
  @node_index = 0
  @pos = 0
  @input = nil
  @line_start = true
end

Instance Method Details

#scan(input) ⇒ ScanResult

Scan input and extract constructs.

Parameters:

  • input (String)

    Discourse Markdown input

Returns:

  • (ScanResult)

    result containing processed markdown and extracted nodes



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/markbridge/processors/discourse_markdown/scanner.rb', line 65

def scan(input)
  return ScanResult.new(markdown: "", nodes: []) if input.nil? || input.empty?

  @code_tracker = CodeBlockTracker.new
  @result = +""
  @nodes = []
  @node_index = 0
  @pos = 0
  @input = input
  @line_start = true

  scan_input

  ScanResult.new(markdown: @result, nodes: @nodes)
end