Module: JekyllHighlightCards::LinkcardMarkup

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

Overview

Shared structural parser for {% linkcard %} markup.

Used by LinkcardTag at render time and by freeze-archives analysis without Liquid evaluation. Tokens are returned as written in source.

Class Method Summary collapse

Class Method Details

.split(markup) ⇒ Hash

Parse linkcard markup into URL, title, and archive components

Parameters:

  • markup (String)

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

Returns:

  • (Hash)

    keys :url, optional :title, optional :archive (unevaluated)



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

def split(markup)
  tokens = tokenize(markup)

  result = {}
  result[:url] = tokens.shift

  title_tokens = []
  tokens.each do |token|
    if token.start_with?("archive:")
      result[:archive] = token.delete_prefix("archive:")
    else
      title_tokens << token
    end
  end
  result[:title] = title_tokens.join(" ") unless title_tokens.empty?

  result
end

.tokenize(markup) ⇒ Array<String>

Tokenize markup respecting quotes and Liquid brace depth

Parameters:

  • markup (String)

    the tag markup

Returns:

  • (Array<String>)

    non-empty tokens



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

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

  "#{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 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.reject!(&:empty?)
  tokens
end