<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
  <channel>
    <title>🔥 Updates</title>
    <link>https://aoba-test.netlify.app/</link>
    <atom:link href="https://aoba-test.netlify.app/feed.xml" rel="self" type="application/rss+xml"/>
    <description>A blog to follow the updates of Lume, the static site generator for Deno</description>
    <lastBuildDate>Sat, 11 Nov 2023 13:28:08 GMT</lastBuildDate>
    <language>en</language>
    <generator>Lume v1.19.3</generator>
    <item>
      <title>Lume 1.19.0 release notes</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>Lume 1.19.0 was released! Hopefully, it will be the last minor version of 1.x
        before the incoming Lume 2. This is a summary of the changes and new features.</p>
        <!-- more -->
        <h2 id="favicon-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#favicon-plugin" class="header-anchor">Favicon plugin</a></h2>
        <p>The favicon is a common task we have to do every time we build a new website.
        It's not as easy as should be because there are different formats, sizes,
        resolutions, etc. The new <code>favicon</code> plugin was created to make it more simple.</p>
        <p>You only have to specify an input file (by default <code>favicon.svg</code>) and the plugin
        automatically creates the files <code>/favicon.ico</code>, <code>/favicon-16.png</code>,
        <code>/favicon-32.png</code> and <code>/apple-touch-icon.png</code> and adds the <code>&lt;link&gt;</code> elements
        needed in all HTML pages.</p>
        <p>As any other Lume plugin, the installation can't be easier: just import the
        plugin and use it:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import favicon from &quot;lume/plugins/favicon.ts&quot;;
        
        const site = lume();
        site.use(favicon());
        
        export default site;
        </code></pre>
        <p>See <a href="https://lume.land/plugins/favicon/">the favicon plugin documentation</a>.</p>
        <h2 id="reading-info-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#reading-info-plugin" class="header-anchor">Reading info plugin</a></h2>
        <p>This plugin was created by <a href="https://github.com/jrson83">Jrson</a> and available in
        the
        <a href="https://github.com/lumeland/experimental-plugins">experimental plugins repo</a>
        since a time ago, under the name <code>reading_time</code>. It's a simple plugin to
        calculate the time required to read the content of a page.</p>
        <p>Due the plugin is being used in several projects (among them, this blog), it was
        moved to Lume repo and renamed to <code>reading_info</code>. The reason of the new name is
        the plugin not only returns the time, but also other interesting info like the
        number of words. Maybe we can include more interesting info in the future, let
        me know your suggestions.</p>
        <p>It uses the
        <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter"><code>Int.Segmenter</code></a>
        standard function to count the words, using the page variable <code>lang</code> to detect
        the language. The data is stored in the variable <code>readingInfo</code>, so you can use
        it in your templates in this way:</p>
        <pre><code class="language-vento">&lt;h1&gt;{{ title }}&lt;/h1&gt;
        &lt;p&gt;{{ readingInfo.words }} words / {{ readingInfo.minutes }} min read&lt;/p&gt;
        </code></pre>
        <p>See
        <a href="https://lume.land/plugins/reading_info/">the reading_info plugin documentation</a></p>
        <h2 id="improved-the-picture-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#improved-the-picture-plugin" class="header-anchor">Improved the <code>picture</code> plugin</a></h2>
        <p>The <a href="https://lume.land/plugins/picture/">picture plugin</a> has received many
        improvements and bug fixes. The most notable:</p>
        <h3 id="changed-the-src-value-of-the-original-img-element" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#changed-the-src-value-of-the-original-img-element" class="header-anchor">Changed the <code>src</code> value of the original <code>img</code> element</a></h3>
        <p>In previous versions, the <code>src</code> value of the <code>img</code> element referred to the
        original image. But this image isn't always exported so it returns a <code>404</code>
        error. As of Lume 1.19, the last <code>source</code> element will be used as the value for
        the <code>img</code>:</p>
        <pre><code class="language-html">&lt;!-- Source code --&gt;
        &lt;img src=&quot;/images/test.jpg&quot; imagick=&quot;jpg webp 600&quot;&gt;
        
        &lt;!-- Previous output: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/images/test-600w.webp&quot; type=&quot;image/webp&quot;&gt;
        &lt;source srcset=&quot;/images/test-600w.jpg&quot; type=&quot;image/jpeg&quot;&gt;
        &lt;img src=&quot;/images/test.jpg&quot;&gt;
        &lt;/picture&gt;
        
        &lt;!-- New output: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/images/test-600w.webp&quot; type=&quot;image/webp&quot;&gt;
        &lt;img src=&quot;/images/test-600w.jpg&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <h3 id="formats-sorted-automatically" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#formats-sorted-automatically" class="header-anchor">Formats sorted automatically</a></h3>
        <p>In the previous version, the <code>source</code> elements were created in the same order as
        defined in the <code>imagick</code> attribute. For example:</p>
        <pre><code class="language-html">&lt;img src=&quot;/images/test.jpg&quot; imagick=&quot;jpg webp avif 600&quot;&gt;
        </code></pre>
        <p>This outputs the <code>source</code> elements in the same order (<code>jpg</code>, <code>webp</code> and <code>avif</code>):</p>
        <pre><code class="language-html">&lt;picture&gt;
        &lt;source srcset=&quot;/images/test-600w.jpg&quot; type=&quot;image/jpeg&quot;&gt;
        &lt;source srcset=&quot;/images/test-600w.webp&quot; type=&quot;image/webp&quot;&gt;
        &lt;source srcset=&quot;/images/test-600w.avif&quot; type=&quot;image/avif&quot;&gt;
        &lt;img src=&quot;/images/test.jpg&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <p>Because <code>jpg</code> is a format widely supported, it will be choosen by all browsers
        because it's the first in the list, even if better formats like <code>webp</code> or <code>avif</code>
        are there. As of Lume 1.19 the formats are sorted automatically. By default the
        order is: <code>jxl, avif, webp, png, jpg</code> (from the most modern to the most
        supported). So the new output is:</p>
        <pre><code class="language-html">&lt;picture&gt;
        &lt;source srcset=&quot;/images/test-600w.avif&quot; type=&quot;image/avif&quot;&gt;
        &lt;source srcset=&quot;/images/test-600w.webp&quot; type=&quot;image/webp&quot;&gt;
        &lt;img src=&quot;/images/test-600w.jpg&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <h3 id="allow-to-define-only-formats" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#allow-to-define-only-formats" class="header-anchor">Allow to define only formats</a></h3>
        <p>From now on, the <code>imagick</code> attribute can have only formats, sizes are no longer
        mandatory. It's useful if you don't want to resize the image, just provide
        different formats:</p>
        <pre><code class="language-html">&lt;!-- Source code --&gt;
        &lt;img src=&quot;/images/test.jpg&quot; imagick=&quot;avif jpg webp&quot;&gt;
        
        &lt;!-- Ouputs: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/images/test.avif&quot; type=&quot;image/avif&quot;&gt;
        &lt;source srcset=&quot;/images/test.webp&quot; type=&quot;image/webp&quot;&gt;
        &lt;img src=&quot;/images/test.jpg&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <h3 id="don't-create-a-new-picture-just-for-one-source" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#don't-create-a-new-picture-just-for-one-source" class="header-anchor">Don't create a new picture just for one source</a></h3>
        <p>If the image has only one format, no <code>picture</code> element will be created:</p>
        <pre><code class="language-html">&lt;!-- Source code --&gt;
        &lt;img src=&quot;/images/test.jpg&quot; imagick=&quot;avif 300&quot;&gt;
        
        &lt;!-- Previous output: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;/images/test-300.avif&quot; type=&quot;image/avif&quot;&gt;
        &lt;img src=&quot;/images/test.jpg&quot;&gt;
        &lt;/picture&gt;
        
        &lt;!-- New ouput: --&gt;
        &lt;img src=&quot;/images/test-300.avif&quot;&gt;
        </code></pre>
        <h3 id="support-for-size-attribute" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#support-for-size-attribute" class="header-anchor">Support for <code>size</code> attribute</a></h3>
        <p>The plugin now supports the <code>size</code> attribute:</p>
        <pre><code class="language-html">&lt;!-- Source code --&gt;
        &lt;img src=&quot;img.png&quot; imagick=&quot;avif png 100@2&quot; sizes=&quot;(width &lt; 700px) 100px, 200px&quot;&gt;
        
        &lt;!-- Previous output: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;img-100w.avif, img-100w@2.avif 2x&quot; type=&quot;image/avif&quot;&gt;
        &lt;source srcset=&quot;img-100w.png, img-100w@2.png 2x&quot; type=&quot;image/png&quot;&gt;
        &lt;img src=&quot;img.png&quot; /&gt;
        &lt;/picture&gt;
        
        &lt;!-- New output: --&gt;
        &lt;picture&gt;
        &lt;source srcset=&quot;img-100w.avif, img-100w@2.avif 2x&quot; type=&quot;image/avif&quot; sizes=&quot;(width &lt; 700px) 100px, 200px&quot;&gt;
        &lt;img src=&quot;img-100w.png&quot; srcset=&quot;img-100w@2.png 2x&quot; sizes=&quot;(width &lt; 700px) 100px, 200px&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <h2 id="new-functions-to-site-instance" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#new-functions-to-site-instance" class="header-anchor">New functions to <code>site</code> instance</a></h2>
        <h3 id="mergekey" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#mergekey" class="header-anchor">mergeKey</a></h3>
        <p>Lume allows to customize the way some keys are merged with the variable
        <code>mergedKeys</code>. You can see a
        <a href="https://lume.land/docs/core/merged-keys/">detailed explanation of this feature</a>
        in the documentation.</p>
        <p>The function <code>site.mergeKey()</code> allows to define this value in the _config.ts
        file, which is more useful specially for plugins that register new merge
        strategies for some keys automatically.</p>
        <p>For example, let's say you want to merge the keys <code>categories</code> using the
        <code>stringArray</code> strategy:</p>
        <pre><code class="language-ts">site.mergeKey(&quot;categories&quot;, &quot;stringArray&quot;);
        </code></pre>
        <h3 id="page" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#page" class="header-anchor">page</a></h3>
        <p>The <code>site.page()</code> function allows to create new pages dynamically from the
        <code>_config.ts</code> file, without having a page file in the disk. You only have to set
        the data object of the page, for example:</p>
        <pre><code class="language-ts">site.page(
        {
        url: &quot;/about-me/&quot;,
        layout: &quot;about-page.njk&quot;,
        content: &quot;Hello, my name is Óscar&quot;,
        },
        );
        </code></pre>
        <p>By default, the context of the page is the root directory (<code>/</code>), so any shared
        data defined in <code>_data</code> files/folders is accessible to this page. You can change
        the scope of the page in the second argument:</p>
        <pre><code class="language-ts">site.page(
        {
        url: &quot;/about-me/&quot;,
        layout: &quot;about-page.njk&quot;,
        content: &quot;Hello, my name is Óscar&quot;,
        },
        &quot;/pages&quot;,
        );
        </code></pre>
        <p>Now the page is scoped to the <code>/pages</code> directory, so it can access to the data
        stored in the <code>/pages/_data.yml</code> file, for example.</p>
        <h2 id="upgrade-pagefind-to-v1.0" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.19.0-release-notes/#upgrade-pagefind-to-v1.0" class="header-anchor">Upgrade pagefind to v1.0</a></h2>
        <p>The great <a href="https://pagefind.app/">Pagefind</a> library, used by the
        <a href="https://lume.land/plugins/pagefind/">pagefind plugin</a> is now 1.0🎉. This new
        version brings
        <a href="https://github.com/CloudCannon/pagefind/releases/tag/v1.0.0">new awesome features</a>,
        but also some changes:</p>
        <ul>
        <li>The option to configure the binary file was removed. The plugin use the <code>npm</code>
        version that downloads the binary automatically in the Deno cache folder. No
        more <code>_bin</code> folders!</li>
        <li>The option <code>indexing.bundleDirectory</code> was renamed to <code>outputPath</code>.</li>
        <li>Added the option <code>customRecords</code> that allows to add additional records to the
        pagefind database in addition to those generated by the output pages.</li>
        </ul>
        <p>See the
        <a href="https://github.com/lumeland/lume/blob/v1.19.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Mon, 25 Sep 2023 18:25:59 GMT</pubDate>
    </item>
    <item>
      <title>Improved plugins docs</title>
      <link>https://aoba-test.netlify.app/posts/improved-plugins-docs/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/improved-plugins-docs/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>Documentation is possibly one of the most important things for the adoption of
        any OSS project. No matter if your software is good and easy to use: if you
        don't communicate it well, most people won't spend time figuring out how to use
        it.</p>
        <!-- more -->
        <p>Lume was very clear about that from the beginning and a lot of effort was put
        into the documentation website. But one of the difficulties is to keep it
        updated with the new changes because <strong>wrong documentation is worse than no
        documentation.</strong></p>
        <h2 id="plugins-documentation" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/improved-plugins-docs/#plugins-documentation" class="header-anchor">Plugins documentation</a></h2>
        <p>Documentation is especially challenging for the
        <a href="https://lume.land/plugins/">plugins section</a>: A lot of plugins, each one with
        its configuration, many of them depend on external libraries (like nunjucks,
        pug, etc.) which have more configuration, etc. Maintaining all this info up to
        date is a hard time-consuming job.</p>
        <p>But Lume is built on top of Deno, and Deno is supposed to make our life better,
        right? (at least our life as developers). <strong>And it does!</strong> because Deno includes
        a
        <a href="https://deno.land/manual@v1.36.3/tools/documentation_generator">Documentation generator</a>
        thanks to <code>deno doc</code>, which can extract a lot of interesting info from
        TypeScript files. It's used to build automatically the modules' documentation in
        deno.land/x repository. Take a look at
        <a href="https://deno.land/x/lume@v1.18.5/plugins/date.ts?s=Options">the options for the date plugin</a>.</p>
        <h2 id="deno-doc-%2B-aldara" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/improved-plugins-docs/#deno-doc-%2B-aldara" class="header-anchor">Deno Doc + Aldara</a></h2>
        <p>With this idea in mind, I started working on a tool to generate this kind of
        documentation automatically to be displayed inside the lume.land website. Most
        Lume plugins export the following two elements:</p>
        <ul>
        <li><a href="https://github.com/lumeland/lume/blob/5e03f8c13d9e0af6c3737bd2813449d59d2084e6/plugins/code_highlight.ts#L6-L18">The <code>Options</code> interface</a>
        with the types of plugin options</li>
        <li><a href="https://github.com/lumeland/lume/blob/5e03f8c13d9e0af6c3737bd2813449d59d2084e6/plugins/code_highlight.ts#L21-L31">The <code>defaults</code> object</a>
        with the default options.</li>
        </ul>
        <p>The idea is to use these two elements to build automatically the documentation
        for every plugin. This not only saves time but also ensures the documentation is
        always up to date.</p>
        <p>The command <code>deno doc --json</code> outputs the info in JSON format, perfect for
        processing. I've created the
        <a href="https://github.com/oscarotero/aldara">aldara library</a> that gets the types from
        Deno Doc, transforms the JSON to a more easy-to-consume structure and even
        completes some missing info with any JsDoc content found. Then, it can set the
        default values from the <code>defaults</code> object exported by the plugin and that's all!</p>
        <p>The code do all this stuff it is very simple:</p>
        <pre><code class="language-ts">import analyze, {
        mergeDefaults,
        } from &quot;https://deno.land/x/aldara@v0.1.1/mod.ts&quot;;
        
        async function getScheme(mod: string) {
        const url = `https://deno.land/x/lume@v1.18.5/${mod}`;
        const { defaults } = await import(url);
        const { Options } = await analyze(url, { maxDepth: 2 });
        
        mergeDefaults(Options, defaults);
        return Options.children;
        }
        </code></pre>
        <p>You can see an example in the
        <a href="https://lume.land/plugins/minify_html/">Minify HTML plugin documentation</a>.</p>
        <h2 id="future" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/improved-plugins-docs/#future" class="header-anchor">Future</a></h2>
        <p>This is only the first version, there's a lot of room for improvement. I've
        found some issues in <code>deno doc</code> that I hope they were fixed at some point soon:</p>
        <ul>
        <li><code>npm:</code> dependencies are not supported, so the types provided by NPM packages
        are not included.</li>
        <li>There are memory issues with circular dependencies
        (<a href="https://github.com/denoland/deno_doc/issues/303">issue #303</a>), so private
        types (those that are not exported) cannot be displayed.</li>
        </ul>
        <p>Anyway, even with these issues, I think the plugin documentation is now much
        better than it was. Please, let me know if you have any questions or have found
        any issues.</p>
        ]]>
      </content:encoded>
      <pubDate>Fri, 01 Sep 2023 13:54:48 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.18.0 release notes</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>This is a summary of the new features introduced in Lume (<strong>1.18.0</strong>).</p>
        <!-- more -->
        <h2 id="picture-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/#picture-plugin" class="header-anchor">Picture plugin</a></h2>
        <p>Adding images to web pages is a hard task nowadays. There are new modern image
        formats like AVIF and JPEG XL with better quality and compression but they are
        not supported by all browsers.</p>
        <p>In order to make this work more easy, Lume has the <code>picture</code> plugin that
        converts any regular <code>&lt;img&gt;</code> element to a full featured <code>&lt;picture&gt;</code> element
        creating all <code>&lt;source srcset&gt;</code> needed to support all formats and resolutions.
        This plugin relies on the <code>imagick</code> plugin to make the transformations, so you
        need the two plugins installed in this exact order:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import picture from &quot;lume/plugins/picture.ts&quot;;
        import imagick from &quot;lume/plugins/imagick.ts&quot;;
        
        const site = lume();
        site.use(picture());
        site.use(imagick());
        
        export default site;
        </code></pre>
        <p>Once installed, the plugin will search for all HTML elements with the <code>imagick</code>
        attribute and will convert the images to the specified formats. For example:</p>
        <pre><code class="language-html">&lt;img src=&quot;/flowers.jpg&quot; imagick=&quot;avif webp jpg 300@2&quot;&gt;
        </code></pre>
        <p>The <code>imagick</code> attribute of this image contains the desired formats (<code>avif</code>,
        <code>webp</code> and <code>jpg</code>) and the different sizes (<code>300</code> which means 300 pixels). The
        <code>@2</code> suffix indicates that this size should support also the <code>2x</code> resolution.
        The output HTML code is:</p>
        <pre><code class="language-html">&lt;picture&gt;
        &lt;source srcset=&quot;/flowers-300w.avif, /flowers-300w@2.avif 2x&quot; type=&quot;image/avif&quot;&gt;
        &lt;source srcset=&quot;/flowers-300w.webp, /flowers-300w@2.webp 2x&quot; type=&quot;image/webp&quot;&gt;
        &lt;source srcset=&quot;/flowers-300w.jpg, /flowers-300w@2.jpg 2x&quot; type=&quot;image/jpeg&quot;&gt;
        &lt;img src=&quot;/flowers.jpg&quot;&gt;
        &lt;/picture&gt;
        </code></pre>
        <p><a href="https://lume.land/plugins/picture/">See the documentation</a> for more info about
        this plugin.</p>
        <h2 id="symlinks-support" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/#symlinks-support" class="header-anchor">Symlinks support</a></h2>
        <p>Lume 1.18.0 introduces symlinks support in the <code>src</code> directory. This means that
        you can include symlinks targeting files and folders outside of the <code>src</code> (for
        example a page or a folder with templates) and Lume will follow them and will
        use those files to build the site.</p>
        <p>This can be useful if you want to reuse the same files for different projects.
        Instead of copying the files for each project, you can store them in a single
        place and add symlinks from the different projects.</p>
        <p>Keep in mind that the Lume watcher doesn't detect changes in these files.</p>
        <h2 id="vento-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/#vento-plugin" class="header-anchor">Vento plugin</a></h2>
        <p><a href="https://github.com/oscarotero/vento">Vento</a> is a new template engine designed
        to use the best ideas from Nunjucks, Liquid, Eta/EJS and Mustache. Some
        highlighted features are:</p>
        <ul>
        <li>Async friendly</li>
        <li>Simple API</li>
        <li>Allows to write JavaScript code in the templates</li>
        </ul>
        <p>To use it, you must import it in the _config file:</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        import vento from &quot;lume/plugins/vento.ts&quot;;
        
        const site = lume();
        site.use(vento());
        
        export default site;
        </code></pre>
        <p>Vento template engine has been created by me (Óscar Otero, also the Lume
        creator) and I'm thinking of making it the default engine (replacing Nunjucks)
        at some point. I would like to know your thoughts.</p>
        <p><a href="https://lume.land/plugins/vento/">See more info about this plugin</a> in the
        documentation.</p>
        <h2 id="lightningcss-bundler" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/#lightningcss-bundler" class="header-anchor">LightningCSS bundler</a></h2>
        <p>Until now, the <code>lightningcss</code> plugin only transformed the CSS code but
        <a href="https://github.com/lumeland/lume/issues/273">it couldn't bundle it</a> (inline the
        <code>@import</code>'ed styles to output a single file with all the code). The reason is
        LightningCSS is an NPM package that didn't work properly on Deno due the lack of
        support of some NAPI functions so Lume had to use the WASM version
        <a href="https://github.com/parcel-bundler/lightningcss/issues/277">that only transform the code but not bundle it</a>.</p>
        <p>Deno team finally improved support for NAPI and now it's possible to use the NPM
        version of <code>lightningcss</code> and bundle the code. In fact, as of Lume 1.18 the
        plugin <strong>bundles the CSS code by default</strong>.</p>
        <p>If you want to disable the bundler and only transform the code (back to the
        previous behavior), just add a <code>includes: false</code> option in the _config file:</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        import lightningcss from &quot;lume/plugins/lightningcss.ts&quot;;
        
        const site = lume();
        site.use(lightningcss({
        includes: false, // Disable the bundler
        }));
        
        export default site;
        </code></pre>
        <h2 id="support-for-jsonc-and-toml" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.18.0-release-notes/#support-for-jsonc-and-toml" class="header-anchor">Support for JSONC and TOML</a></h2>
        <p>Thanks to <a href="https://github.com/kwaa">@kwaa</a> for working on the JSONC and TOML
        support for Lume. Now you not only can use YAML format in the front matter but
        also JSON and TOML formats.</p>
        <p>To use JSON (or JSONC) in the front matter:</p>
        <pre><code>{
        &quot;title&quot;: &quot;Hello world&quot;
        }
        
        Page content
        </code></pre>
        <p>To use TOML in the front matter:</p>
        <pre><code>+++
        title = Hello world
        +++
        
        Page content
        </code></pre>
        <p>JSONC is enabled by default for pages and data files. So any file with the
        extension <code>.tmpl.jsonc</code> or a data file <code>_data.jsonc</code> or <code>_data/*.jsonc</code> is
        loaded by default.</p>
        <p>TOML files can also be used for pages and data files but this format is not
        enabled by default (probably it will in Lume 2.0). To enable it, just import the
        plugin in the _config file:</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        import toml from &quot;lume/plugins/toml.ts&quot;;
        
        const site = lume();
        site.use(toml());
        
        export default site;
        </code></pre>
        <p>See the
        <a href="https://github.com/lumeland/lume/blob/v1.18.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Thu, 22 Jun 2023 12:51:21 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.17.0 release notes</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>This is a brief summary of the main changes introduced in Lume (<strong>1.17.0</strong>).</p>
        <!-- more -->
        <h2 id="new-plugin%3A-feed" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/#new-plugin%3A-feed" class="header-anchor">New plugin: <code>feed</code></a></h2>
        <p>One of the most common things to do when developing a web site is the RSS feed.
        It's almost mandatory for blogs but it can also be useful for any website with
        some regular updates. In the same way that there was a
        <a href="https://lume.land/plugins/sitemap/"><code>sitemap</code> plugin</a> to build the sitemap of
        the site, Lume 1.17 introduces the new
        <a href="https://lume.land/plugins/feed/"><code>feed</code> plugin</a> to build a feed in <code>RSS</code> or
        <code>JSON Feed</code> format.</p>
        <p>🔥🔥 Thanks to
        <a href="https://github.com/lumeland/lume/pull/413">adb-sh for his initial pull request</a>.</p>
        <p>To use this plugin, just import it in your <code>_config.ts</code> and configure it:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import feed from &quot;lume/plugins/feed.ts&quot;;
        
        const site = lume();
        
        site.use(feed({
        output: [&quot;/posts.rss&quot;, &quot;/posts.json&quot;],
        query: &quot;type=post&quot;,
        sort: &quot;date=desc&quot;,
        limit: 10,
        info: {
        title: &quot;My awesome blog&quot;,
        description: &quot;Post updates of my blog&quot;,
        },
        items: {
        title: &quot;=title&quot;,
        description: &quot;=excerpt&quot;,
        },
        }));
        
        export default site;
        </code></pre>
        <p>In this example, Lume creates two Feed files defined in the <code>output</code> key:
        <code>/posts.rss</code> (in RSS format) and <code>/posts.json</code> (in
        <a href="https://www.jsonfeed.org/">JSON Feed format</a>). The file extensions determines
        the format to use.</p>
        <p>The <code>query</code>, <code>sort</code> and <code>limit</code> options are the same as you typically use in the
        <a href="https://lume.land/plugins/search/"><code>search.pages()</code></a> API.</p>
        <p>The <code>info</code> object has the description of the Feed (like title, description, etc)
        and the <code>items</code> object the description of every item in the Feed. Both objects
        use the
        <a href="https://lume.land/plugins/metas/#field-aliases">same aliases as <code>metas</code> plugin</a>:
        any value starting with <code>=</code> represents a variable name that will be used to
        extract this info. In our example, the title and description is the same as the
        title and excerpt variables of the page.</p>
        <p>It's also possible to extract the info using CSS selectors. For example, let's
        say we want to generate a RSS with the same content as the div <code>.post-content</code>.
        We just have to start the value of the code with <code>$</code>:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import feed from &quot;lume/plugins/feed.ts&quot;;
        
        const site = lume();
        
        site.use(feed({
        output: [&quot;/posts.rss&quot;, &quot;/posts.json&quot;],
        query: &quot;type=post&quot;,
        sort: &quot;date=desc&quot;,
        limit: 10,
        info: {
        title: &quot;My awesome blog&quot;,
        description: &quot;Post updates of my blog&quot;,
        },
        items: {
        title: &quot;=title&quot;,
        description: &quot;=excerpt&quot;,
        content: &quot;$.post-content&quot;,
        },
        }));
        
        export default site;
        </code></pre>
        <p>If you want to create more than one feed, just use the plugin once per feed:</p>
        <pre><code class="language-ts">site.use(feed({
        output: &quot;/posts.rss&quot;,
        // Posts feed configuration
        }));
        
        site.use(feed({
        output: &quot;/articles.rss&quot;,
        // Articles feed configuration
        }));
        </code></pre>
        <h2 id="sass-supports-remote-files" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/#sass-supports-remote-files" class="header-anchor">SASS supports remote files</a></h2>
        <p>In this version, Lume got a big refactoring of how the files in the <code>src</code>
        directory are scanned, loaded and refreshed. This change fixed some existing
        bugs and open the door for new possibilities, because now it will be easier to
        implement new features.</p>
        <p>Thanks to this refactoring, SASS plugin supports
        <a href="https://lume.land/docs/core/remote-files/">remote files</a>, so you can load your
        variables and mixings from a remote URL to use them in your build:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import sass from &quot;lume/plugins/sass.ts&quot;;
        
        const site = lume();
        site.use(sass());
        
        site.remoteFile(
        &quot;/_includes/variables.scss&quot;,
        &quot;https://example.com/theme/variables.scss&quot;,
        );
        
        export default site;
        </code></pre>
        <pre><code class="language-css">@import &quot;variables.scss&quot;;
        
        body {
        color: $main-color;
        }
        </code></pre>
        <p>The're a breaking change in the SASS plugin: the <code>includes</code> option accepts only
        a string instead of an array of paths.</p>
        <h2 id="allow-to-pass-extra-data-to-on-demand-pages" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/#allow-to-pass-extra-data-to-on-demand-pages" class="header-anchor">Allow to pass extra data to on demand pages</a></h2>
        <p>The <a href="https://lume.land/plugins/on_demand/">on_demand plugin</a> allows to render a
        page on request time, instead of build time. This is useful to insert dynamic
        content and reduce the build time specially for big sites. Lume 1.17 introduces
        a way to insert additional variables to the page before rendering.</p>
        <p>The <code>onDemand</code> plugin has the new option <code>extraData</code> which accepts a function
        that must return an object with the extra data to be passed to the page. For
        example, let's say we want to pass the search parameters of the request's url:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import onDemand from &quot;lume/plugins/on_demand.ts&quot;;
        
        site.use(onDemand({
        extraData(request: Request) {
        const searchParams = new URL(request.url).searchParams;
        const params = Object.fromEntries(searchParams.entries());
        
        return {
        params,
        };
        },
        }));
        
        export default site;
        </code></pre>
        <p>Now, the on demand pages will have the <code>params</code> key with the search params
        values. For example, in a Nunjucks page:</p>
        <pre><code class="language-njk">---
        layout: layout.njk
        ondemand: true
        url: /example/
        ---
        
        Hello {{ params.name }}
        </code></pre>
        <p>The URL <code>/example/?name=Óscar</code> will return <code>Hello Òscar</code>.</p>
        <p>Note that on-demand pages works better on Deno CLI than Deno Deploy. There's a
        <a href="https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/ondemand-plugin-november-2022.md">post explaining the current limitations on Deno Deploy</a>,
        so you should consider this plugin as highly experimental.</p>
        <h2 id="removed-old-code" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.17.0-release-notes/#removed-old-code" class="header-anchor">Removed old code</a></h2>
        <p>A few versions ago, Lume removed the ability to be installed globally (with
        <code>deno install ...</code>) in benefit of <code>deno task</code>. Some old files were keept for
        backward compatibility when upgrading from an old version. Now these files were
        removed (<code>ci.ts</code>, <code>install.ts</code>). If you get any issue running Lume (specially in
        CI environments), please update your script to use <code>deno task lume</code>.</p>
        <p>There are more changes in Lume 1.17, like bug fixes in some plugins, dependency
        updates, etc. See the
        <a href="https://github.com/lumeland/lume/blob/v1.17.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Fri, 05 May 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.16.0 release notes</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>Hi everyone! This is a brief summary of what the new version of Lume
        (<strong>1.16.0</strong>) brings.</p>
        <!-- more -->
        <h2 id="breaking-change%3A-multilanguage-plugin-refactor" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#breaking-change%3A-multilanguage-plugin-refactor" class="header-anchor">BREAKING CHANGE: <code>multilanguage</code> plugin refactor</a></h2>
        <p>The <code>multilanguage</code> plugin was created to simplify the creation of sites in
        multiple languages. But the way it worked so far was a bit confusing and not
        very practical. Lume 1.16 introduce some changes that (sadly) breaks some
        compatibility with the previous version. But I think the new behavior is much
        more clear and easy to use and understand. Some of the most important changes:</p>
        <h3 id="you-need-to-specify-the-available-languages-in-the-_config-file" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#you-need-to-specify-the-available-languages-in-the-_config-file" class="header-anchor">You need to specify the available languages in the _config file</a></h3>
        <p>In the old plugin, each page defined its own languages. There wasn't a place to
        specify the available languages for the whole site. This makes the plugin to
        work inconsistently for each page, because it depended on the number of
        languages defined in every case. The new version requires to specify the
        languages in the _config file, so it will work in the same way with all pages.</p>
        <pre><code class="language-ts">site.use(multilanguage({
        languages: [&quot;en&quot;, &quot;gl&quot;],
        }));
        </code></pre>
        <h3 id="the-language-prefix-is-automatically-added-to-the-urls." tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#the-language-prefix-is-automatically-added-to-the-urls." class="header-anchor">The language prefix is automatically added to the urls.</a></h3>
        <p>The new plugin automatically prepend the <code>/${lang}/</code> prefix to all urls. If you
        have the following page:</p>
        <pre><code class="language-md">---
        lang: en
        url: /hello-world/
        ---
        
        # Hello world
        </code></pre>
        <p>The output file is <code>/en/hello-world/</code>. This ensure all pages in the same
        language are in the same subdirectory.</p>
        <p>It's possible to define a language as default, so all pages in this language
        won't have this prefix. For example, let's say our site is in english and
        galician but we want to set english as the main language:</p>
        <pre><code class="language-ts">site.use(multilanguage({
        languages: [&quot;en&quot;, &quot;gl&quot;],
        defaultLanguage: &quot;en&quot;,
        }));
        </code></pre>
        <p>With this configuration, the english version of the page is <code>/hello-world/</code> but
        the galician version is <code>/gl/hello-world/</code>.</p>
        <h3 id="use-id-to-relate-pages-in-different-languages" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#use-id-to-relate-pages-in-different-languages" class="header-anchor">Use <code>id</code> to relate pages in different languages</a></h3>
        <p>In the old version, to setup multiple versions of the same page in individual
        files, you had to follow some strict instructions:</p>
        <ul>
        <li>All files must be in the same folder.</li>
        <li>They must have the same name, suffixed with the language.</li>
        </ul>
        <p>For example:</p>
        <pre><code>- /about-me_en.md
        - /about-me_gl.md
        </code></pre>
        <p>The new plugin removes this behavior. You have to use the <code>id</code> variable to
        relate different pages.</p>
        <p>For example, the english version:</p>
        <pre><code class="language-md">---
        lang: en
        url: /about-me/
        id: about
        ---
        
        # About me
        </code></pre>
        <p>The galician version:</p>
        <pre><code class="language-md">---
        lang: gl
        url: /acerca-de-min/
        id: about
        ---
        
        # Acerca de min
        </code></pre>
        <p>The new plugin interprets these two pages as the same content but in different
        languages, because they have the same id (<code>about</code>). You don't need to have all
        files in the same folder with a specific name.</p>
        <p>See the
        <a href="https://lume.land/plugins/multilanguage/">complete plugin documentation</a>.</p>
        <h2 id="new-nav-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#new-nav-plugin" class="header-anchor">New <code>nav</code> plugin</a></h2>
        <p>The <code>nav</code> plugin builds automatically a menu of your site using the URLs to
        define the hierarchy. For example, let's say we have a site which exports the
        following pages:</p>
        <ul>
        <li><code>/</code></li>
        <li><code>/articles/</code></li>
        <li><code>/articles/first-article/</code></li>
        <li><code>/articles/second-article/chapter-1/</code></li>
        <li><code>/articles/second-article/chapter-2/</code></li>
        </ul>
        <p>This plugin register the <code>nav</code> variable in your templates, similar to
        <a href="https://lume.land/plugins/search/"><code>search</code></a> but intended for navigation stuff.
        The <code>nav</code> variable has some useful functions:</p>
        <h3 id="menu" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#menu" class="header-anchor">Menu</a></h3>
        <p>The <code>nav.menu()</code> function returns an object with the site structure, so you can
        build a tree menu:</p>
        <pre><code class="language-ts">const tree = nav.menu();
        
        console.log(tree);
        
        {
        slug: &quot;&quot;,
        data: Data,
        children: [
        {
        slug: &quot;articles&quot;,
        data: Data,
        children: [
        {
        slug: &quot;first-article&quot;,
        data: Data,
        },
        {
        slug: &quot;second-article&quot;,
        children: [
        {
        slug: &quot;chapter-1&quot;,
        data: Data,
        },
        {
        slug: &quot;chapter-2&quot;,
        data: Data,
        },
        ],
        },
        ],
        },
        ];
        }
        </code></pre>
        <ul>
        <li>The <code>data</code> property contains the page data object. So you can access to any
        page variable like <code>data.title</code> or <code>data.url</code>.</li>
        <li>The item with the slug <code>second-article</code> doesn't have the <code>data</code> value because
        there isn't any page with the url <code>/articles/second-article/</code>. Note that there
        are pages inside this url (<code>/articles/second-page/chapter-1/</code> and
        <code>/articles/second-page/chapter-2/</code>) that do have the <code>data</code> value.</li>
        </ul>
        <h3 id="breadcrumb" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#breadcrumb" class="header-anchor">Breadcrumb</a></h3>
        <p>The <code>nav.breadcrumb()</code> function returns all parent pages of a specific page. For
        example:</p>
        <pre><code class="language-ts">const breadcrumb = nav.breadcrumb(&quot;/articles/second-article/chapter-2/&quot;);
        
        console.log(breadcrumb);
        
        [
        {
        slug: &quot;chapter-2&quot;,
        data: Data,
        },
        {
        slug: &quot;second-article&quot;,
        children: ...
        },
        {
        slug: &quot;articles&quot;,
        data: Data,
        children: ...
        },
        {
        slug: &quot;&quot;,
        data: Data,
        children: ...
        },
        ]
        </code></pre>
        <p>You can see an example of the nav plugin in the
        <a href="https://lumeland.github.io/theme-simple-wiki/posts/firstpost/">Simple Wiki theme</a>.</p>
        <ul>
        <li>The lateral menu is built with <code>nav.menu()</code>
        (<a href="https://github.com/lumeland/theme-simple-wiki/blob/main/src/_includes/templates/menu.njk">see the code</a>)</li>
        <li>The breadcrumb above the title is built with <code>nav.breadcrumb()</code>
        (<a href="https://github.com/lumeland/theme-simple-wiki/blob/main/src/_includes/templates/breadcrumb.njk">see the code</a>)</li>
        </ul>
        <p>See the <a href="https://lume.land/plugins/nav/">plugin documentation</a> for more details.</p>
        <h2 id="new-copyremainingfiles-function" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#new-copyremainingfiles-function" class="header-anchor">New <code>copyRemainingFiles</code> function</a></h2>
        <p>Until now, the only way to copy static files was using the <code>site.copy()</code>
        function, that allows to specify a file/folder or an array of extensions. This
        works fine if you know in advance all files that must be copied, because they
        are in a specific folder like <code>/static</code> or have a known extension (<code>.jpg</code>,
        <code>.png</code>, etc).</p>
        <p>But it's not practical when your static files are distributed in random folders
        or can have any extension. For example, imagine you have a website with
        articles, and every article is stored in it's folder that can contain static
        files of any extension:</p>
        <pre><code>|_ articles/
        |_ article-1/
        |   |_ index.md
        |   |_ picture.jpg
        |   |_ document.pdf
        |   |_ foo32.gif
        |_ article-2/
        |_ index.md
        |_ journey.mp4
        |_ download.zip
        </code></pre>
        <p>The <code>site.copy()</code> function it's not very helpful because if we copy the
        <code>/articles/</code> folder, the <code>index.md</code> files won't be processed (they will be
        treated as static files). We can select the files by extension with
        <code>site.copy([&quot;.jpg&quot;, &quot;.pdf&quot;, &quot;.gif&quot;, &quot;.mp4&quot;, &quot;.zip&quot;])</code> but every time a new
        extension is uploaded, we have to remember to include it in the <code>_config</code> file.</p>
        <p>The <code>copyRemainingFiles()</code> basically says: <strong>when you find a file and don't know
        what to do, just copy it.</strong> You can include a function to filter which files
        will be copied. For example:</p>
        <pre><code class="language-ts">site.copyRemainingFiles((path: string) =&gt; path.startsWith(&quot;/articles/&quot;));
        </code></pre>
        <p>Now, only the remaining files inside the <code>/articles/</code> folder will be copied.</p>
        <p>More info
        <a href="https://lume.land/docs/configuration/copy-static-files/#copy-remaining-files">in the documentation site</a>.</p>
        <h2 id="page.data.children-property" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.16.0-release-notes/#page.data.children-property" class="header-anchor"><code>page.data.children</code> property</a></h2>
        <p>Let's say you have a blog and want to list all posts with their content. It's
        possible with this code:</p>
        <pre><code class="language-njk">{% for post in search.pages(&quot;type=post&quot;) %}
        &lt;h1&gt;{{ post.data.title }}&lt;/h1&gt;
        {{ post.data.content | md | safe }}
        {% endfor %}
        </code></pre>
        <p>If the post are written in Markdown, the variable <code>post.data.content</code> of the
        page has the unrendered markdown code, so you have to use the <code>md</code> filter to
        render it to HTML. This has the drawback of every post need to be rendered
        twice, one to build the post page and other to build this list of posts.</p>
        <p>If your posts are in <code>MDX</code> this is even worse, because there's no filter to
        convert <code>mdx</code> code to HTML. It's possible to get the rendered content of the
        page from <code>post.content</code> but it includes not only the HTML of the post but also
        the layout used in this page.</p>
        <p>As of version 1.16, Lume will save the rendered content into the <code>children</code>
        property, so you can use it in other pages in this way:</p>
        <pre><code class="language-njk">{% for post in search.pages(&quot;type=post&quot;) %}
        &lt;h1&gt;{{ post.data.title }}&lt;/h1&gt;
        {{ post.data.children | safe }}
        {% endfor %}
        </code></pre>
        <p>The content will be rendered only once and no filter is needed.</p>
        <p>There are more interesting things in Lume v1.16.0. See the
        <a href="https://github.com/lumeland/lume/blob/v1.16.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Tue, 21 Mar 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.15.0 - Release notes</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>The version <strong>1.15.0</strong> is full of exciting new features.</p>
        <!-- more -->
        <h2 id="archetypes" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/#archetypes" class="header-anchor">Archetypes</a></h2>
        <p><a href="https://gohugo.io/content-management/archetypes/">Hugo has a nice feature called <strong>archetypes</strong></a>,
        templates used when creating new content. The most obvious example is a post:
        instead of creating a new markdown file from scratch everytime you want to
        create a new post, you can run an archetype that creates the post file for you
        with a preconfigured front matter and content.</p>
        <p>In Lume, an archetype is just a JavaScript or TypeScript file that export a
        function returning an object with the file path and the file content. The
        archetype must be saved in the <code>_archetypes</code> directory, inside the <code>src</code> folder.
        For example:</p>
        <pre><code class="language-ts">// _archetypes/example.js
        
        export default function () {
        return {
        path: &quot;/pages/example.md&quot;,
        content: &quot;Content of the file&quot;,
        };
        }
        </code></pre>
        <p>The archetypes are invoked with the command
        <code>deno task lume new [archetype-name]</code> (or <code>lume new [archetype-name]</code> with the
        new <a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/lume-cli.md">Lume CLI</a>). If you run <code>lume new example</code> to run this
        archetype, the file <code>/pages/example.md</code> will be created.</p>
        <p>See the <a href="https://lume.land/docs/core/archetypes/">archetypes documentation</a> to
        learn more about how to generate different formats, pass arguments or create
        multiple files.</p>
        <h2 id="tailwindcss" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/#tailwindcss" class="header-anchor">Tailwindcss</a></h2>
        <p><a href="https://tailwindcss.com/">Tailwind</a> support is a recurring request for Lume.
        Until now it was not possible to use Tailwind in Deno, so the only alternative
        available was <a href="https://lume.land/plugins/windi_css/">Windi CSS</a>.</p>
        <p>The support of <code>npm:</code> packages in Deno allowed to use many NPM packages that
        until now only work on Node. Still, there were errors in Tailwind due the
        <a href="https://www.npmjs.com/package/acorn-node"><code>acorn-node</code></a> dependency that doesn't
        work on Deno.</p>
        <p>The <a href="https://www.npmjs.com/search?q=%40lumeland"><code>@lumeland</code></a> organization in
        NPM contains modified versions of the packages that don't work in Deno.
        <a href="https://www.npmjs.com/package/@lumeland/tailwindcss"><code>@lumeland/tailwindcss</code></a>
        is the same code as <a href="https://www.npmjs.com/package/tailwindcss"><code>tailwindcss</code></a>
        but replacing that dependency. When this is fixed in the official library, this
        modified version will be deprecated.</p>
        <p>The Tailwindcss plugin depends on <code>postcss</code>, so you need to use both plugins in
        this exact order:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import tailwind from &quot;lume/plugins/tailwindcss.ts&quot;;
        import postcss from &quot;lume/plugins/postcss.ts&quot;;
        
        const site = lume();
        
        site.use(tailwind());
        site.use(postcss());
        
        export default site;
        </code></pre>
        <h2 id="context-data" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/#context-data" class="header-anchor">Context data</a></h2>
        <p>The function <code>site.data()</code> allows to insert arbitrary data in your site from the
        <code>_config.ts</code> file:</p>
        <pre><code class="language-ts">site.data(&quot;layout&quot;, &quot;main.njk&quot;);
        </code></pre>
        <p>The context of this data is global: is available to all pages of the site. It's
        equivalent to having a <code>_data.*</code> file in the root of your site. As of Lume
        1.15.0, it's possible to specify the directory of the data in the third
        argument, for example:</p>
        <pre><code class="language-ts">site.data(&quot;layout&quot;, &quot;main.njk&quot;, &quot;/posts&quot;);
        </code></pre>
        <p>Now, the <code>layout</code> value is available only to the pages inside the <code>/posts</code>
        directory. Equivalent to creating a <code>/posts/_data.yml</code> file with this value.</p>
        <p>You can assign data not only to directories but also to specific files:</p>
        <pre><code class="language-ts">site.data(&quot;layout&quot;, &quot;main.njk&quot;, &quot;/posts/hello-world.md&quot;);
        </code></pre>
        <h2 id="%F0%9F%92%A3-breaking-changes-in-the-plugin-date" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/#%F0%9F%92%A3-breaking-changes-in-the-plugin-date" class="header-anchor">💣 Breaking changes in the plugin <code>date</code></a></h2>
        <p>The <code>date</code> plugin use the
        <a href="https://deno.land/x/date_fns@v2.15.0">Deno version of <code>date_fns</code></a> to transform
        the dates. That version wasn't updated in 2 years so I decided to switch to
        <a href="https://www.npmjs.com/package/date-fns">the Node version</a>. Everything should
        work fine, the only difference is the locales configuration, that need to be
        imported from npm in the _config file. For example, if you have this
        configuration:</p>
        <pre><code class="language-ts">site.use(date({
        locales: [&quot;gl&quot;, &quot;pt&quot;],
        }));
        </code></pre>
        <p>You need to change it to:</p>
        <pre><code class="language-ts">import gl from &quot;npm:date-fns/locale/gl/index.js&quot;;
        import pt from &quot;npm:date-fns/locale/pt/index.js&quot;;
        
        //...
        site.use(date({
        locales: { gl, pt },
        }));
        </code></pre>
        <h2 id="other-changes" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.15.0-release-notes/#other-changes" class="header-anchor">Other changes</a></h2>
        <ul>
        <li>The <code>sass</code> plugin uses now a
        <a href="https://www.npmjs.com/package/@lumeland/sass">modified version</a> of the
        official NPM package.</li>
        <li>The <code>relations</code> plugin has been improved and there are some breaking changes
        in the configuration API.
        <a href="https://lume.land/plugins/relations/">See the plugin page</a> for the updated
        documentation.</li>
        <li>Dependency update and bugfixes.</li>
        </ul>
        <p>See the
        <a href="https://github.com/lumeland/lume/blob/v1.15.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Tue, 10 Jan 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Lume CLI</title>
      <link>https://aoba-test.netlify.app/posts/lume-cli/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-cli/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>Happy new year, Lumers!</p>
        <p>2022 was a great year for Lume, it reached to 1K stars in GitHub and many of you
        have collaborated in form of pull requests, promoting Lume in your blogs and
        social networks or
        <a href="https://github.com/sponsors/oscarotero/">even sponsoring me</a>. I want to thank
        you and promise to keep working hard to make Lume even better.</p>
        <p>🔥🔥🔥🔥🔥🔥🔥🔥🔥</p>
        <!-- more -->
        <h2 id="introducing-lume-cli" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-cli/#introducing-lume-cli" class="header-anchor">Introducing Lume CLI</a></h2>
        <p>The best way to run Lume is using the Deno tasks. It's the most portable way to
        run Lume without installing anything else but Deno, and it ensures that the Lume
        version is the same as specified in the <code>import_map.json</code> file. In fact,
        <a href="https://github.com/lumeland/lume/issues/232">there's a plan to remove the CLI interface</a>
        completely.</p>
        <p>The only drawback of using Deno tasks is they are more verbose to type. Instead
        of simply running <code>lume -s</code> or <code>lume run my-script</code> you have to type
        <code>deno task lume -s</code> and <code>deno task lume run my-script</code>.</p>
        <p>In order to keep using tasks to run Lume and, at the same time, having a more
        ergonomic way to run the commands, I have released the new
        <a href="https://deno.land/x/lume_cli">Lume CLI</a>.</p>
        <p>To install it, just run:</p>
        <pre><code>deno install --allow-run --name lume --force --reload https://deno.land/x/lume_cli/mod.ts
        </code></pre>
        <p>Lume CLI is just a small script to add the <code>deno task</code> words at the beginning of
        your lume commands. For example, if you run <code>lume -s</code>, the CLI will run
        <code>deno task lume -s</code>.</p>
        <p>It's an independent module, separated from the Lume repository, so it's up to
        you to use it or not.</p>
        <p>It also includes two additional commands:</p>
        <ul>
        <li><code>lume init</code>: To initialise Lume in the current directory. It's like running
        <code>deno run -Ar https://deno.land/x/lume/init.ts</code>.</li>
        <li><code>lume ugrade-cli</code>: As you may guess, it will upgrade the Lume CLI to the
        latest version.</li>
        </ul>
        <p>Lume CLI combines the best of the two worlds and opens the door to removing the
        old CLI interface in the Lume repo sometime soon.</p>
        ]]>
      </content:encoded>
      <pubDate>Fri, 06 Jan 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.14.0 is out</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.14.0-release/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.14.0-release/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>Lume <code>1.14.0</code> was released. This is a list of the main changes and new features.</p>
        <!-- more -->
        <h2 id="new-functions-to-(pre)process-all-pages-at-the-same-time" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#new-functions-to-(pre)process-all-pages-at-the-same-time" class="header-anchor">New functions to (pre)process all pages at the same time</a></h2>
        <p>The functions <code>site.process()</code> and <code>site.preprocess()</code> are used to modify pages
        after or before rendering. For example, to process the HTML pages, you can do:</p>
        <pre><code class="language-js">site.process([&quot;.html&quot;], (page) =&gt; my_processor(page));
        </code></pre>
        <p>This callback is executed once per page, so if you have 200 pages, the callback
        is executed 200 times.</p>
        <p>This is great to transform pages individually, but sometimes it's better to run
        the function only once to all pages at the same time. Two new functions were
        added for this purpose: <code>processAll()</code> and <code>preprocessAll()</code>. They are similar
        to <code>process()</code> and <code>preprocess()</code> but will receive all matched pages in the
        first argument:</p>
        <pre><code class="language-js">site.processAll([&quot;.html&quot;], (pages) =&gt; {
        pages.forEach((page) =&gt; my_processor(page));
        console.log(`Processed ${pages.length} HTML pages!`);
        });
        </code></pre>
        <p>In previous versions, the only way to do something like that was through events
        like <code>afterRender</code>, <code>beforeRender</code>, <code>beforeSave</code>, etc. The advantage of using
        the new <code>processAll</code> and <code>preprocessAll</code> is they respect the order of the other
        processors:</p>
        <pre><code class="language-js">site.process([&quot;.html&quot;], first_processor);
        site.processAll([&quot;.html&quot;], second_processor);
        site.process([&quot;.html&quot;], third_processor);
        </code></pre>
        <p>In this example, <code>second_processor</code> is run after <code>first_processor</code> and before
        <code>third_processor</code>.</p>
        <h2 id="introducing-hooks" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#introducing-hooks" class="header-anchor">Introducing <code>hooks</code></a></h2>
        <p>Hooks are functions registered by some plugins that can be invoked by other
        plugins or by yourself in the <code>_config</code> file. Hooks are stored in <code>site.hooks</code>
        and are useful to change a plugin configuration after the installation. For
        example, the <code>postcss</code> plugin sets the hook <code>addPostcssPlugin</code>. You can create a
        Lume plugin to, for example, minify the css code with
        <a href="https://cssnano.co/">CSS Nano</a>:</p>
        <pre><code class="language-js">import cssnano from &quot;npm:cssnano@5.1.14&quot;;
        
        export default function () {
        return (site) =&gt; {
        if (!site.hooks.addPostcssPlugin) {
        throw new Error(&quot;This plugin depends on postcss&quot;);
        }
        
        site.hooks.addPostcssPlugin(cssnano);
        };
        }
        </code></pre>
        <p>Now, you can use this plugin in the <code>_config.ts</code> file:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import postcss from &quot;lume/plugins/postcss.ts&quot;;
        import nanocss from &quot;./plugins/nanocss.ts&quot;;
        
        const site = lume();
        
        site.use(postcss());
        site.use(nanocss());
        
        export default site;
        </code></pre>
        <h2 id="support-for-splitting-mode-for-esbuild" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#support-for-splitting-mode-for-esbuild" class="header-anchor">Support for <code>splitting</code> mode for esbuild</a></h2>
        <p><a href="https://esbuild.github.io/api/#splitting">Code splitting</a> is a bundle technique
        that creates separate files with common code shared by multiple entry points.
        For example, if both entry points <code>a.ts</code> and <code>b.ts</code> imports <code>c.ts</code>, instead of
        including the <code>c.ts</code> code in both files (which would be duplicated), the code is
        saved into a <em>chunk</em> file that is imported by both files.</p>
        <p>To generate the <em>chunk</em> files, we need to know all entry points first. But
        thanks to the implementation of <code>processAll()</code> function (previously explained)
        this is now possible in Lume. To enable the splitting mode, just need to
        configure the esbuild plugin in this way:</p>
        <pre><code class="language-js">site.use(esbuild({
        options: {
        splitting: true,
        },
        }));
        </code></pre>
        <h2 id="improved-metas-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#improved-metas-plugin" class="header-anchor">Improved <code>metas</code> plugin</a></h2>
        <p>A couple of improvements have been added to <code>metas</code>:</p>
        <h3 id="no-need-for-mergedkeys" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#no-need-for-mergedkeys" class="header-anchor">No need for <code>mergedKeys</code></a></h3>
        <p>The <code>metas</code> plugin needs a <code>mergedKeys</code> to customise the merging mode of the
        <code>metas</code> key:</p>
        <pre><code class="language-yml">metas:
        site: Site title
        icon: /img/icon.png
        lang: en
        
        # Customise the merging mode of &quot;metas&quot;
        mergedKeys:
        metas: object
        </code></pre>
        <p>You no longer need to add this value manually. The plugin inserts it
        automatically for you.</p>
        <h3 id="field-aliases" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#field-aliases" class="header-anchor">Field aliases</a></h3>
        <p>Field aliases are the new way to reuse a value in the <code>metas</code>. For example:</p>
        <pre><code class="language-yml">title: This is the title
        
        metas:
        title: &quot;=title&quot; # Alias to the title value
        </code></pre>
        <p>Any value starting with <code>=</code> is considered an alias to another field. You can use
        dots for subvalues:</p>
        <pre><code class="language-yml">title: This is the title
        intro:
        text: Page description
        metas:
        title: &quot;=title&quot;
        description: &quot;=intro.text&quot;
        </code></pre>
        <p>Field aliases are way more powerful than the <code>defaultPageData</code> option of the
        plugin, which <strong>is deprecated and will be removed in the future</strong>.</p>
        <ul>
        <li>Field aliases supports subvalues.</li>
        <li>They can be configured at page or folder level with <code>_data</code> files.</li>
        </ul>
        <h2 id="changes-to-prism-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#changes-to-prism-plugin" class="header-anchor">Changes to <code>prism</code> plugin</a></h2>
        <p>The <a href="https://lume.land/plugins/prism/">prism plugin</a> now loads the
        <a href="https://prismjs.com/">Prism</a> library from <code>npm:</code>. This change removes the
        <code>languages</code> option so if you need to load additional languages, you have to
        import them in your <code>_config.ts</code> file:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import prism from &quot;lume/plugins/prism.ts&quot;;
        
        // Additional prism languages
        import &quot;npm:prismjs@1.29.0/components/prism-less.js&quot;;
        import &quot;npm:prismjs@1.29.0/components/prism-git.js&quot;;
        
        const site = lume();
        site.use(prism());
        
        export default site;
        </code></pre>
        <p>The good news is you can also <a href="https://prismjs.com/#plugins">load plugins</a>.</p>
        <h2 id="new-plugin-filter_pages" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.14.0-release/#new-plugin-filter_pages" class="header-anchor">New plugin <code>filter_pages</code></a></h2>
        <p>This plugin is the first step to deprecate the <code>--dev</code> mode of Lume (that
        ignores the pages with <code>draft=true</code>). The new plugin <code>filter_pages</code> filters
        pages using a callback and provides more flexibility. For example, let's say you
        want to ignore the <code>draft</code> pages in the production environment:</p>
        <pre><code class="language-ts">import lume from &quot;lume/mod.ts&quot;;
        import filter_pages from &quot;lume/plugins/filter_pages.ts&quot;;
        
        const site = lume();
        const isProd = Deno.env.get(&quot;DENO_ENV&quot;) === &quot;prod&quot;;
        
        site.use(filter_pages({
        fn: (page) =&gt; !isProd || !page.data.draft,
        }));
        
        export default site;
        </code></pre>
        <p>See the
        <a href="https://github.com/lumeland/lume/blob/v1.14.0/CHANGELOG.md">CHANGELOG.md file</a>
        for the full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Mon, 12 Dec 2022 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>How to use the &quot;on demand&quot; plugin in November 2022</title>
      <link>https://aoba-test.netlify.app/posts/ondemand-plugin-november-2022/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/ondemand-plugin-november-2022/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>The <a href="https://lume.land/plugins/on_demand/"><code>on_demand</code> plugin</a> is the attempt of
        Lume to provide some server-side rendering behaviour to a static site. The idea
        is simple: omit some pages in the build process (with <code>ondemand: true</code>) in order
        to build them when they are requested.</p>
        <!-- more -->
        <p>This allows insert dynamic content in the pages like
        <a href="https://lume-ondemand.deno.dev/">in this example</a>, a site with the pages
        showing the current time. You can see the
        <a href="https://github.com/lumeland/test-lume-ondemand">code repository</a>, where the
        current time is defined as a
        <a href="https://github.com/lumeland/test-lume-ondemand/blob/0ea72e6449cd7e6d5ca7013d2a2b0ca0d5e3f5a5/_config.ts#L8">helper in the <code>_config.ts</code> file</a>
        and then
        <a href="https://github.com/lumeland/test-lume-ondemand/blob/0ea72e6449cd7e6d5ca7013d2a2b0ca0d5e3f5a5/_includes/layout.njk#L14">called in the Nunjucks layout</a>
        used by both pages.</p>
        <p>This plugin was tested only in Deno Deploy but it should work on any hosting
        with Deno. But it is not all rosy in the garden, because Deno Deploy has some
        limitations that makes more difficult to use this plugin, compared with the Deno
        CLI that you have installed locally:</p>
        <h2 id="no-support-for-dynamic-imports" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/ondemand-plugin-november-2022/#no-support-for-dynamic-imports" class="header-anchor">No support for dynamic imports</a></h2>
        <p>One of the
        <a href="https://github.com/denoland/deploy_feedback/issues/1">most requested features</a>
        in Deno Deploy is the ability to import modules dynamically. One year and half
        since the issue was created, it's still not possible and looks like it won't be
        in the short term. Lume uses dynamic imports to load pages and data in
        JavaScript, JSX and TypeScript, so if your on demand pages use any of these
        formats, they will fail on Deno Deploy. The only way to skip this limitation is
        by generating a file that imports statically all files that, under normal
        conditions, would be imported dynamically (this file is generated automatically
        <a href="https://lume.land/plugins/on_demand/#preload-modules">by the ondemand plugin</a>).
        It's not an elegant solution but it's the only solution that works at this
        moment.</p>
        <h2 id="no-support-for-npm-modules" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/ondemand-plugin-november-2022/#no-support-for-npm-modules" class="header-anchor">No support for NPM modules</a></h2>
        <p>As of version 1.12.0, Lume uses <code>npm:</code> modules for some dependencies. NPM
        especifiers
        <a href="https://github.com/denoland/deploy_feedback/issues/314">are not yet supported in Deno Deploy</a>.
        Fortunately we can use import maps to use the esm.sh version of the NPM
        packages. In the repository of the plugin demo, you can
        <a href="https://github.com/lumeland/test-lume-ondemand/blob/0ea72e6449cd7e6d5ca7013d2a2b0ca0d5e3f5a5/import_map.json">see the import_map.json file</a>
        needed to map all NPM lume dependencies to the esm.sh equivalent.</p>
        <p>And this is the state of the dynamic pages in Lume for now. I hope these
        limitations disappear in the short term (I guess NPM modules will be supported
        soon). If you know of other hosting providers with Deno support and you get the
        <code>on demand</code> plugin to work there, please, let me know.</p>
        ]]>
      </content:encoded>
      <pubDate>Tue, 22 Nov 2022 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Lume 1.13.0 is out</title>
      <link>https://aoba-test.netlify.app/posts/lume-1.13.0-release/</link>
      <guid isPermaLink="false">https://aoba-test.netlify.app/posts/lume-1.13.0-release/</guid>
      <description/>
      <content:encoded>
        <![CDATA[<p>I'm happy to announce that Lume <code>1.13.0</code> was released with some interesting
        additions and changes. Let's see the highlights.</p>
        <!-- More -->
        <h2 id="mdx-support" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#mdx-support" class="header-anchor">MDX support</a></h2>
        <p><a href="https://mdxjs.com/">MDX</a> support for Lume was requested for a long time. Now
        that Deno can handle <code>npm</code> imports, it's more easy to bring support for this
        library. The new <code>mdx</code> plugin allows to create your pages in <code>.mdx</code>, so you can
        combine markdown and JSX components in a single file.</p>
        <p>To enable MDX in your site, you only need to import the <code>mdx</code> plugin and any of
        the JSX plugins available (<code>jsx</code> to use React, <code>jsx_preact</code> to use Preact). This
        is an example with Preact:</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        import jsx from &quot;lume/plugins/jsx_preact.ts&quot;;
        import mdx from &quot;lume/plugins/mdx.ts&quot;;
        
        const site = lume();
        
        site.use(jsx());
        site.use(mdx());
        
        export default site;
        </code></pre>
        <p>Now you can create <code>.mdx</code> files that imports JSX components or use the Lume's
        components from the global <code>comp</code> variable:</p>
        <pre><code class="language-md">---
        title: Hello world
        description: This is a description
        ---
        
        import Image from &quot;./_includes/Image.tsx&quot;;
        
        &lt;comp.Header title={title} description={description}/&gt;
        
        ## Hello world
        
        This is a markdown file with the title **{ title }**.
        
        &lt;Image alt=&quot;foo&quot; /&gt;
        </code></pre>
        <p><a href="https://lume.land/plugins/mdx/">See more info in the documentation</a></p>
        <h2 id="new-sitemap-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#new-sitemap-plugin" class="header-anchor">New <code>sitemap</code> plugin</a></h2>
        <p>The <code>sitemap</code> plugin was created by <a href="https://github.com/jrson83">Jrson</a> some
        time ago in the
        <a href="https://github.com/lumeland/experimental-plugins">experimental plugins repo</a>.
        It creates a <code>sitemap.xml</code> file and a <code>robots.txt</code> file with a link to the
        sitemap file.</p>
        <p>This plugin is now included in Lume 1.13.0, so you can import it via
        <code>lume/plugins/sitemap.ts</code>.</p>
        <p><a href="https://lume.land/plugins/sitemap/">See more info in the documentation</a></p>
        <h2 id="improved-the-multilanguage-plugin" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#improved-the-multilanguage-plugin" class="header-anchor">Improved the <code>multilanguage</code> plugin</a></h2>
        <p>The <code>multilanguage</code> plugin allows to create multiple language versions of the
        same page. In Lume <code>v1.13.0</code> it's possible to save the language versions in
        different files. To be identified by the plugin as language versions of the same
        page, the files must fulfill the following requirements:</p>
        <ul>
        <li>They must be saved in the same directory.</li>
        <li>They must have the <code>lang</code> variable defined.</li>
        <li>They must have the same filename ending with the <code>_[lang]</code> suffix.</li>
        </ul>
        <p>For example:</p>
        <pre><code>|_ /posts
        |_ /my-first-post_en.md
        |_ /my-first-post_es.md
        </code></pre>
        <p>These two files contains the same post but in different languages and Lume will
        generate the pages <code>/en/posts/my-first-post/</code> and <code>/es/posts/my-first-post/</code>.</p>
        <p>It's possible to have one page without the language suffix, useful if you
        already have a site with only one language and want to add other languages
        progressively without affeting to the existing urls. For example:</p>
        <pre><code>|_ /posts
        |_ /my-first-post.md
        |_ /my-first-post_es.md
        </code></pre>
        <p>In this case, Lume detects they are the same posts but the URLs generated are
        <code>/posts/my-first-post/</code> and <code>/es/posts/my-first-post/</code>.</p>
        <h2 id="deprecated-page.dest-and-page.updatedest" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#deprecated-page.dest-and-page.updatedest" class="header-anchor">Deprecated <code>page.dest</code> and <code>page.updateDest</code></a></h2>
        <p>All pages in Lume have the property <code>dest</code> with info about the destination file.</p>
        <p>The destination is calculated according to the <code>page.data.url</code> value (if
        defined) or the source file name. More info
        <a href="https://lume.land/docs/creating-pages/page-files/">in the Lume docs</a>.</p>
        <p>The problem is whenever the URL of a page is changed, it's necessary to change
        the value in two places, <code>page.data.url</code> and <code>page.dest</code>. For example, a SASS
        plugin that modifies the extension of the files from <code>.scss</code> to <code>.css</code>:</p>
        <pre><code class="language-js">// Extremely simplified code:
        site.process([&quot;.scss&quot;], (page) =&gt; {
        page.content = processSASS(page.content);
        
        // Change the page URL
        page.data.url = page.data.url.replace(/\.scss$/, &quot;.css&quot;);
        
        // Change the destination extension
        page.dest.ext = &quot;.css&quot;;
        });
        </code></pre>
        <p>There's the <code>page.updateDest</code> function that changes the <code>page.dest</code> and
        <code>page.data.url</code> values accordingly, ensuring both properties are consistent:</p>
        <pre><code class="language-js">// Extremely simplified code:
        site.process([&quot;.scss&quot;], (page) =&gt; {
        page.content = processSASS(page.content);
        
        // Change the page URL and destination
        page.updateDest({ ext: &quot;.css&quot; });
        });
        </code></pre>
        <p>I never felt confortable with this, because it's duplicating the same value in
        two different places. Originally it has been created in this way because they
        have different purposes and they can have different values (like a page with the
        url <code>/about-us/</code> but the destination file is <code>/about-us/index.html</code>).</p>
        <p>In Lume 1.13.0 the <code>page.dest</code> and <code>page.updateDest</code> are deprecated (and
        probably removed in 1.14.0). Now you only have to change the value in one place:
        <code>page.data.url</code>.</p>
        <p>More simple and intuitive.</p>
        <h2 id="new-option-returnpagedata-to-search-helper" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#new-option-returnpagedata-to-search-helper" class="header-anchor">New option <code>returnPageData</code> to <code>search</code> helper</a></h2>
        <p>The global helper <code>search.pages()</code> returns an array of pages. But in most cases
        you don't need the page instance, only its data. The new <code>returnPageData</code> option
        allows to change this behavior to return only the <code>page.data</code> object. This will
        be the default behavior in Lume 2.0, but for compatibility it's disabled by
        default. See
        <a href="https://github.com/lumeland/lume/issues/251">more info in this issue</a>.</p>
        <p>To enable it, just configure the plugin in the <code>_config.ts</code> file.</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        
        const search = { returnPageData: true };
        
        const site = lume({}, { search });
        
        export default site;
        </code></pre>
        <p>Once configured, the following code:</p>
        <pre><code class="language-liquid">{% for article in search.pages(&quot;type=article&quot;, &quot;date=desc&quot;) %} 
        &lt;a href=&quot;{{ article.data.url }}&quot;&gt;
        &lt;h1&gt;{{ article.data.title }}&lt;/h1&gt;
        &lt;/a&gt;
        {% endfor %}
        </code></pre>
        <p>needs to be changed to:</p>
        <pre><code class="language-liquid">{% for article in search.pages(&quot;type=article&quot;, &quot;date=desc&quot;) %} 
        &lt;a href=&quot;{{ article.url }}&quot;&gt;
        &lt;h1&gt;{{ article.title }}&lt;/h1&gt;
        &lt;/a&gt;
        {% endfor %}
        </code></pre>
        <h2 id="removed-no-html-extension-option-for-prettyurls" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#removed-no-html-extension-option-for-prettyurls" class="header-anchor">Removed <code>no-html-extension</code> option for prettyUrls</a></h2>
        <p>Pretty URLs configuration allowed the <code>no-html-extension</code> value. It exports the
        page as regular html (like <code>/article.html</code>) but the url of these pages are
        <code>/article</code> (without extension). You can see more info
        <a href="https://github.com/lumeland/lume/issues/193">in this issue</a>.</p>
        <p>This option was removed in Lume 1.13.0 because it's not needed. If you want this
        functionality, just use the <code>modify_urls</code> plugin to remove the extension to the
        HTML links:</p>
        <pre><code class="language-js">import lume from &quot;lume/mod.ts&quot;;
        import modifyUrls from &quot;lume/plugins/modify_urls.ts&quot;;
        
        const site = lume({
        prettyUrls: false, //To export the pages as example.html
        });
        
        site.use(modifyUrls({
        fn: (url) =&gt; url.replace(/\.html$/, &quot;&quot;),
        }));
        
        export default site;
        </code></pre>
        <h2 id="new-emptydest-option" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#new-emptydest-option" class="header-anchor">New <code>emptyDest</code> option</a></h2>
        <p>Lume needs to load all pages in order to build the site. This may be a problem
        for large sites with 50K or more pages that cause out of memory issues.</p>
        <p>A solution is to build these large sites in several steps, creating different
        builds exporting to the same <code>dest</code> directory, so the site can be built
        incrementally. Lume automatically empty the <code>dest</code> folder before any build, so
        the new <code>emptyDest</code> option allows to change this behavior:</p>
        <pre><code class="language-ts">const site = lume({
        emptyDest: false, // Don't empty the dest folder
        });
        </code></pre>
        <h2 id="removed-timestamp-detection-in-the-filename" tabindex="-1"><a href="https://aoba-test.netlify.app/posts/lume-1.13.0-release/#removed-timestamp-detection-in-the-filename" class="header-anchor">Removed timestamp detection in the filename</a></h2>
        <p>Lume can
        <a href="https://lume.land/docs/creating-pages/page-files/#page-date">extract dates from the page's filename</a>
        (for instance <code>2022-10-02_post-title.md</code>).</p>
        <p>If there's a number (like <code>23_post-title.md</code>), it's interpreted as a timestamp.
        This behavior was removed because it's a too generical pattern
        (<a href="https://github.com/lumeland/lume/issues/284">See this issue</a>). If you need
        this feature back, you can create a preprocessor for that:</p>
        <pre><code class="language-ts">site.preprocess([&quot;.md&quot;], (page) =&gt; {
        const [date, url] = myCustomFileParse(page.data.url);
        page.data.date = date;
        page.data.url = url;
        });
        </code></pre>
        <p>See the
        <a href="https://github.com/lumeland/lume/blob/v1.13.0/CHANGELOG.md">CHANGELOG.md file</a>
        for a full list of changes.</p>
        ]]>
      </content:encoded>
      <pubDate>Wed, 16 Nov 2022 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>