<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
  <author>
    <name>Brooke Kuhlmann</name>
    <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
  </author>
  <category term="projects"
    label="Projects"/>
  <generator uri="https://alchemists.io"
    version="0.3.0">Alchemists</generator>
  <icon>https://alchemists.io/favicon.ico</icon>
  <id>https://alchemists.io/projects</id>
  <link href="https://alchemists.io/projects"
    rel="alternate"
    type="text/html"
    title="Alchemists: Projects (web)"/>
  <link href="https://alchemists.io/feeds/projects.xml"
    rel="self"
    type="application/atom+xml"
    title="Alchemists: Projects (feed)"/>
  <logo>https://alchemists.io/images/logo/syndication.png</logo>
  <rights>2026</rights>
  <subtitle>Software projects available for use and in collaboration with others.</subtitle>
  <title>Alchemists: Projects</title>
  <updated>2026-10-09T16:00:48+00:00</updated>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/metapath&quot;&gt;
    &lt;img src=&quot;/images/projects/metapath/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/metapath&quot;&gt;Metapath&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dynamically parses and enriches paths metadata so you can obtain information from directories and files with minimal effort. Having metadata for each directory and/or file&amp;#8201;&amp;#8212;&amp;#8201;no matter how nested your directory structure is&amp;#8201;&amp;#8212;&amp;#8201;allows you to perform additional processing on your file structure for analysis, transformation, import, and so much more.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_roots&quot;&gt;Roots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_directories_and_files&quot;&gt;Directories and Files&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_positions&quot;&gt;Positions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tags&quot;&gt;Tags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_attributes&quot;&gt;Attributes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_configurations&quot;&gt;Configurations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_priority&quot;&gt;Priority&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_monads&quot;&gt;Monads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_models&quot;&gt;Models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dynamically obtains metadata about a directory or a file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Supports an optional, per directory, configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Supports nested directory structures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Answers an array of paths with associated metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;metapath &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;metapath&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add metapath&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;metapath&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Getting started is as quick as creating an instance and then pointing it at a directory structure:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pwd&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Metapath::Model:0x00002710&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Crested Butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;crested_butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Pathname:/Users/demo/Scratch/photos/Crested_Butte.jpeg&amp;gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Metapath::Model:0x00002780&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Flaming Gorge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;flaming_gorge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Pathname:/Users/demo/Scratch/photos/Flaming_Gorge.jpeg&amp;gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Metapath::Model:0x000027f0&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Grand Canyon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;grand_canyon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Pathname:/Users/demo/Scratch/photos/Grand_Canyon.jpeg&amp;gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_roots&quot;&gt;Roots&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When calling a metapath, you must always supply a root path for processing. In the earlier example, this was &lt;code&gt;Pathname.pwd&lt;/code&gt; (current path):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pwd&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Strings, if supplied, will be automatically converted into pathnames and auto-expanding into absolute paths. Examples:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~/photos&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Expands to: #&amp;lt;Pathname:/Users/&amp;lt;your user&amp;gt;/photos&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;photos&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Expands to: #&amp;lt;Pathname:&amp;lt;current working directory&amp;gt;/photos&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;metapath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/Users/demo/photos&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Identical: &quot;#&amp;lt;Pathname:/Users/demo/photos&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All directories and files will be processed within the root path supplied (no matter how deeply nested).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_directories_and_files&quot;&gt;Directories and Files&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each directory and file can have it&amp;#8217;s own metadata using any of the following characters:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;0-9&lt;/code&gt;: Any number is valid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;a-z&lt;/code&gt;: Any lowercase letter is valid. This includes Unicode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;A-Z&lt;/code&gt;: Any uppercase letter is valid. This includes Unicode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-&lt;/code&gt; (hyphen): Translates to &lt;code&gt;&quot; - &quot;&lt;/code&gt; when building the label. Example:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Before: &lt;code&gt;A-Demo&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After: &lt;code&gt;A - Demo&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_&lt;/code&gt; (underscore): Translates to &lt;code&gt;&quot; &quot;&lt;/code&gt; when building the label. Example:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Before: &lt;code&gt;A_Demo&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After: &lt;code&gt;A Demo&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;+&lt;/code&gt; (plus): Marks the start of tag or attribute information. See examples below for details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;,&lt;/code&gt; (comma): Specifies an array of tag or attribute metdata. See examples below for details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;=&lt;/code&gt; (equals): Delimits the key and value of an attribute. For example &lt;code&gt;kind=demo&lt;/code&gt;, where &lt;code&gt;kind&lt;/code&gt; is the key and &lt;code&gt;demo&lt;/code&gt; is the value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;%&lt;/code&gt; (percent): Reserved for token replacement as commonly found in &lt;a href=&quot;https://alchemists.io/projects/rubysmith&quot;&gt;Rubysmith&lt;/a&gt; for processing of templates where you want to dynamically replace each placeholder (example: &lt;code&gt;%demo%&lt;/code&gt;) with a dynamic value that matches the &lt;code&gt;demo&lt;/code&gt; key (in this example). Currently meant for post-processing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.&lt;/code&gt; (dot): Reserved for file extensions or multiple formats. Example: &lt;code&gt;demo.html&lt;/code&gt;, &lt;code&gt;demo.html.erb&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;~&lt;/code&gt; (tilde): Reserved but currently not used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;@&lt;/code&gt; (at): Reserved but currently not used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;^&lt;/code&gt; (carrot): Reserved but currently not used.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All of the characters shown above allow you to have files and directories that don&amp;#8217;t require special quoting which works well across multiple operating systems.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_positions&quot;&gt;Positions&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prefix your directories or files with a number immediately followed by a dash to keep them organized but also for sequential processing order.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Format&lt;/strong&gt;: &lt;code&gt;&amp;lt;position&amp;gt;-&amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; &lt;code&gt;01-demo&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The position is always &lt;code&gt;0&lt;/code&gt; when none is given.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_tags&quot;&gt;Tags&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Use tags to provide additional metadata about your directories and files (use a comma to separate multiple values).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Format&lt;/strong&gt; (single): &lt;code&gt;&amp;lt;name&amp;gt;+&amp;lt;tag&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (single): &lt;code&gt;demo+blue&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Format&lt;/strong&gt; (multiple): &lt;code&gt;&amp;lt;name&amp;gt;+&amp;lt;tag&amp;gt;,&amp;lt;tag&amp;gt;,&amp;lt;tag&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (multiple): &lt;code&gt;demo+blue,red,green&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 Use a directory configuration (&lt;code&gt;meta.yml&lt;/code&gt;) to extract common metadata if your metadata gets too long and unwieldy.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_attributes&quot;&gt;Attributes&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Use attributes to provide additional metadata about your directories and files (use a comma to separate multiple values).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Format&lt;/strong&gt; (single): &lt;code&gt;&amp;lt;name&amp;gt;+&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (single): &lt;code&gt;demo+album=panoramas&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Format&lt;/strong&gt; (multiple): &lt;code&gt;&amp;lt;name&amp;gt;+&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;,&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;,&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; (multiple): &lt;code&gt;demo+album=panoramas,kind=landscapes,location=snow_peak&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 Use a directory configuration (&lt;code&gt;meta.yml&lt;/code&gt;) to extract common metadata if your metadata gets too long and unwieldy.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_configurations&quot;&gt;Configurations&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can configure common metadata per directory by placing a &lt;code&gt;meta.yml&lt;/code&gt; in the root of any directory. The following is an example of what this file might contain:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;demo&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;photos&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;album&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;panoramas&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;landscapes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the above, you can supply as many tags and attributes as necessary which will then be inherited as common metadata when processing files within the directory. This includes inheriting  configurations from parent directories. Keep in mind that any file with it&amp;#8217;s own metdata will take precedence.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Only the &lt;code&gt;tag&lt;/code&gt; and &lt;code&gt;attributes&lt;/code&gt; keys are honored, all other top level keys are ignored.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_priority&quot;&gt;Priority&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Metadata is resolved by merging each of the following in order listed (lowest to highest):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Directory&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;meta.yml&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;File&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Resolution of the above happens by merging metadata from the lowest level into the next level until all levels are merged as one. This means you can set defaults at the lowest level which will be inherited, or overwritten, at the highest level. In pseudo code, it looks like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deep_merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deep_merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_monads&quot;&gt;Monads&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Every time you call your metapath instance, you&amp;#8217;ll get either a &lt;code&gt;Success&lt;/code&gt; or &lt;code&gt;Failure&lt;/code&gt; as provided by &lt;a href=&quot;https://dry-rb.org/gems/dry-monads&quot;&gt;Dry Monads&lt;/a&gt;. This allows you to use the &lt;a href=&quot;https://alchemists.io/articles/railway_pattern&quot;&gt;Railway Pattern&lt;/a&gt; pattern to build fault tolerant functional pipelines for robust error processing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When results are a success, you&amp;#8217;ll get an array of models. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Metapath::Model:0x00002710&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Crested Butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;crested_butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Pathname:/Users/demo/Scratch/photos/Crested_Butte.jpeg&amp;gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can get a success when errors are detected with metadata associated with your directories or files. For example, let&amp;#8217;s say your &lt;code&gt;meta.yml&lt;/code&gt; has the following content:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code&gt;attributes:&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Metapath::Model:0x00002710&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;errors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;attributes: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;must be filled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]},&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Crested Butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;crested_butte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Pathname:/Users/demo/Scratch/photos/Crested_Butte.jpeg&amp;gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If a failure does occur, this usually means errors with your configuration. For example, let&amp;#8217;s say your &lt;code&gt;meta.yml&lt;/code&gt; has the following content:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;s&quot;&gt;Danger!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means you&amp;#8217;ll get the following result:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Failure&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Invalid content: Danger.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_models&quot;&gt;Models&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each model is a &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; object. Additionally, the following methods are also provided for you:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Metapath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;label: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;tags: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w[demo photos]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;attributes: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;album&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;panoramas&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;kind&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;landscapes&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;album&quot;&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# &quot;panoramas&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bogus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fallback&quot;&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &quot;fallback&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bogus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fallback&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;fallback&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bogus&quot;&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# KeyError&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;album&quot;&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;key?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bogus&quot;&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tag?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;photos&quot;&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tag?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bogus&quot;&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Metapath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;other&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;path: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;_demo.html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partial?&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partial?&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Metapath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;other&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;path: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;demo.html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;errors: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;message: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Danger!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errors?&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errors?&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/metapath
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;metapath
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/metapath/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/metapath</id>
    <link href="https://alchemists.io/projects/metapath"/>
    <published>2026-10-08T22:31:01+00:00</published>
    <rights>2026</rights>
    <title>Metapath Project</title>
    <updated>2026-10-09T16:00:48+00:00</updated>
    <dc:date>2026-10-09T16:00:48+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/superfluid&quot;&gt;
    &lt;img src=&quot;/images/projects/superfluid/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/superfluid&quot;&gt;Superfluid&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enhances &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; by smoothing out the rough edges with a strong focus on object composition and functional design. This includes a fully functional filter and tag registry so you can reuse lower level filters and tags within all aspects of your view layer.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_environments&quot;&gt;Environments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_systems&quot;&gt;Systems&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_memory&quot;&gt;Memory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_local&quot;&gt;Local&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_blank&quot;&gt;Blank&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_filters&quot;&gt;Filters&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_defaults&quot;&gt;Defaults&lt;/a&gt;
