Module: AlMarimo

Defined in:
lib/al_marimo.rb,
lib/al_marimo/version.rb

Overview

Embeds marimo notebooks, and turns Python code blocks into runnable snippets.

Two-layer gating, per the al-folio contract: the gem must be loaded and the page must opt in with marimo: true in its front matter. Without the page opt-in every tag renders an empty string, so a site that bundles this plugin pays nothing on pages that do not use it.

Defined Under Namespace

Classes: AssetsGenerator, EmbedTag, PluginStaticFile, ScriptsTag, StylesTag

Constant Summary collapse

PLUGIN_ROOT =
File.expand_path("..", __dir__)
LIB_ROOT =

Jekyll writes a StaticFile to /

/, where is relative to the base below. That base must be lib/, not the gem root, or assets land at /lib/assets/... while every tag in this file points at /assets/... .

__dir__
ASSETS_ROOT =
File.join(LIB_ROOT, "assets")
VENDOR_ROOT =
File.join(PLUGIN_ROOT, "lib", "vendor")
DEFAULT_PLAYGROUND =

marimo runs the notebook itself; only these origins are ever contacted.

"https://marimo.app"
VERSION =
"1.0.0"

Class Method Summary collapse

Class Method Details

.asset_entriesObject

[relative_dir, filename] for everything this gem publishes. Exposed so the destination path can be asserted without booting a full Jekyll site.



83
84
85
86
87
# File 'lib/al_marimo.rb', line 83

def asset_entries
  Dir.glob(File.join(ASSETS_ROOT, "**", "*")).sort.reject { |p| File.directory?(p) }.map do |source_path|
    [File.dirname(source_path).sub("#{LIB_ROOT}/", ""), File.basename(source_path)]
  end
end

.build_url(src, embed: true, mode: "read") ⇒ Object

Builds the notebook URL, folding in the query parameters marimo understands.

Appends with the correct separator rather than assuming the caller passed a bare URL: ?embed=true on a URL that already has a query string produces a link that silently loads the wrong notebook.



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/al_marimo.rb', line 69

def build_url(src, embed: true, mode: "read")
  url = src.to_s.strip
  return nil if url.empty?

  separator = url.include?("?") ? "&" : "?"
  if embed
    url = "#{url}#{separator}embed=true"
    separator = "&"
  end
  "#{url}#{separator}mode=#{mode == "edit" ? "edit" : "read"}"
end

.config(site) ⇒ Object



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

def config(site)
  return {} unless site

  site.config["al_marimo"] || {}
end

.escape(value) ⇒ Object



60
61
62
# File 'lib/al_marimo.rb', line 60

def escape(value)
  CGI.escapeHTML(value.to_s)
end

.page_enabled?(page) ⇒ Boolean

Page-level opt-in. Anything truthy other than the string "false" counts, so marimo: true and marimo: snippets both work.

Reads through [] rather than testing for Hash: at render time Jekyll hands registers[:page] a Drop (Jekyll::Drops::DocumentDrop), not a Hash, so an is_a?(Hash) guard silently discards the front matter and the feature never switches on for any real page.

Returns:

  • (Boolean)


44
45
46
47
48
49
50
51
52
53
54
# File 'lib/al_marimo.rb', line 44

def page_enabled?(page)
  value = begin
    page.respond_to?(:[]) ? page["marimo"] : nil
  rescue StandardError
    nil
  end
  return false if value.nil? || value == false
  return false if value.respond_to?(:strip) && ["", "false"].include?(value.strip.downcase)

  true
end

.provenanceObject



56
57
58
# File 'lib/al_marimo.rb', line 56

def provenance
  @provenance ||= JSON.parse(File.read(File.join(VENDOR_ROOT, "provenance.json")))
end