Module: JekyllSupport

Defined in:
lib/hooks/a_page.rb,
lib/jekyll_plugin_support.rb,
lib/jekyll_plugin_support.rb,
lib/error/jekyll_custom_error.rb,
lib/helper/jekyll_plugin_helper.rb,
lib/tag/jekyll_plugin_support_tag.rb,
lib/block/jekyll_plugin_support_block.rb,
lib/helper/jekyll_plugin_helper_class.rb,
lib/tag/jekyll_plugin_support_tag_noarg.rb,
lib/block/jekyll_plugin_support_block_noarg.rb,
lib/helper/jekyll_plugin_helper_attribution.rb,
lib/generator/jekyll_plugin_support_generator.rb,
lib/jekyll_plugin_support/jekyll_plugin_support_class.rb

Defined Under Namespace

Classes: APage, CustomError, JekyllBlock, JekyllBlockNoArgParsing, JekyllGenerator, JekyllPluginHelper, JekyllTag, JekyllTagNoArgParsing

Constant Summary collapse

FIXNUM_MAX =
(2**((0.size * 8) - 2)) - 1
END_OF_DAYS =

One trillion years in the future

1_000_000_000_000
DISPLAYED_CALLS =
8
JekyllPluginSupportError =
define_error

Class Method Summary collapse

Class Method Details

.apage_from(collection_name: nil, date: nil, description: nil, draft: false, last_modified: nil, logger: nil, order: nil, title: nil, url: nil) ⇒ Object

Contructor for testing and jekyll_outline



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/hooks/a_page.rb', line 7

def self.apage_from( # rubocop:disable Metrics/ParameterLists
  collection_name: nil,
  date: nil,
  description: nil,
  draft: false,
  last_modified: nil,
  logger: nil,
  order: nil,
  title: nil,
  url: nil
)
  # Jekyll documents have inconsistent date and last_modified property types.
  date = Time.parse(date) if date.instance_of?(String)
  unless date.instance_of? Time
    logger.error { "date is not an instance of Time, it is an instance of #{date.class}" }
    exit 2
  end

  last_modified = Date.parse(last_modified) if last_modified.instance_of?(String)
  last_modified = Date.parse(date.strftime('%Y-%m-%d')) if last_modified.nil?
  unless last_modified.instance_of? Date
    logger.error { "last_modified is not an instance of Date, it is an instance of #{last_modified.class}" }
    exit 3
  end
  last_modified = Date.parse(date._to_s) if last_modified.nil?
  data = {
    collection:    { label: collection_name },
    draft:         draft,
    last_modified: last_modified,
    order:         order,
    title:         title,
  }
  obj = {}
  JekyllSupport.new_attribute obj, :data, data
  JekyllSupport.new_attribute obj, :date, date
  JekyllSupport.new_attribute obj, :description, description
  JekyllSupport.new_attribute obj, :draft, draft
  JekyllSupport.new_attribute obj, :extname, '.html'
  JekyllSupport.new_attribute obj, :last_modified, last_modified
  JekyllSupport.new_attribute obj, :logger, PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
  JekyllSupport.new_attribute obj, :title, title
  JekyllSupport.new_attribute obj, :url, url

  JekyllSupport::APage.new obj, nil
rescue StandardError => e
  puts e.full_message
end

.apages_from_objects(objects, origin) ⇒ Object

Create Array of JekyllSupport::APage from objects



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/hooks/a_page.rb', line 58

def self.apages_from_objects(objects, origin)
  pages = []
  objects.each do |object|
    unless object.respond_to?(:logger)
      JekyllSupport.new_attribute(object,
                                  :logger,
                                  PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config))
    end
    page = APage.new(object, origin)
    pages << page unless page.data['exclude_from_all'] || page.path == 'redirect.html'
  end
  pages
end

.define_errorObject



23
24
25
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 23

def define_error
  Class.new ::JekyllSupport::CustomError
end

.dump_stack(stack, cycles, interval) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 70

def self.dump_stack(stack, cycles, interval)
  stack_depth = stack.length
  puts "Stack depth is #{stack_depth}"
  num_entries = cycles * interval
  return unless stack_depth > interval * 5

  stack.last(num_entries).each_with_index do |x, i|
    msg = "  #{i}: #{x}"
    (i % interval).zero? ? puts(msg.yellow) : puts(msg)
  end
end

.dump_vars(_logger, liquid_context) ⇒ Object



30
31
32
33
34
35
36
37
38
39
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 30

def self.dump_vars(_logger, liquid_context)
  page = liquid_context.registers[:page]
  vars = liquid_context.scopes.map do |scope|
    scope.map { |name, value| "  #{name} = #{value}" }.join("\n")
  end.join("\n")
  puts <<~END_MSG
    #{page['name']} variables after injecting any defined in _config.yml:
    #{vars}
  END_MSG
end

