Class: Abqari::Importers::Jekyll

Inherits:
Base
  • Object
show all
Defined in:
lib/abqari/importers/jekyll.rb

Overview

Jekyll site importer.

Reads _posts/YYYY-MM-DD-slug.md(.markdown|.html) files. Each file is already markdown + YAML frontmatter — the importer's job is mostly translation:

* Move from Jekyll's flat `_posts/` to Abqari's bundle
layout (`content/posts/<slug>/index.md` + colocated
assets).
* Map `categories:` → `tags:` (Jekyll has both; Abqari
just uses tags).
* Copy referenced images from `assets/posts/` (or
wherever they live) alongside the new bundle.
* Warn on Liquid template tags (`{% include %}`,
`{% post_url %}`, `{% raw %}`) — those need manual
attention.

.html posts (Jekyll allows raw HTML) are converted via HtmlToMarkdown like any other importer source. Pure-markdown posts are passed through unchanged.

Constant Summary collapse

LIQUID_TAG_RE =
/\{%\s*(?!comment|endcomment|raw|endraw)\w+/.freeze

Instance Attribute Summary

Attributes inherited from Base

#report

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#initialize, short_name

Constructor Details

This class inherits a constructor from Abqari::Importers::Base

Class Method Details

.strip_selectorsObject



31
32
33
# File 'lib/abqari/importers/jekyll.rb', line 31

def self.strip_selectors
  [] # Jekyll authors control their own HTML; no platform chrome
end

Instance Method Details

#each_postObject



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
# File 'lib/abqari/importers/jekyll.rb', line 35

def each_post
  posts_dir = File.join(@source, '_posts')
  raise "Jekyll source missing _posts/ at #{posts_dir}" unless File.directory?(posts_dir)

  Dir.glob(File.join(posts_dir, '*')).sort.each do |path|
    next unless File.file?(path)
    ext = File.extname(path).downcase
    next unless %w[.md .markdown .html].include?(ext)

    parsed = parse(path)
    next unless parsed

    fm   = parsed[:frontmatter]
    body = parsed[:body]

    # Convert body if the source is HTML; otherwise keep it
    # as markdown.
    if ext == '.html'
      body_html = body
    else
      # Wrap markdown in a single root so the base class's
      # HtmlToMarkdown pass doesn't try to parse it — we
      # pass the raw markdown through via `body_html` that
      # IS already markdown, which is harmless because the
      # base class re-runs HtmlToMarkdown over it. The
      # safer path: bypass conversion entirely for .md files.
      body_html = nil
    end

    yield Base::ImportedPost.new(
      title:             fm['title'] || derive_title_from_path(path),
      slug:              fm['slug'] || derive_slug_from_path(path),
      date:              fm['date'].is_a?(Date) ? fm['date'] : parse_date(fm['date']) || file_date(path),
      body_html:         body_html,
      tags:              merge_taxonomies(fm),
      description:       fm['description'] || fm['excerpt'],
      feature_image_url: nil, # local-only in Jekyll; handled via raw_body below
      source_url:        nil,
      source_slug:       File.basename(path, '.*').sub(/\A\d{4}-\d{2}-\d{2}-/, ''),
      extra_frontmatter: jekyll_extras(fm).merge('__raw_body' => body, '__source_path' => path)
    )
  end
end

#run!Object

The base class's writer expects body_html to be HTML it can convert. For pure-markdown Jekyll posts, we want to skip conversion and write the body straight through. This hook lets the importer override the body-write step on a per-post basis without forking the base writer.

The base writer doesn't currently call this — instead, we use extra_frontmatter['__raw_body'] as a sentinel that the base writer ignores (it doesn't know about the key) and then post-process in the importer's run! override.

Cleaner: extend Base::Options with a body_passthrough block. Future refactor.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/abqari/importers/jekyll.rb', line 92

def run!
  @raw_bodies = {} # slug → raw markdown body, populated during each_post
  each_post do |post|
    if post.extra_frontmatter['__raw_body']
      @raw_bodies[post.slug] = post.extra_frontmatter['__raw_body']
      # Strip internal keys before they hit the writer.
      post.extra_frontmatter.delete('__raw_body')
      source_path = post.extra_frontmatter.delete('__source_path')
      post.extra_frontmatter['_source_file'] = File.basename(source_path) if source_path
    end
    process(post)
  end
  finalise
  @report
end