Class: Jekyll::Carve::Converter

Inherits:
Jekyll::Converter
  • Object
show all
Defined in:
lib/jekyll-carve.rb

Overview

Jekyll converter for the Carve markup language.

Registers the .crv file extension and renders Carve bodies to HTML by delegating to the native carve-lang gem (Carve.to_html). No parsing is reimplemented here; this is a thin Jekyll::Converter adapter over the engine.

Constant Summary collapse

EXTENSIONS =

File extensions this converter handles (lowercased, with and without the leading dot so callers may pass either form).

%w[.crv].freeze

Instance Method Summary collapse

Instance Method Details

#carve_extensionsObject

Carve extensions configured under carve.extensions in _config.yml.

Returns an Array of extension names (Strings/Symbols passed through to the engine). Empty when nothing is configured.



71
72
73
# File 'lib/jekyll-carve.rb', line 71

def carve_extensions
  Array(carve_config["extensions"])
end

#carve_symbolsObject

The :name: symbol map configured under carve.symbols in _config.yml.

Carve parses :name: in core, but what a name renders as is a render option, so a document reaching the engine without a map renders the shortcode as its own source text.

The key accepts three shapes:

carve:
symbols:                    # a mapping, written inline
  smile: "😄"

carve:
symbols: _data/symbols.json # a path to a JSON object

carve:
symbols:                    # both, merged left to right
  - _data/emoji.json
  - { ship: "🚀" }

A path is resolved against the site source and clamped inside it, so it names a file in the project and never one outside it.

SECURITY: the engine substitutes a symbol value as TRUSTED RAW output - it is NOT escaped, so { "l" => "<img src='/l.svg'>" } emits a real element. carve-rb states the rule this inherits: "NEVER build a symbols map out of untrusted / user-supplied input." That is why the only inputs here are _config.yml and files at paths named in it. Page content and front matter cannot reach this method - convert ignores its argument when building the map, and Jekyll hands a converter no front matter at all.

Returns a Hash of String name => String value, or nil when nothing is configured (nil, so the engine keeps its own default rather than being told there are no symbols).



110
111
112
113
114
# File 'lib/jekyll-carve.rb', line 110

def carve_symbols
  return @symbols if defined?(@symbols)

  @symbols = build_symbols
end

#convert(content) ⇒ Object

Convert a Carve document body to HTML.

Jekyll strips the YAML front matter before calling this, so content is the Carve body only.

content - String body of the source file (front matter removed).

Returns the rendered HTML String.



61
62
63
64
65
# File 'lib/jekyll-carve.rb', line 61

def convert(content)
  ::Carve.to_html(content.to_s,
                  extensions: carve_extensions,
                  symbols: carve_symbols)
end

#matches(ext) ⇒ Object

Does the given file extension belong to Carve?

Accepts both ".crv" and "crv" (Jekyll passes the dotted form).

ext - The String extension to check.

Returns true if it matches, false otherwise.



33
34
35
36
37
38
39
# File 'lib/jekyll-carve.rb', line 33

def matches(ext)
  return false if ext.nil?

  normalized = ext.to_s.downcase
  normalized = ".#{normalized}" unless normalized.start_with?(".")
  EXTENSIONS.include?(normalized)
end

#output_ext(_ext) ⇒ Object

The output extension for a converted Carve file.

Jekyll appends this string directly to the output path (":basename:output_ext"), so it MUST include the leading dot to produce "index.html" rather than "indexhtml". This matches Jekyll's own Markdown converter, which returns ".html".

Returns ".html".



49
50
51
# File 'lib/jekyll-carve.rb', line 49

def output_ext(_ext)
  ".html"
end

#reset_symbolsObject

Drop the cached map, so the next render resolves it again.

Called from the :site, :after_reset hook at the bottom of this file, which is what makes the map resolve once per BUILD rather than once per process. Jekyll instantiates converters from Site#initialize while Site#process calls only reset, so under jekyll serve --watch ONE converter instance serves every rebuild - and a map memoized outright would keep serving a file the author has since edited.

Returns nothing.



126
127
128
# File 'lib/jekyll-carve.rb', line 126

def reset_symbols
  remove_instance_variable(:@symbols) if defined?(@symbols)
end