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.("..", __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
-
.asset_entries ⇒ Object
[relative_dir, filename] for everything this gem publishes.
-
.build_url(src, embed: true, mode: "read") ⇒ Object
Builds the notebook URL, folding in the query parameters marimo understands.
- .config(site) ⇒ Object
- .escape(value) ⇒ Object
-
.page_enabled?(page) ⇒ Boolean
Page-level opt-in.
- .provenance ⇒ Object
Class Method Details
.asset_entries ⇒ Object
[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 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.
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 |
.provenance ⇒ Object
56 57 58 |
# File 'lib/al_marimo.rb', line 56 def provenance @provenance ||= JSON.parse(File.read(File.join(VENDOR_ROOT, "provenance.json"))) end |