.error_short_trace(logger, error) ⇒ Object



16
17
18
19
20
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 16

def self.error_short_trace(logger, error)
  error.set_backtrace error.backtrace[0..DISPLAYED_CALLS]
  logger.error { error.full_message } # Are error and logger.error defined?
  error
end

.inject_config_vars(liquid_context) ⇒ Object

Inject variable definitions from _config.yml into liquid_context Modifies liquid_context.scopes in the caller (call by object reference, see stackoverflow.com/a/1872159/553865) See README.md#configuration-variable-definitions See demo/variables.html



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 47

def self.inject_config_vars(liquid_context)
  site = liquid_context.registers[:site]

  plugin_variables = site.config['liquid_vars']

  scope = liquid_context.scopes.last

  env = site.config['env']
  @mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'

  # Set default values
  plugin_variables&.each do |name, value|
    scope[name] = value if value.instance_of? String
  end

  # Override with environment-specific values
  plugin_variables&.[](@mode)&.each do |name, value|
    scope[name] = value if value.instance_of? String
  end

  liquid_context
end

.lookup_liquid_variables(logger, liquid_context, markup_original) ⇒ Object

Modifies a clone of markup_original so variable references are replaced by their values



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 85

def self.lookup_liquid_variables(logger, liquid_context, markup_original)
  markup = markup_original.clone
  page   = liquid_context.registers[:page]
  envs   = liquid_context.environments.first
  layout = envs[:layout]

  markup = process_layout_variables logger, layout, markup
  markup = process_page_variables logger, page, markup
  liquid_context.scopes&.each do |scope|
    markup = process_included_variables logger, scope, markup
    markup = process_liquid_variables logger, scope, markup
  end
  markup
rescue StandardError => e
  logger.error { e.full_message }
end

.new_attribute(obj, prop_name, prop_value) ⇒ Object

Defines a new attribute called ‘prop_name` in object `obj` and sets it to `prop_value`



73
74
75
76
# File 'lib/hooks/a_page.rb', line 73

def self.new_attribute(obj, prop_name, prop_value)
  obj.class.module_eval { attr_accessor prop_name }
  obj.instance_variable_set :"@#{prop_name}", prop_value
end

.process_included_variables(logger, scope, markup) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 102

def self.process_included_variables(logger, scope, markup)
  scope['include']&.each do |name, value|
    raise JekyllPluginSupportError, "include.#{name} is undefined." if name.nil?
    raise JekyllPluginSupportError, "include.#{name} is a #{name.class}, not a String." unless name.instance_of?(String)
    raise JekyllPluginSupportError, "include.#{name} has an undefined value." if value.nil?

    markup.gsub!("{{include.#{name}}}", value.to_s)
  end
  markup
rescue StandardError => e
  logger.error { e.full_message }
  exit! 1
end

.process_layout_variables(logger, layout, markup) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 116

def self.process_layout_variables(logger, layout, markup)
  layout&.each do |name, value|
    if value.nil?
      value = ''
      logger.warn { "layout.#{value} is undefined." }
    end
    markup.gsub!("{{layout.#{name}}}", value.to_s)
  end
  markup
rescue StandardError => e
  logger.error { e.full_message }
end

.process_liquid_variables(logger, scope, markup) ⇒ Object

Process assigned, captured and injected variables



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 130

def self.process_liquid_variables(logger, scope, markup)
  unless markup.instance_of?(String)
    logger.warn { "markup is a #{markup.class}, not a String" }
    return markup
  end
  scope&.each do |name, value|
    next if name.nil?

    value = '' if value.nil?
    markup.gsub!("{{#{name}}}", value&.to_s)
  end
  markup
rescue StandardError => e
  logger.error { e.full_message }
end

.process_page_variables(logger, page, markup) ⇒ Object



146
147
148
149
150
151
152
153
154
155
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 146

def self.process_page_variables(logger, page, markup)
  page&.each_key do |key|
    next if %w[content excerpt next previous output].include? key # Skip problem attributes

    markup.gsub!("{{page.#{key}}}", page[key].to_s)
  end
  markup
rescue StandardError => e
  logger.error { e.full_message }
end

.redef_without_warning(const, value) ⇒ Object



25
26
27
28
# File 'lib/jekyll_plugin_support.rb', line 25

def self.redef_without_warning(const, value)
  send(:remove_const, const) if const_defined?(const)
  const_set const, value
end

.warn_short_trace(logger, error) ⇒ Object



157
158
159
160
161
162
163
164
# File 'lib/jekyll_plugin_support/jekyll_plugin_support_class.rb', line 157

def self.warn_short_trace(logger, error)
  remaining = error.backtrace.length - DISPLAYED_CALLS
  logger.warn do
    error.message + "\n" +
      error.backtrace.take(DISPLAYED_CALLS).join("\n") +
      "\n...Remaining #{remaining} call sites elided.\n"
  end
end