&lt;ul class=&quot;sectlevel4&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_jsonify&quot;&gt;&lt;code&gt;jsonify&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_parse_json&quot;&gt;&lt;code&gt;parse_json&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_pluralize&quot;&gt;&lt;code&gt;pluralize&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_singularize&quot;&gt;&lt;code&gt;singularize&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_trim_end&quot;&gt;&lt;code&gt;trim_end&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_trim_middle&quot;&gt;&lt;code&gt;trim_middle&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_modules&quot;&gt;Modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_functionables&quot;&gt;Functionables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_procs_and_lambdas&quot;&gt;Procs and Lambdas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_classes&quot;&gt;Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_containers&quot;&gt;Containers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tags&quot;&gt;Tags&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_defaults_2&quot;&gt;Defaults&lt;/a&gt;
&lt;ul class=&quot;sectlevel4&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_template&quot;&gt;&lt;code&gt;template&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_containers_2&quot;&gt;Containers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Uses a customizable default environment with a cleaner Object API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Uses &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt; for filter and tag registries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Registers filters via a &lt;code&gt;Module&lt;/code&gt;, &lt;a href=&quot;https://alchemists.io/projects/functionable&quot;&gt;Functionable&lt;/a&gt;, commands (see &lt;a href=&quot;https://alchemists.io/articles/command_pattern&quot;&gt;Command Pattern&lt;/a&gt; for details), or containers (see &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt; for details).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Registers tags via classes or containers (see &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt; for details).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides a default renderer for quick rendering of templates and associated data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;superfluid &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;superfluid&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add superfluid&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;superfluid&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The quickest way to get started is to create a new instance:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Then you can render your template and associated data:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hi, this is a {{ value }}.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;value&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;demo&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above will yield the following output:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&quot;Hi, this is a demo.&quot;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following sections detail how you can configure your environment, register filters, and register tags.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The configuration is used by the environment. This is created for you automatically but if you want an instance of the default configuration, use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Struct:Superfluid::Configuration:0x00001780&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;default_resource_limits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;error_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:strict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;exception_renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Proc:0x0000000131200ee0 (lambda)&amp;gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;file_system&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data Superfluid::Systems::Memory:0x000017b0 templates = {}&amp;gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;filter_registry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Superfluid::Registries::Filter:0x000000012f5a1290 @container=Superfluid::Filters::Container, @mode=:strict&amp;gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tag_registry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;Superfluid::Registries::Tag:0x000000012f5860d0 @container=Superfluid::Tags::Container&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you can see, the configuration is a &lt;a href=&quot;https://alchemists.io/articles/ruby_structs&quot;&gt;Struct&lt;/a&gt; which means you can customize using any of these attributes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;default_resource_limits&lt;/code&gt;: Limits the resources that a template can consume. Default: &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;error_mode&lt;/code&gt;: The error mode (&lt;a href=&quot;https://github.com/Shopify/liquid#error-modes&quot;&gt;details&lt;/a&gt;). Default: &lt;code&gt;:strict&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;exception_renderer&lt;/code&gt;: The function used to render error messages. Default: &lt;code&gt;Core::Identity&lt;/code&gt; (see &lt;a href=&quot;https://alchemists.io/projects/core&quot;&gt;Core&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;file_system&lt;/code&gt;: The file system. Default: &lt;code&gt;Superfluid::Systems::Memory.new&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;filter_registry&lt;/code&gt;: The filter registry. Default: &lt;code&gt;Superfluid::Registries::Filter.new&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;tag_registry&lt;/code&gt;: The tag registry. Default: &lt;code&gt;Superfluid::Registries::Tag.new&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_environments&quot;&gt;Environments&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To build the default environment, use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To build the default environment directly (which is what the above does), use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;d like to build a custom environment, you can do this several ways. For demonstration purposes, only the &lt;code&gt;error_mode&lt;/code&gt; is used below but all configuration attributes are accepted:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;error_mode: :lax&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;error_mode: :lax&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;error_mode: :lax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also freeze the environment&amp;#8201;&amp;#8212;&amp;#8201;which also freezes the filter and tag registries&amp;#8201;&amp;#8212;&amp;#8201;once you&amp;#8217;ve registered any/all filters and tags as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;freeze&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_systems&quot;&gt;Systems&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;These are the file systems used to obtain templates for use within your custom tags. By default, an in memory system is provided for you: &lt;code&gt;Superfluid::Systems::Memory&lt;/code&gt;. &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; also provides it&amp;#8217;s own systems as well. Each are described below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_memory&quot;&gt;Memory&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Provided by this gem. Use to access templates via an in memory file system. This is enabled for you be default when using &lt;code&gt;Superfluid.new&lt;/code&gt; and works in conjunction with the &lt;code&gt;template&lt;/code&gt; tag which is also provided by this gem (see below for details). Again, this system is provided for you but you can be explicit if desired:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;file_system: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Systems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONTENT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
  {% template demo %}
    Hi, this is a {{ subject }}.
  {% endtemplate %}

  {% render &quot;demo&quot;, subject: &quot;demo&quot; %}
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONTENT&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;Hi, this is a demo.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_local&quot;&gt;Local&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Provided by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt;. Use to access templates via your local file system within a specific root folder. Usage:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;templates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;_demo.liquid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{{ salutation }}&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;file_system: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LocalFileSystem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;templates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({% include &quot;demo&quot; %}, this is a demo)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;salutation&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;Hi, this is a demo&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above configures the local system to look for partials (templates) within the &lt;code&gt;templates&lt;/code&gt; folder. You then reference them via the &lt;code&gt;include&lt;/code&gt; tag.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By default, this system uses &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Kernel.html#method-i-format&quot;&gt;Kernel#format&lt;/a&gt; syntax to find your partials (i.e. &lt;code&gt;&quot;_%s.liquid&quot;&lt;/code&gt;). If you don&amp;#8217;t like this pattern, you can configure differently when creating a new instance. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LocalFileSystem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/a/path&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s.html&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_blank&quot;&gt;Blank&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Provided by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt;. This is an abstract class&amp;#8201;&amp;#8212;&amp;#8201;meant for subclassing&amp;#8201;&amp;#8212;&amp;#8201;because it will fail with a &lt;code&gt;FileSystemError&lt;/code&gt; when &lt;code&gt;read_template_file&lt;/code&gt; isn&amp;#8217;t implemented. Usage:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;file_system: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;BlankFileSystem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;templates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above does nothing and is benign.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_filters&quot;&gt;Filters&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By default, &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; only allows registration of filters as instance methods on a namespace (&lt;code&gt;Module&lt;/code&gt;). Unfortunately, this leads to terrible design, bad practices, and unnecessarily hard to test objects. You can still register namespaces but this gem encourages the use of commands (see &lt;a href=&quot;https://alchemists.io/articles/command_pattern&quot;&gt;Command Pattern&lt;/a&gt; for further details) and containers via &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt; which allows you tap into Functional Programming by using procs, lambdas, and any object that responds to &lt;code&gt;#call&lt;/code&gt;. This allows you to build&amp;#8201;&amp;#8212;&amp;#8201;and reuse&amp;#8201;&amp;#8212;&amp;#8201;more powerful filters. The following details the different kinds of filters you can use, each broken down by category.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_defaults&quot;&gt;Defaults&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Default filters are provided for you automatically and can be viewed via your environment. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;build&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter_registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;names&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above will produce a list of all registered filters. These including all filters provided by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; and those unique to this gem which are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_jsonify&quot;&gt;&lt;code&gt;jsonify&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Renders objects as JSON. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ data | jsonify }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;data&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;{\&quot;a\&quot;:1}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_parse_json&quot;&gt;&lt;code&gt;parse_json&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Parses JSON as a primitive. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;{% assign data = payload | parse_json %}{{ data.one }}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;payload&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({&quot;one&quot;: 1, &quot;two&quot;: 2})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_pluralize&quot;&gt;&lt;code&gt;pluralize&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Renders a plural string. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | pluralize: 0 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;0 apples&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | pluralize: 1 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;1 apple&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | pluralize: 2 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;2 apples&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | pluralize: 3, &quot;i&quot;, &quot;us&quot; }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;octopus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;3 octopi&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_singularize&quot;&gt;&lt;code&gt;singularize&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Renders a singular string. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | singularize: 0 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apples&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;0 apples&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | singularize: 1 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apples&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;1 apple&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | singularize: 2 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;apples&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;2 apples&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | singularize: 1, &quot;i&quot;, &quot;us&quot; }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;octopi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;1 octopus&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_trim_end&quot;&gt;&lt;code&gt;trim_end&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Renders string with trimmed end. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_end: 10 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;A demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;A demo.&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_end: 10 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;This is...&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_end: 10, &quot;&quot;, &quot;---&quot; }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;This is---&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_end: 10, &quot;&quot;, &quot;&quot; }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;This is a&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_trim_middle&quot;&gt;&lt;code&gt;trim_middle&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Renders string with trimmed middle. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_middle: 20 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;A demo.&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_middle: 13 }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;This...demo.&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%({{ text | trim_middle: 13, &quot;--&quot; }})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is a demo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;This--demo.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_modules&quot;&gt;Modules&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Module instance methods are what &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; supports by default. You only need to define instance methods within a module and then register your module. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Namespaces&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Primary&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Secondary&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;capitalize&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Renderer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Results&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | echo }})&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# &quot;demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | capitalize }})&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix }})&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &quot;demo-1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix: 2 }})&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;demo-2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you can see, all three methods via the two namespaces are properly registered and immediately available for use. You&amp;#8217;ll also notice multiple namespaces were registered at once but you can register them individually and/or chain them. Examples:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Single.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Multiple.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Chained.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_functionables&quot;&gt;Functionables&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://alchemists.io/projects/functionable&quot;&gt;Functionable&lt;/a&gt; modules are identical to the module examples, as shown above, except you require and extend instead. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;functionable&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Namespaces&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Primary&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Secondary&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;capitalize&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This allows you to use purely functionable methods (see &lt;a href=&quot;https://alchemists.io/projects/functionable&quot;&gt;Functionable&lt;/a&gt; documentation for details). At this point, you can register your functionable namespaces as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Renderer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Results&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | echo }})&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# &quot;demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | capitalize }})&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix }})&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &quot;demo-1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix: 2 }})&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;demo-2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Registration is identical to modules:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Single.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Multiple.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Chained.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Primary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Secondary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_procs_and_lambdas&quot;&gt;Procs and Lambdas&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Procs and lambdas are not supported by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; but are via this gem. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Setup&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;capitalize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Renderer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;suffix: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Results&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | echo }})&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# &quot;demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | capitalize }})&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix }})&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &quot;demo-1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix: 2 }})&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;demo-2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Registration can be singular, plural, or chained:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Single.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Multiple.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Chained.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capitalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_classes&quot;&gt;Classes&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Classes, especially composable classes, are not supported by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; but are via this gem. You only need to ensure you include &lt;code&gt;Core::Composable&lt;/code&gt; and implement the &lt;code&gt;#call&lt;/code&gt; method. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;core&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Suffixer&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Core&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Composable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:default&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now you can register and render with the above class as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Renderer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;suffix: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Suffixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Results&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix }})&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# &quot;demo-1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix: 2 }})&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;demo-2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Registration can be singular, plural, or chained:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Suffixer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Single.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Multiple.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Chained.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_containers&quot;&gt;Containers&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Containers are not supported by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; but are via this gem using &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt;. To use, create a container and then register your dependencies:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;containable&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Container&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Containable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:echo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now you can merge the container as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also selectively merge by supplying only the filters you care about from the container:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge_filters&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:suffix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once registered, then you can use as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | echo }})&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# &quot;demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix }})&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# &quot;demo-1&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%({{ &quot;demo&quot; | suffix: 2 }})&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;demo-2&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With containers, you have the full capabilities of the &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt;. The above only scratches the surface of what&amp;#8217;s possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_tags&quot;&gt;Tags&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As per &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; documentation, tags only need to inherit from &lt;code&gt;Liquid::Tag&lt;/code&gt; and be initialized with &lt;code&gt;tag_name&lt;/code&gt;, &lt;code&gt;factor&lt;/code&gt;, and &lt;code&gt;tokens&lt;/code&gt; parameters. Then you can implement a render method which accepts a &lt;code&gt;context&lt;/code&gt;. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Tag&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Block&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;placeholder&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Renderer&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tag&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Results&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{% sample %}Your value is: &amp;lt;placeholder&amp;gt;.{% endsample %}&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;Your value is: 80.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also register single or multiple tags at once:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Single.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Multiple.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;one: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;two: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Chained.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;one: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;two: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_defaults_2&quot;&gt;Defaults&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You have access to all tags supported by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; including the tags provided by this gem (which is only the &lt;code&gt;template&lt;/code&gt; tag at the moment).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect4&quot;&gt;
&lt;h5 id=&quot;_template&quot;&gt;&lt;code&gt;template&lt;/code&gt;&lt;/h5&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This tag must be used with the &lt;code&gt;Memory&lt;/code&gt; system (see &lt;em&gt;Systems&lt;/em&gt;, mentioned earlier, for details). You can use this tag as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONTENT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
  {% template demo %}
    Hi, this is a {{ subject }}.
  {% endtemplate %}

  {% render &quot;demo&quot;, subject: &quot;demo&quot; %}
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONTENT&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;Hi, this is a demo.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you can see this tag requires two steps:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Define by using the &lt;code&gt;template&lt;/code&gt; tag followed by a unique name for your template (in this case: &lt;code&gt;demo&lt;/code&gt;). You can then use any filters and/or additional tags with your template. Finally, close the tag with &lt;code&gt;endtemplate&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Render your template by using &lt;code&gt;render&lt;/code&gt; followed by the unique name of your template (i.e. &lt;code&gt;demo&lt;/code&gt;) and any attributes you need to provide to the template.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above allows you to define multiple templates for rendering later. Great for situations where you want to organize your in memory code for final later rendering.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_containers_2&quot;&gt;Containers&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Containers are not supported by &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; but are via this gem using &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt;. To use, create a container and then register your dependencies:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;containable&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Container&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Containable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Sample&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now you can merge the container as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge_tags&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also selectively merge by supplying only the tags you care about from the container:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Superfluid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge_tags&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:sample&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once registered, then you can use as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{% sample %}Your value is: &amp;lt;placeholder&amp;gt;.{% endsample %}&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;Your value is: 85.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With containers, you have the full capabilities of the &lt;a href=&quot;https://alchemists.io/projects/containable&quot;&gt;Containable&lt;/a&gt;. The above only scratches the surface of what&amp;#8217;s possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/superfluid
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;superfluid
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/superfluid/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/superfluid</id>
    <link href="https://alchemists.io/projects/superfluid"/>
    <published>2026-08-30T20:54:20+00:00</published>
    <rights>2026</rights>
    <title>Superfluid Project</title>
    <updated>2026-09-15T14:46:48+00:00</updated>
    <dc:date>2026-09-15T14:46:48+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/rfc-api-problem&quot;&gt;
    &lt;img src=&quot;/images/projects/rfc-api-problem/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/rfc-api-problem&quot;&gt;RFC API Problem&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;RFC API Problem implements &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9457&quot;&gt;RFC 9457&lt;/a&gt;: Problem Details for HTTP APIs. This allows you to produce HTTP error responses that are structured, machine readable, and consistent.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_members&quot;&gt;Members&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_media_types&quot;&gt;Media Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_payload&quot;&gt;Payload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_json&quot;&gt;JSON&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_xml&quot;&gt;XML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_examples&quot;&gt;Examples&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_hateoas&quot;&gt;HATEOAS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_semantic_structure&quot;&gt;Semantic Structure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_resources&quot;&gt;Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Provides JSON and XML serialization and deserialization.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides HTTP header and media type support.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rfc-api-problem &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rfc-api-problem&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add rfc-api-problem&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rfc/api/problem&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The quickest way to get started is to create a new instance and then cast as JSON or XML:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/problem_details/timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;413&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;detail: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You&#39;ve exceeded the 5MB upload limit.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;instance: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/profile/3a1bfd54-ae6c-4a61-8d0d-90c132428dc3&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;type&quot; =&amp;gt; &quot;https://demo.io/problem_details/timeout&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;title&quot; =&amp;gt; &quot;Content Too Large&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;status&quot; =&amp;gt; 413,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;detail&quot; =&amp;gt; &quot;You&#39;ve exceeded the 5MB upload limit.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;instance&quot; =&amp;gt; &quot;/profile/3a1bfd54-ae6c-4a61-8d0d-90c132428dc3&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_xml&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;problem xmlns=&#39;urn:ietf:rfc:7807&#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;type&amp;gt;https://demo.io/problem_details/timeout&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;title&amp;gt;Content Too Large&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;status&amp;gt;413&amp;lt;/status&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;detail&amp;gt;You&amp;amp;apos;ve exceeded the 5MB upload limit.&amp;lt;/detail&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;instance&amp;gt;/profile/3a1bfd54-ae6c-4a61-8d0d-90c132428dc3&amp;lt;/instance&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;/problem&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 You can also use &lt;code&gt;RFC::API::Problem.new&lt;/code&gt; to create instances if you don&amp;#8217;t like &lt;code&gt;RFC::API::Problem.[]&lt;/code&gt;, as shown above, but &lt;code&gt;.[]&lt;/code&gt; is preferred.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_members&quot;&gt;Members&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As briefly shown above, the minimum members (attributes) that make up problem details are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt; (optional): The full (or relative) URI that links to additional documentation. Default: &lt;code&gt;&quot;about:blank&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;status&lt;/code&gt; (optional): The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status&quot;&gt;HTTP status code&lt;/a&gt; (or symbol) that must match your HTTP status code. Default: &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;title&lt;/code&gt; (optional): The HTTP status label that must match your HTTP status code label. Default: HTTP status label (dynamically computed based on code unless overwritten).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;detail&lt;/code&gt; (optional): The human readable reason for the error (should not include debugging information). Default: &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;instance&lt;/code&gt; (optional): The full (or relative) URI that represents the cause of the error. Default: &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;extensions&lt;/code&gt; (optional): A free form hash of additional details. Default: &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_media_types&quot;&gt;Media Types&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For convenience, you can obtain the necessary media types for your HTTP headers as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MEDIA_TYPE_JSON&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;application/problem+json&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MEDIA_TYPE_XML&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;application/problem+xml&quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;media_type_for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;application/problem+json&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;media_type_for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:xml&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# &quot;application/problem+xml&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_payload&quot;&gt;Payload&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll always get a &lt;code&gt;RFC::API::Problem::Payload&lt;/code&gt; object answered back when using &lt;code&gt;RFC::API::Problem.[]&lt;/code&gt; or &lt;code&gt;RFC::API::Problem.new&lt;/code&gt; for which you can cast to JSON, XML, and other types. There are few conveniences provided for you when constructing a new payload. For instance, you can also use status to set default title:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;413&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::API::Problem::Payload:0x00002950&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   detail = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   extensions = {},&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   instance = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   status = 413,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   title = &quot;Content Too Large&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   type = &quot;about:blank&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Notice that standard HTTP 413 title of &quot;Content Too Large&quot; is provided for you but only if you don&amp;#8217;t supply a title. This works for symbols too. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;status: :bad_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::API::Problem::Payload:0x00002970&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   detail = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   extensions = {},&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   instance = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   status = 400,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   title = &quot;Bad Request&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   type = &quot;about:blank&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is similar to the above, but notice the status is cast to an integer while the title is also populated for you. Using either an integer or symbol for the HTTP status is handy for situations where you don&amp;#8217;t need a custom title and prefer the default HTTP title.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Due to the payload being a &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; object, you have all of the standard methods available to you which are frozen by default. That said, you can still add or check for extensions after the fact. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code&gt;payload = RFC::API::Problem[status: :forbidden]

