Module: JekyllHighlightCards::PolaroidMarkup

Defined in:
lib/jekyll-highlight-cards/polaroid_markup.rb

Overview

Shared structural parser for {% polaroid %} markup.

Used by PolaroidTag at render time (with Liquid evaluation applied by the tag) and by freeze-archives analysis on unevaluated tokens.

Class Method Summary collapse

Class Method Details

.parse(markup) ⇒ Hash

Parse polaroid markup into image URL and named parameters (unevaluated)

Parameters:

  • markup (String)

    the tag markup (contents between tag name and %})

Returns:

  • (Hash)

    :image_url plus any key=value params as symbols (raw tokens)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/jekyll-highlight-cards/polaroid_markup.rb', line 15

def parse(markup)
  tokens = tokenize(markup)

  image_url_token = tokens.shift
  result = { image_url: image_url_token }
  tokens.each do |token|
    next unless token =~ /\A(\w+)=(.+)\z/

    key = Regexp.last_match(1).to_sym
    value_token = Regexp.last_match(2)
    result[key] = value_token
  end

  result
end

.tokenize(markup) ⇒ Array<String>

Tokenize markup respecting quotes (single or double) and Liquid brace depth

Parameters:

  • markup (String)

    the tag markup

Returns:

  • (Array<String>)

    tokens (may include empty strings from leading whitespace)



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
# File 'lib/jekyll-highlight-cards/polaroid_markup.rb', line 35

def tokenize(markup)
  tokens = []
  current = ""
  in_quotes = false
  quote_char = nil
  in_liquid = 0
  escaped = false

  # Trailing space flushes the final token through the whitespace branch
  "#{markup} ".each_char do |char|
    if escaped
      current += char
      escaped = false
      next
    end

    if char == "\\" && in_quotes
      escaped = true
      next
    end

    if char == "{" && !in_quotes
      in_liquid += 1
      current += char
    elsif char == "}" && in_liquid.positive? && !in_quotes
      in_liquid -= 1
      current += char
    elsif ['"', "'"].include?(char) && !in_quotes
      in_quotes = true
      quote_char = char
      current += char
    elsif char == quote_char
      in_quotes = false
      current += char
      quote_char = nil
    elsif char.match?(/\s/) && !in_quotes && in_liquid.zero?
      tokens << current
      current = ""
    else
      current += char
    end
  end

  tokens
end