Class: Jekyll::SeoTag

Inherits:
Liquid::Tag
  • Object
show all
Defined in:
lib/starter_web/_plugins/seo/j1-seo-tags.rb,
lib/starter_web/_plugins/seo/j1-seo-tags.rb,
lib/starter_web/_plugins/seo/j1-seo-tags.rb,
lib/starter_web/_plugins/seo/j1-seo-tags.rb,
lib/starter_web/_plugins/seo/j1-seo-tags.rb,
lib/starter_web/_plugins/seo/j1-seo-tags.rb

Overview

Major refactor of SeoTag (Liquid::Tag).

The original class body performed file-system path resolution and YAML parsing AT CLASS-BODY LOAD TIME, i.e. as soon as Ruby required the plugin file. That had several problems:

1. `File.dirname(__FILE__).sub('_plugins/seo', '')` was a no-op
   (the substring did not appear in __FILE__), so @project_path
   ended up at <site>/_plugins instead of <site>/, and every
   _data/... lookup beneath it pointed at a non-existent folder.

2. `YAML::load(File.open(...))` leaked the file handle, used the
   unsafe loader, and raised on a missing file. A YAML problem at
   load time prevents the plugin from being required at all.

3. `default.merge!(user)` mutated the loaded defaults hash.

4. There was no access to `site.source` at file-load time, so the
   path computation could only be heuristic.

The fix is to defer all of (1)-(4) to first-render time, when a Liquid context (and therefore ‘context.registers.source`) is available. A class-level memo (`SeoTag.site_source`) is set on the very first `render` call and reused thereafter.

Defined Under Namespace

Modules: UrlHelper Classes: AuthorDrop, Drop, Filters, ImageDrop, JSONLDDrop

Constant Summary collapse

MINIFY_REGEX =

Matches all whitespace that follows either

1. A '}', which closes a Liquid tag
2. A '{', which opens a JSON block
3. A '>' followed by a newline, which closes an XML tag or
4. A ',' followed by a newline, which ends a JSON line

We will strip all of this whitespace to minify the template We will not strip any whitespace if the next character is a ‘-’

so that we do not interfere with the HTML comment at the
very beginning
%r!(?<=[{}]|[>,]\n)\s+(?\!-)!.freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(_tag_name, text, _tokens) ⇒ SeoTag

Returns a new instance of SeoTag.



146
147
148
149
# File 'lib/starter_web/_plugins/seo/j1-seo-tags.rb', line 146

def initialize(_tag_name, text, _tokens)
  super
  @text = text
end

Class Attribute Details

.site_sourceObject

Site source is captured at first render (see ‘render` above) and used to resolve plugin/template paths lazily.



200
201
202
# File 'lib/starter_web/_plugins/seo/j1-seo-tags.rb', line 200

def site_source
  @site_source
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



130
131
132
# File 'lib/starter_web/_plugins/seo/j1-seo-tags.rb', line 130

def context
  @context
end

Class Method Details

.templateObject



202
203
204
# File 'lib/starter_web/_plugins/seo/j1-seo-tags.rb', line 202

def template
  @template ||= Liquid::Template.parse template_contents
end

Instance Method Details

#render(context) ⇒ Object



151
152
153
154
155
156
157
158
159
160
# File 'lib/starter_web/_plugins/seo/j1-seo-tags.rb', line 151

def render(context)
  @context = context

  # Stash the site source on the class on first render so the lazy
  # template/config helpers below can resolve _data/plugins/... and
  # _data/templates/... without relying on __FILE__ heuristics.
  #
  SeoTag.site_source ||= context.registers[:site].source
  SeoTag.template.render!(payload, info)
end