Class: Abqari::TaxonomyPage

Inherits:
Object
  • Object
show all
Defined in:
lib/abqari/taxonomy_page.rb

Constant Summary collapse

'/:taxonomy/:slug/'
DEFAULT_LAYOUT =
'taxonomy'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(taxonomy, term, posts, site) ⇒ TaxonomyPage

Returns a new instance of TaxonomyPage.



12
13
14
15
16
17
18
# File 'lib/abqari/taxonomy_page.rb', line 12

def initialize(taxonomy, term, posts, site)
  @taxonomy = taxonomy
  @term = term
  @posts = posts
  @site = site
  @config = site.taxonomy_config(taxonomy)
end

Instance Attribute Details

#postsObject (readonly)

Returns the value of attribute posts.



10
11
12
# File 'lib/abqari/taxonomy_page.rb', line 10

def posts
  @posts
end

#siteObject (readonly)

Returns the value of attribute site.



10
11
12
# File 'lib/abqari/taxonomy_page.rb', line 10

def site
  @site
end

#taxonomyObject (readonly)

Returns the value of attribute taxonomy.



10
11
12
# File 'lib/abqari/taxonomy_page.rb', line 10

def taxonomy
  @taxonomy
end

#termObject (readonly)

Returns the value of attribute term.



10
11
12
# File 'lib/abqari/taxonomy_page.rb', line 10

def term
  @term
end

Instance Method Details

#bundle_imagesObject

Bundle images aren't sitemap-relevant for tag pages — they live on the posts.



90
91
92
# File 'lib/abqari/taxonomy_page.rb', line 90

def bundle_images
  []
end

#contentObject



37
38
39
# File 'lib/abqari/taxonomy_page.rb', line 37

def content
  ''
end

#descriptionObject



31
32
33
34
35
# File 'lib/abqari/taxonomy_page.rb', line 31

def description
  return "#{posts.size} item#{'s' if posts.size != 1} in this series." if @config['field'] == 'series'

  "All posts tagged #{term}."
end

#frontmatterObject



41
42
43
# File 'lib/abqari/taxonomy_page.rb', line 41

def frontmatter
  {}
end

#lastmodObject

Reflect the latest update across the posts this taxonomy collects.



85
86
87
# File 'lib/abqari/taxonomy_page.rb', line 85

def lastmod
  posts.map(&:lastmod).compact.max
end

#layout_nameObject

Incremental rendering — re-render when shared deps change or any post in this taxonomy was modified more recently than this page's output. The layout this page renders through. Shared by render and needs_render? so the staleness check can't drift from what's actually rendered.



99
100
101
# File 'lib/abqari/taxonomy_page.rb', line 99

def layout_name
  @config['layout'] || DEFAULT_LAYOUT
end

#needs_render?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/abqari/taxonomy_page.rb', line 103

def needs_render?
  return true unless File.exist?(output_path)

  output_mtime = File.mtime(output_path)
  return true if @site.shared_deps_mtime > output_mtime
  # Layouts are deliberately excluded from GLOBAL_DEP_GLOBS and
  # tracked per-page instead (see Renderer::GLOBAL_DEP_GLOBS). Only
  # Page consulted them, so editing `taxonomy.html.erb` with the dev
  # server running rebuilt nothing and the browser reloaded to stale
  # HTML.
  return true if @site.layout_deps_mtime(layout_name) > output_mtime

  posts.any? { |post| (post.lastmod || Time.now) > output_mtime }
end

#output_pathObject



80
81
82
# File 'lib/abqari/taxonomy_page.rb', line 80

def output_path
  File.join(@site.output_dir, url.sub(%r{\A/}, '').chomp('/'), 'index.html')
end

#term_slugObject

The term's URL segment, refusing to be empty.

slugify strips to URL-safe ASCII, so a term with no Latin characters — a CJK or Arabic tag — produces "". That collapsed /tags/:slug/ to /tags/, and the page then wrote over the taxonomy index at _site/tags/index.html. With two such terms the build did fail, via detect_output_collisions!, but the message named colliding paths rather than the tag that caused them.

Page#render_permalink has had this guard for page slugs; this is the same failure one level up, so it fails the same way and names the term.

Raises:



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/abqari/taxonomy_page.rb', line 66

def term_slug
  slug = Helpers.slugify(term)
  return slug unless slug.empty?

  # The term is interpolated raw rather than via `inspect`: when the
  # process's default encoding isn't UTF-8, `inspect` renders it as
  # `日本語`, and a user staring at escape sequences
  # can't tell which of their tags is at fault.
  raise PathSafe::Error,
        %(the #{taxonomy} term "#{term}" produced an empty slug — it has no ) +
        'URL-safe characters, so its page would overwrite the taxonomy index. ' \
        'Rename the term, or add a Latin-character alias.'
end

#titleObject



20
21
22
23
24
25
26
27
28
29
# File 'lib/abqari/taxonomy_page.rb', line 20

def title
  # Series taxonomies (configured with `field: series`) get a
  # cleaner h1 / <title> — just the series name, e.g. "Damascus
  # 2026" rather than "Posts tagged 'Damascus 2026'". Other
  # taxonomies (tags, countries, etc.) keep the historical
  # "tagged" framing.
  return term.to_s if @config['field'] == 'series'

  "Posts tagged ‘#{term}"
end

#urlObject



45
46
47
48
49
50
51
52
# File 'lib/abqari/taxonomy_page.rb', line 45

def url
  permalink = @config['permalink'] || DEFAULT_PERMALINK
  '/' + permalink
    .gsub(':taxonomy', taxonomy)
    .gsub(':slug', term_slug)
    .sub(%r{\A/}, '')
    .sub(%r{/?\z}, '/')
end

#writeObject



118
119
120
121
# File 'lib/abqari/taxonomy_page.rb', line 118

def write
  FileUtils.mkdir_p(File.dirname(output_path))
  File.write(output_path, @site.post_process(render, page: self))
end