payload.add_extension(:account, &quot;/accounts/1&quot;)
       .add_extension(:balance, 50)

# #&amp;lt;data RFC::API::Problem::Payload:0x000029a0
#   detail = nil,
#   extensions = {
#     account: &quot;/accounts/1&quot;,
#     balance: 50
#   },
#   instance = nil,
#   status = 403,
#   title = &quot;Forbidden&quot;,
#   type = &quot;about:blank&quot;
# &amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Given the above, you can also check if an extension exists:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extension?&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:account&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extension?&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_json&quot;&gt;JSON&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Both serialization and deserialization of JSON is supported. For example, given the following payload:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/problem_details/out_of_credit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You do not have enough credit.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;detail: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Your current balance is 30, but that costs 50.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;instance: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/accounts/1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;extensions: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;balance: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;accounts: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w[/accounts/1 /accounts/10]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means you can serialize as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;{\&quot;type\&quot;:\&quot;https://demo.io/problem_details/out_of_credit\&quot;,\&quot;title\&quot;:\&quot;You do not have enough credit.\&quot;,\&quot;status\&quot;:403,\&quot;detail\&quot;:\&quot;Your current balance is 30, but that costs 50.\&quot;,\&quot;instance\&quot;:\&quot;/accounts/1\&quot;,\&quot;balance\&quot;:30,\&quot;accounts\&quot;:[\&quot;/accounts/1\&quot;,\&quot;/accounts/10\&quot;]}&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;indent: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;  &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;space: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;object_nl: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;array_nl: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;type&quot;: &quot;https://demo.io/problem_details/out_of_credit&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;title&quot;: &quot;You do not have enough credit.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;status&quot;: 403,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;detail&quot;: &quot;Your current balance is 30, but that costs 50.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;instance&quot;: &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;balance&quot;: 30,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &quot;accounts&quot;: [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &quot;/accounts/10&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 All of the &lt;a href=&quot;https://docs.ruby-lang.org/en/master/JSON.html#module-JSON-label-Output+Options&quot;&gt;JSON&lt;/a&gt; output options are available to you when casting to JSON.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also deserialize by taking the result of the above and turning the raw JSON back into a &lt;code&gt;RFC::API::Problem::Payload&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_json&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://demo.io/problem_details/out_of_credit&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;You do not have enough credit.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:403,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Your current balance is 30, but that costs 50.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/accounts/1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;balance&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:30,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;accounts&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/accounts/1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/accounts/10&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]}&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::API::Problem::Payload:0x00002d10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   detail = &quot;Your current balance is 30, but that costs 50.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   extensions = {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#      balance: 30,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     accounts: [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       &quot;/accounts/10&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   },&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   instance = &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   status = 403,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   title = &quot;You do not have enough credit.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   type = &quot;https://demo.io/problem_details/out_of_credit&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_xml&quot;&gt;XML&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;XML is supported too but isn&amp;#8217;t as robust as JSON support, at the moment. This is mostly due to the fact that extensions can be deeply nested so your mileage may vary. For example, given the following payload:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/problem_details/out_of_credit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You do not have enough credit.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;detail: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Your current balance is 30, but that costs 50.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;instance: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/accounts/1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;extensions: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;balance: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;accounts: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w[/accounts/1 /accounts/10]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means you can serialize as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_xml&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;&amp;lt;problem xmlns=&#39;urn:ietf:rfc:7807&#39;&amp;gt;&amp;lt;type&amp;gt;https://demo.io/problem_details/out_of_credit&amp;lt;/type&amp;gt;&amp;lt;title&amp;gt;You do not have enough credit.&amp;lt;/title&amp;gt;&amp;lt;status&amp;gt;403&amp;lt;/status&amp;gt;&amp;lt;detail&amp;gt;Your current balance is 30, but that costs 50.&amp;lt;/detail&amp;gt;&amp;lt;instance&amp;gt;/accounts/1&amp;lt;/instance&amp;gt;&amp;lt;balance&amp;gt;30&amp;lt;/balance&amp;gt;&amp;lt;accounts&amp;gt;&amp;lt;i&amp;gt;/accounts/1&amp;lt;/i&amp;gt;&amp;lt;i&amp;gt;/accounts/10&amp;lt;/i&amp;gt;&amp;lt;/accounts&amp;gt;&amp;lt;/problem&amp;gt;&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_xml&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;indent: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;problem xmlns=&#39;urn:ietf:rfc:7807&#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     https://demo.io/problem_details/out_of_credit&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     You do not have enough credit.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;status&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     403&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/status&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;detail&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     Your current balance is 30, but that costs 50.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/detail&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;instance&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     /accounts/1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/instance&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;balance&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     30&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/balance&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;accounts&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;lt;i&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       /accounts/1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;lt;/i&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;lt;i&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       /accounts/10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;lt;/i&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   &amp;lt;/accounts&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;/problem&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 All of the &lt;a href=&quot;https://ruby.github.io/rexml/REXML/Document.html#method-i-write&quot;&gt;REXML::Document.write&lt;/a&gt; output options are available to you when casting to XML.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also deserialize by taking the result of the above and turning the raw JSON back into a &lt;code&gt;RFC::API::Problem::Payload&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_xml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
  &amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;
  &amp;lt;problem xmlns=&#39;urn:ietf:rfc:7807&#39;&amp;gt;
    &amp;lt;type&amp;gt;https://demo.io/problem_details/out_of_credit&amp;lt;/type&amp;gt;
    &amp;lt;title&amp;gt;You do not have enough credit.&amp;lt;/title&amp;gt;
    &amp;lt;status&amp;gt;403&amp;lt;/status&amp;gt;
    &amp;lt;detail&amp;gt;Your current balance is 30, but that costs 50.&amp;lt;/detail&amp;gt;
    &amp;lt;instance&amp;gt;/accounts/1&amp;lt;/instance&amp;gt;
    &amp;lt;balance&amp;gt;30&amp;lt;/balance&amp;gt;
    &amp;lt;accounts&amp;gt;
      &amp;lt;i&amp;gt;/accounts/1&amp;lt;/i&amp;gt;
      &amp;lt;i&amp;gt;/accounts/10&amp;lt;/i&amp;gt;
    &amp;lt;/accounts&amp;gt;
  &amp;lt;/problem&amp;gt;
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;XML&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::API::Problem::Payload:0x00000940&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   detail = &quot;Your current balance is 30, but that costs 50.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   extensions = {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#      balance: &quot;30&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     accounts: [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       &quot;/accounts/10&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   },&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   instance = &quot;/accounts/1&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   status = 403,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   title = &quot;You do not have enough credit.&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   type = &quot;https://demo.io/problem_details/out_of_credit&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_examples&quot;&gt;Examples&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There is a lot of useful information you can provide in your problem details depending on the context you are working in. Some have been shown above but here&amp;#8217;s a few more that might be of interest.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_hateoas&quot;&gt;HATEOAS&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With &lt;a href=&quot;https://nordicapis.com/tools-to-make-hateoas-compliance-easier&quot;&gt;HATEOAS&lt;/a&gt;, you can provide additional information and links for which the client can understand what next actions are available. The below example shows how you can provide additional resources for clients to adjust accordingly:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/problem_details/rate_limit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Rate limit exceeded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;429&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;detail: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You have exceeded your rate limit of 150 requests per minute&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;instance: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/articles&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;extensions: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;retry_after: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;links: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;ref: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;self&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;href: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/articles&quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;rel: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;retry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;href: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/articles&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Retry after five minutes&quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;rel: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;href: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/statuses/rate_limit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Check current rate limit usage&quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_semantic_structure&quot;&gt;Semantic Structure&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In other situations, you might need a different structure in order to aid clients that might be AI driven which needs a semantically structured response in order to course correct. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Problem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/problem_details/invalid_field&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Invalid field value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;status: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;detail: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The category requested doesn&#39;t exist&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;instance: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/categories&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;extensions: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;parameters: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;category_id: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;suggestions: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;ruby&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;git&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;htmx&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the above, the client now knows what parameters where invalid along with relevant suggestions for proceeding. Even better, the suggestions implicitly show the types of IDs that are required.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/rfc-api-problem
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rfc-api-problem
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_resources&quot;&gt;Resources&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can find additional resources here:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.iana.org/assignments/http-problem-types/http-problem-types.xhtml&quot;&gt;IANA Hypertext Transfer Protocol (HTTP) Problem Types&lt;/a&gt;: A registered list of problem types you can use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/protocol-registries/http-problem-types&quot;&gt;HTTP Problem Type Registration Requests&lt;/a&gt;: Where you can register new problem types.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/rfc-api-problem/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/rfc-api-problem</id>
    <link href="https://alchemists.io/projects/rfc-api-problem"/>
    <published>2026-08-22T20:29:24+00:00</published>
    <rights>2026</rights>
    <title>RFC API Problem Project</title>
    <updated>2026-09-17T12:58:45+00:00</updated>
    <dc:date>2026-09-17T12:58:45+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/rfc-web-link&quot;&gt;
    &lt;img src=&quot;/images/projects/rfc-web-link/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/rfc-web-link&quot;&gt;RFC Web Link&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;RFC Web Link implements &lt;a href=&quot;https://www.rfc-editor.org/info/rfc8288&quot;&gt;RFC 8288&lt;/a&gt;: Web Linking. This allows you to process links via the HTTP &lt;code&gt;link&lt;/code&gt; header when processing HTTP responses. For example, the following demonstrates a HTTP link header which links to a previous and next article:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;link: &amp;lt;https://demo.io/articles?page=1&amp;gt;; rel=&quot;previous&quot;; title=&quot;Previous&quot;,
      &amp;lt;https://demo.io/articles?page=3&amp;gt;; rel=&quot;next&quot;; title=&quot;Next&quot;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above parses each line, delimited by a comma (&lt;code&gt;,&lt;/code&gt;), and then each pair (attribute) in the line as delimited by a semicolon (&lt;code&gt;;&lt;/code&gt;). This is not something you want to reinvent for each application you maintain so this gem handles the parsing (and creation) of HTTP &lt;code&gt;link&lt;/code&gt; headers so you can stay focused on your own business logic.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_root_uri&quot;&gt;Root URI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_delimiters&quot;&gt;Delimiters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_attributes&quot;&gt;Attributes&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_anchor&quot;&gt;anchor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_hreflang&quot;&gt;hreflang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_media&quot;&gt;media&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_rel&quot;&gt;rel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_title&quot;&gt;title&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_type&quot;&gt;type&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_extensions&quot;&gt;Extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_models&quot;&gt;Models&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_list&quot;&gt;List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_link&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_pair&quot;&gt;Pair&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_error_handling&quot;&gt;Error Handling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Implements &lt;a href=&quot;https://www.rfc-editor.org/info/rfc8288&quot;&gt;RFC 8288&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Parses web link headers into whole value objects for processing and/or inspection.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides explicit or implicit casting of whole value objects into a web links.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rfc-web-link &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rfc-web-link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add rfc-web-link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rfc/web/link&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The fastest way to get started is to create a new instance of the parser that you can reuse upon each HTTP request. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Then you can use the &lt;code&gt;parser&lt;/code&gt; instance to parse HTTP headers and build lists you can interact with:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; rel=index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above will yield the following set of links (in this case, only with a single link):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#&amp;lt;data RFC::Web::Link::Models::List:0x00000900&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;links&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data RFC::Web::Link::Models::Link:0x00000920&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;pairs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;                                                                                                                                                                                  &lt;span class=&quot;c1&quot;&gt;#&amp;lt;data RFC::Web::Link::Models::Pair:0x00000940&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;delimiter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;language&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;index&quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io/articles&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you can see, you get an immutable &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; (whole value) object for which you can directly access all attributes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_root_uri&quot;&gt;Root URI&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A root URI (&lt;code&gt;root_uri&lt;/code&gt;) must be supplied in order to resolve all relative URIs as absolute URIs. Generally, the &lt;code&gt;root_uri&lt;/code&gt; is your host (i.e. primary domain). There are a few ways you can supply the root URI:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Initialization&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following sets the root URI globally so you only have to define it once:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Call&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following sets the root URI per call.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; rel=index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;root_uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Call (override)&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following sets the root URI globally but also allows you to override the global value with a custom value per call.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; rel=index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;root_uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://alt.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_delimiters&quot;&gt;Delimiters&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each delimiter provides the following behavior:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Semicolon&lt;/strong&gt; (&lt;code&gt;;&lt;/code&gt;): Delimits each pair associated with a line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Comma&lt;/strong&gt; (&lt;code&gt;,&lt;/code&gt;): Delimits each line of a link.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;They must be quoted when not used as delimiters.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_attributes&quot;&gt;Attributes&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There are six &lt;a href=&quot;https://www.rfc-editor.org/info/rfc8288&quot;&gt;RFC 8288&lt;/a&gt; registered target attributes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;anchor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;hreflang&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;media&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;rel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;title&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;type&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each is described in detail below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_anchor&quot;&gt;anchor&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Optional but, when supplied, can be a single string, quoted with special characters, a relative URI, or an absolute URI. Here&amp;#8217;s a few examples:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fragment&lt;/strong&gt;: &lt;code&gt;#footer&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Quoted (special characters)&lt;/strong&gt;: &lt;code&gt;&quot;#overview,body,footer&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Relative URI&lt;/strong&gt;: &lt;code&gt;/policies&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Absolute URI&lt;/strong&gt;: &lt;code&gt;&lt;a href=&quot;https://demo.io/about&quot; class=&quot;bare&quot;&gt;https://demo.io/about&lt;/a&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Relative URIs will automatically be expanded into an absolute URIs when parsed. This means if the &lt;code&gt;root_uri&lt;/code&gt; is &lt;code&gt;&lt;a href=&quot;https://demo.io&quot; class=&quot;bare&quot;&gt;https://demo.io&lt;/a&gt;&lt;/code&gt; and the anchor&amp;#8217;s value is &lt;code&gt;/policies&lt;/code&gt; (relative), then the resulting URI will be: &lt;code&gt;&lt;a href=&quot;https://demo.io/polices&quot; class=&quot;bare&quot;&gt;https://demo.io/polices&lt;/a&gt;&lt;/code&gt;. Examples:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Fragment&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; anchor=#footer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x000016f0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00001710&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001730&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;anchor&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;#footer&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; anchor=#footer&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Quoted&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%(&amp;lt;/articles&amp;gt;; anchor=&quot;#overview,body,footer&quot;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00001660&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00001680&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000016a0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;anchor&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;\&quot;#overview,body,footer\&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; anchor=\&quot;#overview,body,footer\&quot;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Relative URI&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; anchor=/policies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x000017c0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000017e0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001800&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;anchor&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;https://demo.io/policies&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; anchor=https://demo.io/policies&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Absolute URI&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; anchor=https://demo.io/about&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00001890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000018b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000018d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;anchor&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;https://demo.io/about&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; anchor=https://demo.io/about&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_hreflang&quot;&gt;hreflang&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Optional but, when supplied, is a hint indicating the language of the associated link. This &lt;em&gt;does not&lt;/em&gt; override the value of the &lt;code&gt;content-language&lt;/code&gt; header. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Single&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; hreflang=en&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000008d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;hreflang&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;en&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; hreflang=en&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Multiple&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; hreflang=en; hreflang=de&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x000016c0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000016e0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001700&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;hreflang&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;en&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001740&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;hreflang&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;de&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; hreflang=en; hreflang=de&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_media&quot;&gt;media&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Optional but, when supplied, is a hint indicating the kind of media associated with the link. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; media=print&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x000017d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000017f0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001810&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;media&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;print&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; media=print&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_rel&quot;&gt;rel&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Required and must be first defined. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Single&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; rel=index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000008d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;rel&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;index&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; rel=index&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Shorthand&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Short hand, for multiple relations, is supported as well. To use, each relation &lt;em&gt;must&lt;/em&gt; be delimited by a space within a single &lt;em&gt;quoted&lt;/em&gt; string. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%(&amp;lt;/articles&amp;gt;; rel=&quot;one two three&quot;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000960&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00000980&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000009a0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;rel&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;one&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000009f0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000a10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;rel&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;two&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00000a60&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000a80&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;rel&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;three&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; rel=one, &amp;lt;https://demo.io/articles&amp;gt;; rel=two, &amp;lt;https://demo.io/articles&amp;gt;; rel=three&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Notice that the original relation short hand of &lt;code&gt;&quot;one two three&quot;&lt;/code&gt; produced three unique links for each relation which allows you to type less while still producing three distinct links.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_title&quot;&gt;title&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Optional but, when supplied, allows you to provide a human readable label for the associated link. This includes being able to encode and decode the value based on the delimiter used. For example, notice the difference in delimiters used below:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Plain&lt;/strong&gt; (&lt;code&gt;=&lt;/code&gt;): &lt;code&gt;title=Demo&lt;/code&gt; (example)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Encoded&lt;/strong&gt; (&lt;code&gt;*=&lt;/code&gt;): &lt;code&gt;title*=UTF-8&#39;en&#39;d%C3%A9j%C3%A0%20vu&lt;/code&gt; (example)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The title &lt;em&gt;must not&lt;/em&gt; appear more than once. If multiple occurrences are detected then only the first is honored. Also, if &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;*=&lt;/code&gt; is used then &lt;code&gt;*=&lt;/code&gt; takes precedence. Examples:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Without Encoding&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; title=Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000008d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;title&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; title=Demo&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;With Encoding&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; title*=UTF-8&#39;en&#39;d%C3%A9j%C3%A0%20vu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000008d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;*=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = &quot;UTF-8&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;title&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = &quot;en&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;déjà vu&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; title*=UTF-8&#39;en&#39;d%C3%A9j%C3%A0%20vu&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_type&quot;&gt;type&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Optional but, when supplied, is a hint indicating the MIME Type of the associated link. This &lt;em&gt;does not&lt;/em&gt; override the value of the &lt;code&gt;content-type&lt;/code&gt; header. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; type=text/html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000890&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000008d0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;type&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;text/html&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; type=text/html&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_extensions&quot;&gt;Extensions&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Extensions allow you to extend your implementation beyond the registered target attributes, described above, with your own custom attributes. For example, maybe you want to use the following attributes which are specific to your application: hint, errata, copyright. You can do this as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%(&amp;lt;/articles&amp;gt;; hint=&quot;A demo.&quot;; errata=&quot;For demonstration only.&quot;; copyright=2025)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000980&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000009a0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x000009c0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;hint&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;\&quot;A demo.\&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000a00&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;errata&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;\&quot;For demonstration only.\&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000a40&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;copyright&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;2025&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; hint=\&quot;A demo.\&quot;; errata=\&quot;For demonstration only.\&quot;; copyright=2025&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also encode your extensions by using the &lt;code&gt;*=&lt;/code&gt; delimiter. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; demo*=UTF-8&#39;en&#39;d%C3%A9j%C3%A0%20vu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000ad0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00000af0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000b10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = &quot;*=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = &quot;UTF-8&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;demo&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = &quot;en&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = &quot;déjà vu&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# &quot;&amp;lt;https://demo.io/articles&amp;gt;; demo*=UTF-8&#39;en&#39;d%C3%A9j%C3%A0%20vu&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_models&quot;&gt;Models&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ve already seen all of the models (whole value objects) used in the examples above but this section details what you can do with each model individually.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_list&quot;&gt;List&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This model has both &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; and &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Enumerable.html&quot;&gt;Enumerable&lt;/a&gt; behavior because it encapsulates the list of links parsed from an HTTP link header or created by you. A list can be created multiple ways:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;All At Once&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;links: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;pairs: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 Ensure you use a &lt;code&gt;Set&lt;/code&gt; when adding your links and pairs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Separately&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once you have a list, you can send the following messages including &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; and &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Enumerable.html&quot;&gt;Enumerable&lt;/a&gt; messages:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_str&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll notice you can explicitly and implicitly cast your list to a string. This makes the following quite handy:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# link: &amp;lt;https://demo.io&amp;gt;; title=Demo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_link&quot;&gt;Link&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This model encapsulates a single HTTP link header. A link can be created multiple ways:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;All At Once&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;pairs: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;💡 Ensure you use a &lt;code&gt;Set&lt;/code&gt; when adding your pairs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Separately&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once you have a link, you can then send the following messages (including &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; messages):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:relation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;index&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&quot;déjà vu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;delimiter: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;*=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;encoding: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;language: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;en&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_pair&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;key: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_pair&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;key: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/dem/i&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_pair&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;key: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;delimiter: &lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\*=/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pair?&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;key: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pair?&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;key: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_str&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll notice you can explicitly and implicitly cast your link to a string. This makes the following quite handy:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# link: &amp;lt;https://demo.io&amp;gt;; title=Demo&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_pair&quot;&gt;Pair&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This models encapsulates a single HTTP link header pair (i.e. key/value). A pair can be created as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Basic&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001e90&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   delimiter = &quot;=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   key = &quot;title&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   value = &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encoded?&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Encoded&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;key: :title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;delimiter: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;*=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;value: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;encoding: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;language: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;en&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::Pair:0x00001ec0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   delimiter = &quot;*=&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   encoding = &quot;UTF-8&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   key = &quot;title&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   language = &quot;en&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   value = &quot;Demo&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encoded?&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The key can be either a symbol or a string but is always stored as a string, internally. When using &lt;code&gt;=&lt;/code&gt; as your delimiter (default), &lt;code&gt;#encoded?&lt;/code&gt; will be &lt;code&gt;false&lt;/code&gt; but when using &lt;code&gt;*=&lt;/code&gt; as your delimiter, &lt;code&gt;#encoded?&lt;/code&gt; will be &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As with &lt;code&gt;List&lt;/code&gt; and &lt;code&gt;Link&lt;/code&gt;, you have full access to all &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; messages and can explicitly and implicitly cast to a string. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Pair: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Pair: title=Demo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_error_handling&quot;&gt;Error Handling&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As per &lt;a href=&quot;https://www.rfc-editor.org/info/rfc8288&quot;&gt;RFC 8288&lt;/a&gt;, this implementation is designed to safely ignore malformed web links. To illustrate, we&amp;#8217;ll start with an initialized parser:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RFC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following examples show the result of parsing different malformed URIs:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;With Nil Value&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000880&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = []&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;With Empty Value&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000880&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = []&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;With No Leading Less Than Sign For URI&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/articles; rel=index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000880&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = []&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Without Attributes&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x00000880&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x000008b0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;With Missing Attribute Value&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;link&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;/articles&amp;gt;; rel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# #&amp;lt;data RFC::Web::Link::Models::List:0x000008a0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   links = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     #&amp;lt;data RFC::Web::Link::Models::Link:0x00000910&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       pairs = [&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         #&amp;lt;data RFC::Web::Link::Models::Pair:0x00000930&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           delimiter = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           encoding = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           key = &quot;rel&quot;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           language = nil,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#           value = nil&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#         &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       ],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#       uri = &quot;https://demo.io/articles&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     &amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   ]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/rfc-web-link
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rfc-web-link
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/rfc-web-link/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/rfc-web-link</id>
    <link href="https://alchemists.io/projects/rfc-web-link"/>
    <published>2026-08-22T17:22:35+00:00</published>
    <rights>2026</rights>
    <title>RFC Web Link Project</title>
    <updated>2026-09-17T12:59:28+00:00</updated>
    <dc:date>2026-09-17T12:59:28+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/docker-debian-ruby&quot;&gt;
    &lt;img src=&quot;/images/projects/docker-debian-ruby/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/docker-debian-ruby&quot;&gt;Docker Debian Ruby&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Provides a &lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; focused &lt;a href=&quot;https://www.debian.org&quot;&gt;Debian&lt;/a&gt; Docker image with current tooling for development purposes. Great for local development and/or continuous integration builds using the most up-to-date tooling.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Installs &lt;a href=&quot;https://jemalloc.net&quot;&gt;jemalloc&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Installs &lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; with &lt;a href=&quot;https://speed.yjit.org&quot;&gt;YJIT&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Updates &lt;a href=&quot;https://rubygems.org&quot;&gt;RubyGems&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To set up the project, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/docker-debian-ruby.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;docker-debian-ruby
git checkout:0.3.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All versions of this image can be found on
&lt;a href=&quot;https://hub.docker.com/r/bkuhlmann/debian-ruby/tags&quot;&gt;Docker Hub&lt;/a&gt;. The image can be pulled as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;docker pull bkuhlmann/debian-ruby:latest  &lt;span class=&quot;c&quot;&gt;# &amp;lt;= Pull latest version.&lt;/span&gt;
docker pull bkuhlmann/debian-ruby:0.3.0   &lt;span class=&quot;c&quot;&gt;# &amp;lt;= Pull specific version.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also build on top of this image via your &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; bkuhlmann/debian-ruby:latest  # &amp;lt;= Latest version.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; bkuhlmann/debian-ruby:0.3.0   # &amp;lt;= Specific version.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/docker-debian-ruby.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;docker-debian-ruby&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To build, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/build&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To use the console, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To deploy the &lt;em&gt;latest&lt;/em&gt; version, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/deploy&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To automatically calculate the next logical version and deploy it, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/deploy p&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Versions are calculated and created via the &lt;a href=&quot;https://alchemists.io/projects/milestoner&quot;&gt;Milestoner&lt;/a&gt; gem. Best practice is to deploy both the latest version and next version. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/deploy
bin/deploy p&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above will ensure new images are created with the following tags:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;latest&lt;/code&gt;: This is the most recent stable version which may or may not be ahead of the last version released.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;major&amp;gt;.&amp;lt;minor&amp;gt;.&amp;lt;patch&amp;gt;&lt;/code&gt;: This the next logical version as calculated and created by &lt;a href=&quot;https://alchemists.io/projects/milestoner&quot;&gt;Milestoner&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console
ruby &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/docker-debian-ruby/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/rubysmith&quot;&gt;Rubysmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/docker-debian-ruby</id>
    <link href="https://alchemists.io/projects/docker-debian-ruby"/>
    <published>2026-06-14T23:06:10+00:00</published>
    <rights>2026</rights>
    <title>Docker Debian Ruby Project</title>
    <updated>2026-09-30T01:22:58+00:00</updated>
    <dc:date>2026-09-30T01:22:58+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/htmx-slide&quot;&gt;
    &lt;img src=&quot;/images/projects/htmx-slide/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/htmx-slide&quot;&gt;htmx Slide&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This library is a &lt;a href=&quot;https://htmx.org&quot;&gt;htmx&lt;/a&gt; &lt;a href=&quot;https://htmx.org/extensions&quot;&gt;extension&lt;/a&gt; for rendering slides.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_screencasts&quot;&gt;Screencasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_configuration&quot;&gt;Configuration&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_defaults&quot;&gt;Defaults&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_globals&quot;&gt;Globals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_elements&quot;&gt;Elements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_precedence&quot;&gt;Precedence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_keyframes&quot;&gt;Keyframes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_view_transitions&quot;&gt;View Transitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_partials&quot;&gt;Partials&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_slide&quot;&gt;Slide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_progress&quot;&gt;Progress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_actions&quot;&gt;Actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_examples&quot;&gt;Examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_deployment&quot;&gt;Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Renders slides with silky smooth &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/View_transitions&quot;&gt;CSS View Transitions&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides customizable slide transitions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides full screen toggling of your presentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides keyboard shortcuts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Works with seamlessly with dynamically or statically generated web sites.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_screencasts&quot;&gt;Screencasts&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;videoblock focal_point&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;video src=&quot;https://alchemists.io/videos/projects/htmx-slide/demo.mp4&quot; width=&quot;1120&quot; height=&quot;920&quot; poster=&quot;https://alchemists.io/images/projects/htmx-slide/demo.webp&quot; controls&gt;
Your browser does not support the video tag.
&lt;/video&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://htmx.org&quot;&gt;htmx&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org&quot;&gt;Node&lt;/a&gt; (optional, for development).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; (optional, for development).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://eradman.com/entrproject&quot;&gt;entr&lt;/a&gt; (optional, for development).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following &lt;em&gt;assumes&lt;/em&gt; you are already using &lt;a href=&quot;https://htmx.org&quot;&gt;htmx&lt;/a&gt; and have it configured in the same manner as documented in this setup section.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To load CSS and JavaScript, add the following to your page:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://unpkg.com/htmx-slide@latest/build/style.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://unpkg.com/htmx-slide@latest&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;integrity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha384-wqhWD7RgQ3amBmpZ0soDOU6KHATp+GRksh5Y47N/vP3YYyNgaQoipBLP/Qn511zP&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;crossorigin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anonymous&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To use via Import Maps, add the following to your layout:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://unpkg.com/htmx-slide@latest/build/style.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;importmap&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;imports&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;htmx-slide&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://unpkg.com/htmx-slide@latest&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;htmx-slide&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install via &lt;a href=&quot;https://www.npmjs.com&quot;&gt;NPM&lt;/a&gt;, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;htmx-slide&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the library is installed, you only need to import it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;htmx-slide/build/style.css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;htmx-slide&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To use, add a top-level element (&lt;code&gt;section&lt;/code&gt; in this case) where you enable the &lt;code&gt;slide&lt;/code&gt; extension. Once the extension has been enabled, you can then add your view port, progress bar, and actions.  Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;htmx-slide&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;one.svg&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;One&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;slide&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;960&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;540&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;data-transitions-forward=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;push&quot;&lt;/span&gt;
           &lt;span class=&quot;na&quot;&gt;data-transitions-backward=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wipe&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;progress&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;progress&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;max=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;actions&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;backward&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[key == &#39;ArrowLeft&#39;] from:body&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        Previous
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;1 of 5&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

      &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_two.html&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;forward&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_two.html&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[key == &#39;ArrowRight&#39;] from:body&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        Next
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

      &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-fullscreen-trigger&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;[ ]&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above is the minimum to load the extension, the initial slide, and navigate between slides. Here&amp;#8217;s the breakdown:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;section&lt;/code&gt; (required): The &lt;code&gt;section&lt;/code&gt; element provides a semantic element to encapsulate all functionality and supply the minimum attributes. You&amp;#8217;re not limited to the &lt;code&gt;section&lt;/code&gt; element as any valid HTML element would work for your top level element.&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;class&lt;/code&gt; (optional): Provides a default style for the extension. If you don&amp;#8217;t want any styling then you can remove along with the associated &lt;code&gt;style.css&lt;/code&gt;. The &lt;code&gt;style.css&lt;/code&gt; is compiled from the style sheets located in the &lt;code&gt;lib/stylesheets&lt;/code&gt; of this project. If you need a detailed breakdown on how CSS View Transitions and key frames work, check out the &lt;a href=&quot;https://alchemists.io/articles/htmx_view_transitions&quot;&gt;htmx View Transitions&lt;/a&gt; article to learn more.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.container&lt;/code&gt; (required): Ensures the view port, progress bar, and associated actions don&amp;#8217;t expand the width of your slides.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.viewport&lt;/code&gt; (required): Ensures contents of this element can be toggled via the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API&quot;&gt;Fullscreen API&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.slide&lt;/code&gt; (required): Ensures your slide can be updated with a new slide based on the direction you are going.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.progress&lt;/code&gt; (optional): Provides real-time progress. Delete if not desired.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.actions&lt;/code&gt; (required): Ensures you can navigate to the previous, next, first, and last slide. You can add or remove actions as desired. The above shows what&amp;#8217;s possible. When using action links, use the following attributes:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.action&lt;/code&gt; (optional): Allows you to style the action if desired.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;data-direction&lt;/code&gt; (required): Ensures this extension knows which direction to transition the slide. Valid values are: &lt;code&gt;forward&lt;/code&gt; or &lt;code&gt;backward&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;hx-get&lt;/code&gt; (required): Requests the next slide.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;hx-trigger&lt;/code&gt;(required): Triggers the action. Feel free to customize keyboard short behavior as desired.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;hx-push_url&lt;/code&gt; (optional): Ensures your browser history is updated so back and forward navigation works.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;data-fullscreen-trigger&lt;/code&gt; (optional): Triggers full screen mode. The value is meant to be empty and any value supplied is ignored. You can, optionally, add a &lt;code&gt;data-fullscreen-target&lt;/code&gt; with any valid CSS selector in case you want to target a different element for full screen. The default is: &lt;code&gt;.viewport&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When building your implementation, the above shows the initial page to render. All subsequent pages only need to be HTML partials which have the elements shown in the &lt;code&gt;.container&lt;/code&gt; as those are the only elements that need to change upon each HTTP GET request.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In addition to the above, you can configure the extension globally or per element. The following details each.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_defaults&quot;&gt;Defaults&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This extensions is configured with the following defaults:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;DEFAULTS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;slide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.slide&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;transitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;backward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;fullscreen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[data-fullscreen-trigger]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.viewport&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each is key is described as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;slide&lt;/code&gt;: Defines the slide selector. This can be any valid CSS selector.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;transitions&lt;/code&gt;: Defines the transitions.&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;forward&lt;/code&gt;: Defines the forward transition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;backward&lt;/code&gt;: Defines the backward transition.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fullscreen&lt;/code&gt;: Defines fullscreen behavior.&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;key&lt;/code&gt;: Defines the keyboard shortcut to toggle full screen mode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;trigger&lt;/code&gt;: Defines the trigger selector of the element that will toggle full screen mode. This can be any valid CSS selector.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;target&lt;/code&gt;: Defines the full screen target selector for which will enlarged in full screen mode.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_globals&quot;&gt;Globals&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can override the defaults using &lt;a href=&quot;https://four.htmx.org/docs/hcon-guide&quot;&gt;HCON&lt;/a&gt; notation as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;htmx-config&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;slide.slide:.slide
               slide.fullscreen.forward:push
               slide.fullscreen.backward:push
               slide.fullscreen.key:k
               slide.fullscreen.trigger:[data-fullscreen-trigger]
               slide.fullscreen.target:.viewport&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the above, you&amp;#8217;ll notice the global configuration is identical to the &lt;code&gt;DEFAULTS&lt;/code&gt;. This is where you would customize as desired. At the moment, all keys must be represented even if you only customize a few of them.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_elements&quot;&gt;Elements&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also customize behavior by specific element using &lt;code&gt;data&lt;/code&gt; attributes. For example, to change transitions, apply the following attributes to your slide (img) element:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;data-transitions-forward=&quot;push&quot;
data-transitions-backward=&quot;push&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above gives you fine level control over the behavior of &lt;em&gt;each&lt;/em&gt; slide instead of inheriting the default or global configuration and is a powerful way to keep your presentation interesting with different transitions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also change full screen behavior by editing the element (button) that toggles full screen mode as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;data-fullscreen-target=&quot;.viewport&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_precedence&quot;&gt;Precedence&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The configuration is dynamically computed based on global and per element customization with the first in the following list having the most specificity followed by least specificity:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Elements&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Globals&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Defaults&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_keyframes&quot;&gt;Keyframes&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@keyframes&quot;&gt;Keyframes&lt;/a&gt; provide the low level animation sequences for use in your view transitions (see below). The source for these can be found in the &lt;code&gt;lib/stylesheets/keyframes.css&lt;/code&gt; file which is included when you import the &lt;code&gt;htmx-slide/build/style.css&lt;/code&gt; as described &lt;em&gt;Setup&lt;/em&gt; section above.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each keyframe uses the &lt;code&gt;htmx-slide-*&lt;/code&gt; prefix but feel free to add your own and link them to your own view transitions.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_view_transitions&quot;&gt;View Transitions&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;View transitions (i.e. &lt;code&gt;::view-transition-old&lt;/code&gt;, &lt;code&gt;::view-transition-new&lt;/code&gt;) are built atop the keyframes and are what make the slide transitions possible. The source for these can be found in the &lt;code&gt;lib/stylesheets/view_transitions.css&lt;/code&gt; file which is included when you import the &lt;code&gt;htmx-slide/build/style.css&lt;/code&gt; as described &lt;em&gt;Setup&lt;/em&gt; section above.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Several view transitions are provided for you:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Curtain&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Iris&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Push (default)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scale&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wipe&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can customize each slide&amp;#8217;s transition, as mentioned in the &lt;em&gt;Configuration&lt;/em&gt; section, by using the following data attributes on the extension element or the slide element. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;data-transitions-forward=&quot;iris&quot;&lt;/code&gt;: Uses the &lt;em&gt;iris&lt;/em&gt; transition when moving forward to the next slide.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;data-transitions-backward=&quot;scale&quot;&lt;/code&gt;: Uses the &lt;em&gt;scale&lt;/em&gt; transition when moving backward to the next slide.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each view transition name uses the &lt;code&gt;htmx-slide-&amp;lt;name&amp;gt;-forward&lt;/code&gt; prefix. You can create and use your own transitions by using the same format as long as your name is unique and doesn&amp;#8217;t conflict with the provided transitions. Once your custom view transition is ready, use the name of your transition via the &lt;code&gt;data-transitions-*&lt;/code&gt; attributes to enable.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_partials&quot;&gt;Partials&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All of your partials needs to be wrapped within the &lt;a href=&quot;https://four.htmx.org/reference/tags/hx-partial&quot;&gt;hx-partial&lt;/a&gt; tag. You can always add more partials and standard HTML elements as you like but the following detail what is possible:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_slide&quot;&gt;Slide&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is your most critical partial which informs htmx how to swap in and transition your new slide. Use of &lt;code&gt;transition:true&lt;/code&gt; is important for enabling &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/View_transitions&quot;&gt;CSS View Transitions&lt;/a&gt;. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;hx-partial&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.slide&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-swap=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;outerHTML transition:true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;one.svg&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;One&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;slide&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;960&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;540&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-transitions-forward=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;push&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-transitions-backward=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wipe&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/hx-partial&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_progress&quot;&gt;Progress&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As mentioned earlier this is optional but handy for providing a clear visual indication of where you are in your presentation. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;hx-partial&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.progress&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-swap=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;outerHTML&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;progress&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;progress&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;max=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/hx-partial&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_actions&quot;&gt;Actions&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You are not limited to previous and next actions as mentioned earlier because you can add as many as you deem necessary. For example, the following shows how to use previous, next, first, and last actions for navigation.&lt;/p&gt;
&lt;/div&gt;
&lt;details&gt;
&lt;summary class=&quot;title&quot;&gt;With First and Last Actions&lt;/summary&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;hx-partial&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.actions&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hx-swap=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;outerHTML&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;actions&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;backward&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[key == &#39;ArrowLeft&#39;] from:body&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      Previous
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;1 of 5&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_two.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;forward&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_two.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[key == &#39;ArrowRight&#39;] from:body&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      Next
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_one.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;backward&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_one.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[event.code == &#39;BracketLeft&#39;] from:body&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      First
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-fullscreen-trigger&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;[ ]&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;action&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;data-direction=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;forward&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-get=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_five.html&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-trigger=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;click, keyup[event.code == &#39;BracketRight&#39;] from:body&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;hx-push_url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      Last
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/hx-partial&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As long as your actions are defined within the &lt;code&gt;.actions&lt;/code&gt; element and wrapped within a &lt;code&gt;hx-partial&lt;/code&gt; element, this extension will swap them in properly.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_examples&quot;&gt;Examples&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Should you need real-word examples of this extension in production use, check out the following:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://alchemists.io/talks&quot;&gt;Talks&lt;/a&gt;: A collection of talks given at past presentations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://alchemists.io/projects/terminus&quot;&gt;Terminus&lt;/a&gt;: A web server for ePaper devices. Each playlist uses this extension for viewing screens rendered on your ePaper devices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/htmx-slide
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;htmx-slide
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To build, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/build&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To view the interactive demonstration, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/demo
open http://localhost:3030&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Any changes to source code will automatically rebuild and reload the demonstration.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_deployment&quot;&gt;Deployment&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To deploy, follow these steps:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Ensure you are on the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensure you&amp;#8217;ve updated the &lt;code&gt;CITATION.cff&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt; with new version and committed the changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the following:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/build
bin/publish&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/htmx-slide/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/rubysmith&quot;&gt;Rubysmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/htmx-slide</id>
    <link href="https://alchemists.io/projects/htmx-slide"/>
    <published>2026-05-24T17:41:14+00:00</published>
    <rights>2026</rights>
    <title>htmx Slide Project</title>
    <updated>2026-10-14T17:05:34+00:00</updated>
    <dc:date>2026-10-14T17:05:34+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/pi&quot;&gt;
    &lt;img src=&quot;/images/projects/pi/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/pi&quot;&gt;Pi&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This project automates the setup of Raspberry Pi devices by flashing your microSSD card with a fully customized &lt;a href=&quot;https://www.raspberrypi.com/software/operating-systems&quot;&gt;Raspberry Pi OS&lt;/a&gt; for immediate use. This allows you to spend more time putting your Raspberry Pis to good use.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_configuration&quot;&gt;Configuration&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_raspberry_pi_imager&quot;&gt;Raspberry Pi Imager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_ssh&quot;&gt;SSH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_scripts&quot;&gt;Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_example&quot;&gt;Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Allows you to setup and configure multiple &lt;a href=&quot;https://www.raspberrypi.org&quot;&gt;Raspberry Pi&lt;/a&gt; devices.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows you to manage multiple device profiles.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows you to install and run multiple services on your devices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.raspberrypi.org&quot;&gt;Raspberry Pi&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ensure you have the &lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt; installed for your operating system because this project depends on the Raspberry Pi Imager to format the micro SSD for your Raspberry Pi. If on macOS, use &lt;a href=&quot;https://brew.sh&quot;&gt;Homebrew&lt;/a&gt; as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; raspberry-pi-imager&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Next, clone this project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/pi.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;pi
git checkout 0.3.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By default, this project assumes you want to use the &lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt;. You can override the defaults by setting the following environment variables (see &lt;code&gt;settings/main.sh&lt;/code&gt; for details):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;EDITOR&lt;/code&gt;: This has no default but assumes you have this configured to run your favorite text editor. For example, if using Sublime Text, the value would be: &lt;code&gt;sublime&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;PI_CLI&lt;/code&gt;: The path to where the &lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt; is installed. By default, this assumes a macOS installation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;PI_URI&lt;/code&gt;: The &lt;a href=&quot;https://www.raspberrypi.com/software/operating-systems&quot;&gt;Raspberry Pi OS&lt;/a&gt; to be installed. By default, this assumes 64-bit, Lite OS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;PI_INTEGRITY&lt;/code&gt;: The integrity SHA used to verify the OS you are installing is valid. You can find the corresponding SHA for each OS on the &lt;a href=&quot;https://www.raspberrypi.com/software/operating-systems&quot;&gt;Raspberry Pi OS&lt;/a&gt; page. You&amp;#8217;ll want to update this each time you change the &lt;code&gt;PI_URI&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This project comes preconfigured with several scripts to help you get up and running quickly. You can find them in the &lt;code&gt;scripts&lt;/code&gt; folder:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;services&lt;/code&gt;: A directory of executable scripts for managing multiple services. This is meant to be customized with your own logic for installing, configuring, and running your services. The &lt;code&gt;docker&lt;/code&gt; service is provided for you, by default, so you can use &lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt; to run multiple projects at once.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;setup&lt;/code&gt;: The primary script that first updates your system and then runs all services.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;update&lt;/code&gt;: Ensures your Raspberry Pi OS is upgraded and up-to-date with latest software. You can also use this script to keep your OS updated on a scheduled basis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;d like to customize any of the above scripts, you can do so by making a copy of them using identical script name in your &lt;a href=&quot;https://alchemists.io/projects/xdg&quot;&gt;XDG&lt;/a&gt; configuration folder. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$XDG_CONFIG_HOME/pi/scripts/services
$XDG_CONFIG_HOME/pi/scripts/setup
$XDG_CONFIG_HOME/pi/scripts/update&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is also a good way to zero them out entirely if you want them to do nothing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_raspberry_pi_imager&quot;&gt;Raspberry Pi Imager&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When first getting set up, you&amp;#8217;ll want to use the &lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt; to walk through setting up your device for the first time. Afterwards, you can copy and customize the files created by the Raspberry Pi Imager. This is only necessary if you&amp;#8217;ve never used this project before and don&amp;#8217;t feel comfortable writing all of the configuration files by default.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Insert the micro SSD into your machine you want to format.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch &lt;a href=&quot;https://www.raspberrypi.com/software&quot;&gt;Raspberry Pi Imager&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select your Raspberry Pi hardware.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on Raspberry Pi OS (other) software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select Raspberry Pi OS Lite (64-bit).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select your micro SSD card (example: &quot;Generic- SD/MMC Media&quot;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter your desired hostname.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in your capital city, time zone, and keyboard layout.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in your username and password for your desired Raspberry user account.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in your SSID and password for your local network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable SSH by supplying the path to your public key (i.e. &lt;code&gt;$HOME/.ssh/*.pub&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose whether to enable/disable Raspberry Pi Connect.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write image to disk.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When the above is complete, you&amp;#8217;ll be able to inspect the files created for you by running the following:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /Volumes/bootfs
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;network-config
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;user-data&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll want to make a copy of each of the above files so you can customize them for different networks and hosts as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /Volumes/bootfs/network-config &lt;span class=&quot;nv&quot;&gt;$XDG_CONFIG_HOME&lt;/span&gt;/pi/networks/demo.yml
&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /Volumes/bootfs/user-data &lt;span class=&quot;nv&quot;&gt;$XDG_CONFIG_HOME&lt;/span&gt;/pi/hosts/demo.yml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This allows you to have multiple &lt;em&gt;profiles&lt;/em&gt;, so-to-speak, for different networks and hosts. Due to these being YAML configurations, you can quickly adjust your host name, SSH public key, time zone, WiFi SSID, etc. You can learn more about the structure and configuration of each of these files via the &lt;a href=&quot;https://www.raspberrypi.com/documentation/computers&quot;&gt;Raspberry Pi Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To run, use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/run&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll then be greeted with the following options:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Usage: run OPTION

Script Options:
  s: Setup
  e: Edit configuration
  o: Open configuration
  E: Eject Card
  q: Quit/Exit

Enter selection:&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above breaks down as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;: Formats, configures, and sets up your micro SSD card so you can boot your Raspberry Pi with desired operating system and custom configuration. A wizard will prompt you for further information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Edit configuration&lt;/strong&gt;: Allows you to select and edit an individual &lt;a href=&quot;https://alchemists.io/projects/xdg&quot;&gt;XDG&lt;/a&gt; configuration in your default editor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open configuration&lt;/strong&gt;: Allows you to open and view your entire &lt;a href=&quot;https://alchemists.io/projects/xdg&quot;&gt;XDG&lt;/a&gt; configuration in your default editor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Eject Card&lt;/strong&gt;: Allows you to eject (unmount) the micro SSD card created during setup.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Quit/Exit&lt;/strong&gt;: Allows you to quit the CLI.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you know which option you want to run, like setup, you can skip the interactive options shown above. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/run s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_ssh&quot;&gt;SSH&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once you&amp;#8217;ve configured your Raspberry Pi settings, you can insert your micro SSD card into your Raspberry Pi, and connect power. Then you can look for your device to show up on your local network with whatever host name you gave it. To make SSH&amp;#8217;ing into your device more convenient, edit your SSH configuration (i.e. &lt;code&gt;$HOME/.ssh/config&lt;/code&gt;) to add your new host. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Host demo.local
  HostName 192.168.0.123
  User admin
  IdentityFile ~/.ssh/demo&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With SSH configured, you can SSH into your Raspberry Pi. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;ssh admin@demo.local&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_scripts&quot;&gt;Scripts&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;After SSH&amp;#8217;ing into your Raspberry Pi, run the &lt;code&gt;setup&lt;/code&gt; script from your home directory to complete the setup of your device. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/boot/firmware/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This&amp;#8217;ll run all of the scripts/services (default or custom) based on the configuration you used when setting up your micro SSD card.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_example&quot;&gt;Example&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following is an example of what the output can look like when running setup (i.e. &lt;code&gt;bin/run s&lt;/code&gt;) where I walk through all options to configure my Raspberry Pi 5 (a.k.a. &lt;code&gt;five&lt;/code&gt;) using my &lt;code&gt;demo&lt;/code&gt; network complete with default services and my custom &lt;a href=&quot;https://github.com/usetrmnl/byos_hanami&quot;&gt;Terminus&lt;/a&gt; service:&lt;/p&gt;
&lt;/div&gt;
&lt;details&gt;
&lt;summary class=&quot;title&quot;&gt;Setup Output Example&lt;/summary&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Have you inserted your micro SSD card for formatting (y/n)? y

Please select your host configuration:

1) /Users/demo/.config/pi/hosts/five.yml
2) /Users/demo/.config/pi/hosts/zero.yml
#? 1

Please select your network configuration:

1) /Users/demo/.config/pi/networks/demo.yml
#? 1

Using host configuration: /Users/demo/.config/pi/hosts/five.yml.
Using network configuration: /Users/demo/.config/pi/networks/demo.yml.
Using setup script: /Users/demo/Engineering/OSS/pi/scripts/setup.
Using update script: /Users/demo/Engineering/OSS/pi/scripts/update.

The following external disks are detected for your micro SSD:

/dev/disk4 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                        +5.4 GB     disk4
   1:        Apple_partition_map                         32.3 KB    disk4s1
   2:                  Apple_HFS projects                5.4 GB     disk4s2

/dev/disk5 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.7 GB    disk5
   1:             Windows_FAT_32 bootfs                  536.9 MB   disk5s1
   2:                      Linux                         31.2 GB    disk5s2

Please enter your disk number (i.e. 1, 2, 3) for /dev/disk to format: 5
CacheManager initialized with background thread
Detected total system memory: 24576 MB on &quot;macOS&quot;
Optimal async queue depth: 256 (available: 9093 MB, budget: 1363 MB, block size: 1024 KB, baseline: 256 )
FileOperations log callback installed
Starting background cache operations
Found cached file info, starting background verification: &quot;/Users/demo/Library/Caches/Raspberry Pi/Raspberry Pi Imager/lastdownload.cache&quot;
Starting background drive list polling
Opening macOS device: /dev/rdisk5
Device path detected, using macOS authorization...
Successfully opened device with authorization, fd=13 (direct I/O enabled)
Block device size: 31719424000 bytes (blocks=61952000, block_size=512)
PrepareForSequentialRead: fd=13 path=/dev/rdisk5
  F_RDAHEAD result: 0 (OK)
  F_NOCACHE result: 0 (OK)
Write successful.

Copied: /Users/demo/Engineering/OSS/pi/scripts/setup to /Volumes/bootfs/setup.
Copied: /Users/demo/Engineering/OSS/pi/scripts/update to /Volumes/bootfs/update.
Copied: /Users/demo/Engineering/OSS/pi/scripts/services/docker to /Volumes/bootfs/services/docker.
Copied: /Users/demo/.config/pi/scripts/services/terminus to /Volumes/bootfs/services/terminus.

Raspberry Pi SSD card is ready!
Please eject card before using.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/pi.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;pi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/pi/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Build with &lt;a href=&quot;https://alchemists.io/projects/bashsmith&quot;&gt;Bashsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/pi</id>
    <link href="https://alchemists.io/projects/pi"/>
    <published>2026-02-01T21:37:39+00:00</published>
    <rights>2026</rights>
    <title>Pi Project</title>
    <updated>2026-09-15T14:45:15+00:00</updated>
    <dc:date>2026-09-15T14:45:15+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/functionable&quot;&gt;
    &lt;img src=&quot;/images/projects/functionable/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/functionable&quot;&gt;Functionable&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enhances modules to be functional by disabling the ability to extend, include, or prepend while also ensuring all methods are class methods. This allows you to use a module as a functional collection of related methods for reuse throughout your application via &lt;em&gt;composition&lt;/em&gt; instead of &lt;em&gt;inheritance&lt;/em&gt;. In other words, this is an enhanced version of &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Module.html#method-i-module_function&quot;&gt;module_function&lt;/a&gt; by preventing inheritance and reducing the memory overhead due to making copies of the original methods.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_function_methods&quot;&gt;Function Methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conceal&quot;&gt;Conceal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_avoidances&quot;&gt;Avoidances&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_extend&quot;&gt;Extend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_include&quot;&gt;Include&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_prepend&quot;&gt;Prepend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_module_function&quot;&gt;Module Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_public&quot;&gt;Public&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_protected&quot;&gt;Protected&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_private&quot;&gt;Private&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_aliasing&quot;&gt;Aliasing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_class_variables&quot;&gt;Class Variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_class_methods&quot;&gt;Class Methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_constants&quot;&gt;Constants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_define_method&quot;&gt;Define Method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_remove_method&quot;&gt;Remove Method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_undef_method&quot;&gt;Undef Method&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_benchmarks&quot;&gt;Benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Allows modules to be a collection of functional methods.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows your modules and/or methods to be composable instead of inherited.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides faster performance and a reduced memory than any object within your application. See the &lt;a href=&quot;#_benchmarks&quot;&gt;Benchmarks&lt;/a&gt; section for details.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A solid understanding &lt;a href=&quot;https://alchemists.io/articles/ruby_modules&quot;&gt;Ruby Modules&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;functionable &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;functionable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add functionable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;functionable&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enhancing your module to be functional is as simple as extending your module:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Math&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;subtract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;multiply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;divide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# 9&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;subtract&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 3&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;multiply&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 18&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;divide&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it! Now you can add related methods, as desired, which are specific to your namespace.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_function_methods&quot;&gt;Function Methods&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can acquire the array of function method names that were implemented and created by you. By default, you&amp;#8217;ll get an empty array when no methods are defined:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;function_methods&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# []&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once methods are defined, you&amp;#8217;ll then get an array of names:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;one&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;two&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;function_methods&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# [:one, :two]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This behavior is similar to what a &lt;code&gt;Module&lt;/code&gt; already provides you when it comes to categorizing method names:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Module#instance_methods&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Module#private_instance_methods&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Module#protected_instance_methods&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Module#public_instance_methods&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Module#undefined_instance_methods&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_conceal&quot;&gt;Conceal&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Should you need to make any of your methods private, use the &lt;code&gt;conceal&lt;/code&gt; method as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;welcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The default message.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;conceal&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:print&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;welcome&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &quot;The default message.&quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# private method &#39;print&#39; called for module Demo (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;code&gt;conceal&lt;/code&gt; method takes the same parameters as the &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Module.html#method-i-private_class_method&quot;&gt;private_class_method&lt;/a&gt; which means you can use a string, symbol, a single argument, multiple arguments, or an array.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_avoidances&quot;&gt;Avoidances&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Functional modules are only meant to be a collection of related methods which allows you to namespace your behavior, compose multiple methods together, and use composition to inject your module as a dependency within objects that need this functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means the following behavior is disabled (each uses an anonymous module and/or class for demonstration purposes and reduced syntax).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_extend&quot;&gt;Extend&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Use composition instead of inheritance:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Module extend is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_include&quot;&gt;Include&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Use composition instead of inheritance:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Module include is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You also can&amp;#8217;t include &lt;code&gt;Funtionable&lt;/code&gt;, only extend:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Module include is disabled, use extend instead. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_prepend&quot;&gt;Prepend&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Use composition instead of inheritance:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;prepend&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functions&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Module prepend is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You also can&amp;#8217;t prepend, only extend:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;prepend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Module prepend is disabled, use extend instead. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_module_function&quot;&gt;Module Function&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following is not allowed because you have this behavior when extending &lt;code&gt;Functionable&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;module_function&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Module function behavior is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_public&quot;&gt;Public&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid the following since all methods are public by default:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;public&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Public visibility is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_protected&quot;&gt;Protected&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid the following since a functionable module isn&amp;#8217;t mean to be inherited:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;protected&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Protected visibility is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_private&quot;&gt;Private&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid the following by using &lt;a href=&quot;#_conceal&quot;&gt;conceal&lt;/a&gt; instead:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Private visibility is disabled, use conceal instead. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_aliasing&quot;&gt;Aliasing&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid aliasing as you are not meant to inherit methods within a functional module:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;alias_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:alt&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Aliasing :alt as :demo is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_class_variables&quot;&gt;Class Variables&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid using class variables since they are a code smell and introduce unwanted state:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class_variable_get&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:@@bogus&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class_variable_set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:@@bogus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Getting class variable :@@bogus is disabled. (NoMethodError)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Setting class variable :@@bogus is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_class_methods&quot;&gt;Class Methods&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid class methods, use instance methods instead:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bogus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Avoid defining :bogus as a class method because the method will be automatically converted to a class method for you. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_constants&quot;&gt;Constants&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid dynamically setting constants since you can add constants directly to the top of the module:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bogus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;const_set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:BOGUS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bogus&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Setting constant :BOGUS is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_define_method&quot;&gt;Define Method&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid dynamically defining a method since you can explicitly define your method instead:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Defining method :bogus is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_remove_method&quot;&gt;Remove Method&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid dynamically removing a method since you can explicitly delete the method instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;remove_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Removing method :bogus is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_undef_method&quot;&gt;Undef Method&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avoid dynamically undefining a method since you can explicitly delete the method instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;undef_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bogus&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Undefining method :bogus is disabled. (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When you lean into the power of functional programming in Ruby, you gain performance and lower your memory footprint since you are creating the minimal amount of objects necessary. In terms of CPU performance, here&amp;#8217;s a benchmark script (see &lt;code&gt;bin/benchmark&lt;/code&gt; included in this project):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#! /usr/bin/env ruby&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bundler/inline&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;gemfile&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://rubygems.org&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark-ips&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;functionable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;path: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;..&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ModuleSelf&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ModuleFunction&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;module_function&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ModuleFunctionable&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Functionable&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClassFunction&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:message&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;proc_function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lambda_function&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;benchmark&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;memoized_instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;memoized_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memoized_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:call&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ips&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;time: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;warmup: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Proc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Lambda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lambda_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Module (function)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ModuleFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Module (functionable)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ModuleFunctionable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Module (self)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ModuleSelf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Class (new)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ClassFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Class (memoized)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memoized_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Method (new)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memoized_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Method (memoized)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memoized_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compare!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When you run the above benchmark, you should see the following results:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ruby 4.0.1 (2026-01-13 revision e04267a14b) +YJIT +PRISM [arm64-darwin25.2.0]
Warming up --------------------------------------
                Proc     2.275M i/100ms
              Lambda     2.212M i/100ms
   Module (function)     4.654M i/100ms
Module (functionable)
                         4.682M i/100ms
       Module (self)     4.567M i/100ms
         Class (new)     2.359M i/100ms
    Class (memoized)     4.536M i/100ms
        Method (new)     1.176M i/100ms
   Method (memoized)     2.173M i/100ms
Calculating -------------------------------------
                Proc     23.976M (± 0.1%) i/s   (41.71 ns/i) -    120.575M in   5.029071s
              Lambda     24.414M (± 0.2%) i/s   (40.96 ns/i) -    123.885M in   5.074316s
   Module (function)     61.028M (± 0.7%) i/s   (16.39 ns/i) -    307.154M in   5.033292s
Module (functionable)
                         60.864M (± 0.5%) i/s   (16.43 ns/i) -    304.327M in   5.000243s
       Module (self)     60.261M (± 0.6%) i/s   (16.59 ns/i) -    301.446M in   5.002511s
         Class (new)     28.202M (± 8.2%) i/s   (35.46 ns/i) -    141.526M in   5.048420s
    Class (memoized)     57.157M (± 1.0%) i/s   (17.50 ns/i) -    285.794M in   5.000639s
        Method (new)     13.265M (± 9.7%) i/s   (75.39 ns/i) -     65.847M in   5.012654s
   Method (memoized)     24.390M (± 0.2%) i/s   (41.00 ns/i) -    123.861M in   5.078408s

Comparison:
   Module (function): 61027866.3 i/s
Module (functionable): 60864191.4 i/s - same-ish: difference falls within error
       Module (self): 60261194.0 i/s - same-ish: difference falls within error
    Class (memoized): 57156588.3 i/s - 1.07x  slower
         Class (new): 28201872.3 i/s - 2.16x  slower
              Lambda: 24414262.5 i/s - 2.50x  slower
   Method (memoized): 24389728.5 i/s - 2.50x  slower
                Proc: 23975703.7 i/s - 2.55x  slower
        Method (new): 13264797.8 i/s - 4.60x  slower&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you can see, a functional module is one of the fastest while everything else is much slower.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/functionable
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;functionable
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/functionable/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/functionable</id>
    <link href="https://alchemists.io/projects/functionable"/>
    <published>2025-11-02T15:44:12+00:00</published>
    <rights>2026</rights>
    <title>Functionable Project</title>
    <updated>2026-09-17T13:02:05+00:00</updated>
    <dc:date>2026-09-17T13:02:05+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/inspectable&quot;&gt;
    &lt;img src=&quot;/images/projects/inspectable/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/inspectable&quot;&gt;Inspectable&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inspectable is a customizable object inspector which enhances &lt;a href=&quot;https://alchemists.io/articles/ruby_object_inspection&quot;&gt;Ruby Object Inspection&lt;/a&gt; behavior beyond what is provided by default. You can always implement your own &lt;code&gt;#inspect&lt;/code&gt; method but this becomes tedious when you need to exclude or transform the same instance variables across multiple objects.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_registry&quot;&gt;Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_transformers&quot;&gt;Transformers&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_redactor&quot;&gt;Redactor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_typer&quot;&gt;Typer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_overrides&quot;&gt;Overrides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_custom&quot;&gt;Custom&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_native&quot;&gt;Native&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_rspec&quot;&gt;RSpec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Allows you to customize and configure &lt;code&gt;Object#inspect&lt;/code&gt; with minimal effort.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows you to exclude instance variables that are too verbose or undesired.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows you to register reusable transformers for more advanced behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A good understanding of default &lt;a href=&quot;https://alchemists.io/articles/ruby_object_inspection&quot;&gt;Ruby Object Inspection&lt;/a&gt; behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;inspectable &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;inspectable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add inspectable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;inspectable&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By default, &lt;code&gt;Object#inspect&lt;/code&gt; includes all instance variables so this gem is designed to exclude what you don&amp;#8217;t need or transform variables before being inspected. Otherwise, you don&amp;#8217;t need this gem at all. Take the following, for example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;token: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;secret&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Demo:0x00000000000005d0 @uri=&quot;https://demo.io&quot;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Notice, when inspecting the instance of &lt;code&gt;Demo&lt;/code&gt;, the &lt;code&gt;token&lt;/code&gt; instance variable was excluded. This is important when you want to hide sensitive information, information that is too verbose, or you don&amp;#8217;t need at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the built-in transformers to transform sensitive information as well. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;token: :redact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;token: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;secret&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;uri: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://demo.io&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;#&amp;lt;Demo:0x0000000000000ea0 @token=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[REDACTED]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, @uri=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://demo.io&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above is nearly identical to the first example except we&amp;#8217;ve used the built-in &lt;code&gt;:redact&lt;/code&gt; transformer which replaced &lt;code&gt;&quot;secret&quot;&lt;/code&gt; with &lt;code&gt;&quot;[REDACTED]&quot;&lt;/code&gt;. This is why this transformer is provided for you because leaking sensitive information is a fairly common occurrence that this gem has made this simple for you to manage. To learn more, see the &lt;a href=&quot;#_transformers&quot;&gt;Transformers&lt;/a&gt; section below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_registry&quot;&gt;Registry&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;At the moment, this gem&amp;#8217;s registry only allows the registration of custom transformers. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_transformer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:upcase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;upcase&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_transformer&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cleaner&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\h{10}/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Notice you can register transformers using strings or symbols. The latter is preferred because all transformers are identified by symbol when referenced. The value must be a lambda where the value is the value of your instance variable which will be transformed at time of object inspection.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s an example using the above registered transformers:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Demo&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: :suffix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;label: :upcase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;demo-ab12ef&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;label: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;#&amp;lt;Demo:0x00000000000012f0 @name=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, @label=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;DEMO&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_transformers&quot;&gt;Transformers&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This gem includes a few built-in transformers that can help you hide sensitive information or reduce verbosity. To view them, use:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transformers&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#   redact: Inspectable::Transformers::Redactor,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     type: Inspectable::Transformers::Typer&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each is explained below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_redactor&quot;&gt;Redactor&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This transformer&amp;#8217;s sole purpose is to hide sensitive information and is most helpful for obscuring credentials, passwords, and secrets in general. When your instance variable&amp;#8217;s value is not &lt;code&gt;nil&lt;/code&gt;, you&amp;#8217;ll see &lt;code&gt;&quot;[REDACTED]&quot;&lt;/code&gt; as the value. Otherwise, if your instance variable&amp;#8217;s value is &lt;code&gt;nil&lt;/code&gt;, you&amp;#8217;ll see &lt;code&gt;nil&lt;/code&gt; instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To use, supply the instance variable you want to transform as the key and the transformer&amp;#8217;s key (symbol) as the value. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;demo: :redact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_typer&quot;&gt;Typer&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This transformer always computes the instance variable&amp;#8217;s type.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This transformer is most helpful for objects, like &lt;a href=&quot;https://dry-rb.org/gems/dry-schema&quot;&gt;Dry Schema&lt;/a&gt;, that are extremely verbose. With this transformer, you can see the type of schema without all of the additional details. This transformer is also handy when you only want type information in general.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To use, supply the instance variable you want to transform as the key and the transformer&amp;#8217;s key (symbol) as the value. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;demo: :type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_overrides&quot;&gt;Overrides&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Should you not like default transformer behavior, you can override an existing transformer with your own. For example, maybe you&amp;#8217;d like the &lt;code&gt;Redactor&lt;/code&gt; transformer to use &lt;code&gt;&quot;[FILTERED]&quot;&lt;/code&gt; instead of &lt;code&gt;&quot;[REDACTED]&quot;&lt;/code&gt;. Here&amp;#8217;s how you do that:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_transformer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:redact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[FILTERED]&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above will override default behavior with your own functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_custom&quot;&gt;Custom&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can add as many transformers as you like by using the &lt;code&gt;.add_transformer&lt;/code&gt; method. Here are the guidelines for customization:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use only a string or symbol for the first argument (a symbol is preferred). This allows you to quickly identify and use your transformer when applying custom inspection behavior to your objects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use a lambda for the second argument. The lambda must accept a value as the first positional parameter. How you transform the value is up to you but you&amp;#8217;ll want to adhere to default &lt;a href=&quot;https://alchemists.io/articles/ruby_object_inspection&quot;&gt;Ruby Object Inspection&lt;/a&gt; behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s say you need to remove hex values from showing up when inspecting a variable value, you could register a custom transformer for this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add_transformer&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dehexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\h+/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The above would strip hexes from the output. Notice the guard to check if the &lt;code&gt;value&lt;/code&gt; exists before performing the transformation. This is good to have when your value might be &lt;code&gt;nil&lt;/code&gt; so you don&amp;#8217;t have exceptions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ℹ️ In most cases, you &lt;em&gt;must&lt;/em&gt; send the &lt;code&gt;#inspect&lt;/code&gt; message to the transformed value. In situations, where you are dealing with a constant, you&amp;#8217;ll want to avoid sending the &lt;code&gt;#inspect&lt;/code&gt; message because constants shouldn&amp;#8217;t be quoted. All of this is important when adhering to default &lt;a href=&quot;https://alchemists.io/articles/ruby_object_inspection&quot;&gt;Ruby Object Inspection&lt;/a&gt; behavior.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_native&quot;&gt;Native&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As of Ruby 4.0.0, limited native support is provided via the &lt;em&gt;private&lt;/em&gt; &lt;code&gt;instance_variables_to_inspect&lt;/code&gt; instance method. This method is not compatible with this gem because this gem makes &lt;code&gt;instance_variables_to_inspect&lt;/code&gt; redundant and will fail with a &lt;code&gt;NoMethodError&lt;/code&gt; exception. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Inspectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instance_variables_to_inspect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:@name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# undefined method &#39;Inspectable&#39; for class (NoMethodError)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To resolve the above exception, remove &lt;code&gt;instance_variables_to_inspect&lt;/code&gt; and let this gem handle everything for you.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_rspec&quot;&gt;RSpec&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To aid in your testing, you can use the &lt;code&gt;match_inspection&lt;/code&gt; RSpec matcher by requiring it in your spec helper:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# spec_helper.rb&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;inspectable/rspec/matchers/match_inspection&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once required, you can use the matcher by supplying the expected attributes as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;described_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#inspect&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;has inspected attributes&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match_inspection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;label: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;name: :demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also customize the matcher by providing a &lt;code&gt;by&lt;/code&gt; hash &lt;em&gt;before&lt;/em&gt; any expected attributes consisting of the following attributes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;prefix&lt;/code&gt;: The prefix of your attribute names. Default: &lt;code&gt;&quot;@&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;delimiter&lt;/code&gt;: The delimiter between each attribute name and value. Default: &lt;code&gt;&quot;=&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;separator&lt;/code&gt;: The separator between each attribute. Default: &lt;code&gt;&quot;, &quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For example, the following is an explicit demonstration of what the matcher implicitly provides for you by default:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;RSpec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Demo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;described_class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#inspect&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;has inspected attributes&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match_inspection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;by: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;prefix: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;delimiter: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;separator: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;label: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Demo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;name: :demo&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In situations where the spec fails, you’ll get a formatted error to help you quickly resolve and fix the issue:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;expected (using prefix: &quot;@&quot;, delimiter: &quot;=&quot;, and separator: &quot;, &quot;):

&quot;#&amp;lt;Demo:0x00000000000014d0
@label=&quot;Demo&quot;,
@name=:demo
@email=&quot;demo@demo.io&quot;

to match:

@label=&quot;Demo&quot;,
@name=:demo&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/inspectable
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;inspectable
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/inspectable/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/inspectable</id>
    <link href="https://alchemists.io/projects/inspectable"/>
    <published>2025-05-10T22:07:05+00:00</published>
    <rights>2026</rights>
    <title>Inspectable Project</title>
    <updated>2026-09-16T23:36:28+00:00</updated>
    <dc:date>2026-09-16T23:36:28+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Brooke Kuhlmann</name>
      <uri>https://alchemists.io/team/brooke_kuhlmann</uri>
    </author>
    <category term="projects"
      label="Projects"/>
    <content type="html">&lt;div align=&quot;center&quot;&gt;
  &lt;a href=&quot;/projects/kagi-api&quot;&gt;
    &lt;img src=&quot;/images/projects/kagi-api/logo.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
  &lt;/a&gt;

  &lt;h1&gt;&lt;a href=&quot;/projects/kagi-api&quot;&gt;Kagi API&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A monadic API client for &lt;a href=&quot;https://kagi.com&quot;&gt;Kagi&lt;/a&gt; privacy focused information. This allows you to access the full Kagi API using a fault tolerant pipeline to yield whole value objects (i.e. &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt;) for immediate interaction within your own applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Roughly ~2% of funds go to Yandex search results. Unfortunately, Yandex is a Russian company that helps fund corrupt propaganda, the killing of Ukrainians, and other despicable acts. I was not aware of this when I wrote this API client. More can be found &lt;a href=&quot;https://kagifeedback.org/d/5445-reconsider-yandex-integration-due-to-the-geopolitical-status-quo&quot;&gt;here&lt;/a&gt; so you can make an informed decision.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_features&quot;&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_requirements&quot;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_usage&quot;&gt;Usage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_environment&quot;&gt;Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_endpoints&quot;&gt;Endpoints&lt;/a&gt;
&lt;ul class=&quot;sectlevel3&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_enrich_news&quot;&gt;Enrich News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_enrich_web&quot;&gt;Enrich Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_fast&quot;&gt;Fast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_search&quot;&gt;Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_summarize&quot;&gt;Summarize&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tests&quot;&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_license&quot;&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_versions&quot;&gt;Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_community&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_credits&quot;&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_features&quot;&gt;Features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Provides a &lt;a href=&quot;https://kagi.com&quot;&gt;Kagi&lt;/a&gt; API client.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides full access to the Kagi APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides a fault tolerant pipeline for API requests and responses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;a href=&quot;https://kagi.com&quot;&gt;Kagi&lt;/a&gt; account with an API key.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup&quot;&gt;Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;with&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 💡 Skip this line if you already have the public certificate installed.&lt;/span&gt;
gem cert &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--compressed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--location&lt;/span&gt; https://alchemists.io/gems.pem&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;kagi-api &lt;span class=&quot;nt&quot;&gt;--trust-policy&lt;/span&gt; HighSecurity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To install &lt;em&gt;without&lt;/em&gt; security, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;kagi-api&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also add the gem directly to your project:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bundle add kagi-api&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once the gem is installed, you only need to require it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;kagi/api&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage&quot;&gt;Usage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This client provides access to multiple endpoints. Each endpoint will answer either answer a &lt;code&gt;Success&lt;/code&gt; or &lt;code&gt;Failure&lt;/code&gt; (as provided by &lt;a href=&quot;https://dry-rb.org/gems/dry-monads&quot;&gt;Dry Monads&lt;/a&gt;) based on result of the API call. This allows you pattern match in your own code when using each endpoint. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;query: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Failure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Unknown HTTP response.&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;#_endpoints&quot;&gt;Endpoints&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can configure the client using a block and adjusting the &lt;code&gt;content_type&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, and/or &lt;code&gt;uri&lt;/code&gt; settings as desired. For example, you&amp;#8217;d only need to supply your Kagi API token (as found via your &lt;a href=&quot;https://kagi.com/settings?p=api&quot;&gt;account settings&lt;/a&gt;) to start using the client:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;secret&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;query: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you don&amp;#8217;t configure the client, then the following defaults will be used:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;application/json&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://kagi.com/api/v0&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_environment&quot;&gt;Environment&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can configure the client via the following environment variables. This is handy when you don&amp;#8217;t want to use block syntax or want fallbacks when no configuration is provided.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;KAGI_API_CONTENT_TYPE&lt;/code&gt;: Defines the HTTP &lt;code&gt;Content-Type&lt;/code&gt; header. You shouldn&amp;#8217;t need to change this. Default: &lt;code&gt;&quot;application/json&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;KAGI_API_TOKEN&lt;/code&gt;: Defines your personal key for API access. Default: &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;KAGI_API_URI&lt;/code&gt;: Defines the API URI. Default: &lt;code&gt;&quot;https://kagi.com/api/v0&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_endpoints&quot;&gt;Endpoints&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All endpoints are accessible via the client instance. Each will answer a &lt;code&gt;Success&lt;/code&gt; or &lt;code&gt;Failure&lt;/code&gt; result you can pattern match against. Even better, within each result, you&amp;#8217;ll get a &lt;a href=&quot;https://alchemists.io/articles/ruby_data&quot;&gt;Data&lt;/a&gt; object you can immediately interact with. See below to learn more about each endpoint.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_enrich_news&quot;&gt;Enrich News&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Message &lt;code&gt;#enrich_news&lt;/code&gt; to make API requests. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enrich_news&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;q: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby programming language&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Success(#&amp;lt;data Kagi::API::Models::Search meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=577, balance=2.259763&amp;gt;, data=[#&amp;lt;data Kagi::API::Models::Content::Search type=0, rank=nil, title=&quot;The Ruby Programming Language (Ruby)&quot;, url=&quot;https://github.com/ruby/ruby&quot;, snippet=&quot;For a complete list of ways to install Ruby...&quot;, published_at=2025-05-04 09:17:12 UTC, thumbnail=nil&amp;gt;]&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enrich_news&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Failure(#&amp;lt;data Kagi::API::Models::Error meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=87, balance=2.366512&amp;gt;, error=[#&amp;lt;data Kagi::API::Models::Content::Error code=1, message=&quot;Missing q parameter&quot;, reference=nil&amp;gt;]&amp;gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://help.kagi.com/kagi/api/enrich.html&quot;&gt;Kagi API Documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_enrich_web&quot;&gt;Enrich Web&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Message &lt;code&gt;#enrich_web&lt;/code&gt; to make API requests. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enrich_web&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;q: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby programming language&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Success(#&amp;lt;data Kagi::API::Models::Search meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=451, balance=2.257763&amp;gt;, data=[#&amp;lt;data Kagi::API::Models::Content::Search type=0, rank=nil, title=&quot;Ruby Programming Language&quot;, url=&quot;https://www.ruby-lang.org/en/&quot;, snippet=&quot;There is a vulnerability about Command Injection in RDoc which is bundled in Ruby. There is an XML round-trip vulnerability in REXML gem bundled with Ruby. And there is also an unintentional file creation vulnerability in tempfile library bundled with Ruby on Windows, because it uses tmpdir internally.&quot;, published_at=nil, thumbnail=nil&amp;gt;]&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enrich_web&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Failure(#&amp;lt;data Kagi::API::Models::Error meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=27, balance=2.362512&amp;gt;, error=[#&amp;lt;data Kagi::API::Models::Content::Error code=1, message=&quot;Missing q parameter&quot;, reference=nil&amp;gt;]&amp;gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://help.kagi.com/kagi/api/enrich.html&quot;&gt;Kagi API Documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_fast&quot;&gt;Fast&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Message &lt;code&gt;#fast&lt;/code&gt; to make API requests. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;query: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Success(#&amp;lt;data Kagi::API::Models::Fast meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=2915, balance=2.362512&amp;gt;, data=#&amp;lt;data Kagi::API::Models::Content::Fast output=&quot;Ruby is a dynamic, open-source programming language that focuses on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. Ruby supports multiple programming paradigms, including functional, object-oriented, and imperative. It is also known for its flexible nature, allowing developers to easily modify its parts. &quot;, tokens=1172, references=[]&amp;gt;&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fast&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Failure(#&amp;lt;data Kagi::API::Models::Error meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=26, balance=2.347512&amp;gt;, error=[#&amp;lt;data Kagi::API::Models::Content::Error code=1, message=&quot;Parameter \&quot;query\&quot; is required and must not be empty&quot;, reference=nil&amp;gt;]&amp;gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://help.kagi.com/kagi/api/fastgpt.html&quot;&gt;Kagi API Documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_search&quot;&gt;Search&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Message &lt;code&gt;#search&lt;/code&gt; to make API requests. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;search&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;q: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ruby&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Success(#&amp;lt;data Kagi::API::Models::Search meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=1225, balance=2.322512&amp;gt;, data=[#&amp;lt;data Kagi::API::Models::Content::Search type=0, rank=nil, title=&quot;Ruby Programming Language&quot;, url=&quot;https://www.ruby-lang.org/en/&quot;, snippet=&quot;A dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.&quot;, published_at=nil, thumbnail=nil&amp;gt;]&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;search&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Failure(#&amp;lt;data Kagi::API::Models::Error meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=27, balance=2.322512&amp;gt;, error=[#&amp;lt;data Kagi::API::Models::Content::Error code=1, message=&quot;Missing q parameter&quot;, reference=nil&amp;gt;]&amp;gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://help.kagi.com/kagi/api/search.html&quot;&gt;Kagi API Documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_summarize&quot;&gt;Summarize&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Message &lt;code&gt;#summarize&lt;/code&gt; to make API requests. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Kagi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;summarize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;url: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.ruby-lang.org/en&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;summary_type: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;summary&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Success(#&amp;lt;data Kagi::API::Models::Summary meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=3828, balance=2.261763&amp;gt;, data=#&amp;lt;data Kagi::API::Models::Content::Summary output=&quot;The Ruby Programming Language is a dynamic, open-source language designed for simplicity and productivity, featuring an elegant syntax that is easy to read and write. It is well-known for its straightforward \&quot;Hello World!\&quot; program, which requires minimal syntax. The Ruby community actively shares updates, including recent releases such as Ruby 3.5.0-preview1, Ruby 3.4.3, and Ruby 3.3.8, along with security advisories highlighting vulnerabilities like CVE-2025-43857 related to the net-imap gem. \n\nUsers can easily get started with Ruby through resources like \&quot;Try Ruby!\&quot; and \&quot;Ruby in Twenty Minutes.\&quot; The website offers extensive documentation, libraries, and success stories, encouraging participation in a vibrant community through mailing lists, user groups, and issue tracking. Ruby&#39;s commitment to user engagement is evident through various community platforms where developers can collaborate and share knowledge. The site also provides multilingual support, making Ruby accessible to a global audience.&quot;, tokens=2025&amp;gt;&amp;gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;summarize&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Failure(#&amp;lt;data Kagi::API::Models::Error meta=#&amp;lt;data Kagi::API::Models::Content::Meta id=&quot;&amp;lt;redacted&amp;gt;&quot;, node=&quot;us-west2&quot;, duration=114, balance=2.322512&amp;gt;, error=[#&amp;lt;data Kagi::API::Models::Content::Error code=200, message=&quot;We are sorry, this input is not supported. (Invalid Input)&quot;, reference=nil&amp;gt;]&amp;gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://help.kagi.com/kagi/api/summarizer.html&quot;&gt;Kagi API Documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development&quot;&gt;Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To contribute, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/bkuhlmann/kagi-api
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;kagi-api
bin/setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can also use the IRB console for direct access to all objects:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/console&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_tests&quot;&gt;Tests&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To test, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;rouge highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/rake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_license&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/license&quot;&gt;License&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_security&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/security&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_code_of_conduct&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/code_of_conduct&quot;&gt;Code of Conduct&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_contributions&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/contributions&quot;&gt;Contributions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_developer_certificate_of_origin&quot;&gt;&lt;a href=&quot;https://alchemists.io/policies/developer_certificate_of_origin&quot;&gt;Developer Certificate of Origin&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_versions&quot;&gt;&lt;a href=&quot;https://alchemists.io/projects/kagi-api/versions&quot;&gt;Versions&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_community&quot;&gt;&lt;a href=&quot;https://alchemists.io/community&quot;&gt;Community&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_credits&quot;&gt;Credits&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Built with &lt;a href=&quot;https://alchemists.io/projects/gemsmith&quot;&gt;Gemsmith&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Engineered by &lt;a href=&quot;https://alchemists.io/team/brooke_kuhlmann&quot;&gt;Brooke Kuhlmann&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
    <id>https://alchemists.io/projects/kagi-api</id>
    <link href="https://alchemists.io/projects/kagi-api"/>
    <published>2025-05-04T21:10:43+00:00</published>
    <rights>2026</rights>
    <title>Kagi API Project</title>
    <updated>2026-09-16T23:39:25+00:00</updated>
    <dc:date>2026-09-16T23:39:25+00:00</dc:date>
  </entry>
  <dc:date>2026-10-09T16:00:48+00:00</dc:date>
</feed>
