123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Extending Nikola | Riff</title>
- <link href="../assets/css/all-nocdn.css" rel="stylesheet" type="text/css">
- <link rel="alternate" type="application/rss+xml" title="RSS" href="../rss.xml">
- <link rel="canonical" href="http://media.pagelibre.org/riff/site/pages/extending.html">
- <link rel="icon" href="../favicon.ico" sizes="16x16">
- <!--[if lt IE 9]><script src="../assets/js/html5.js"></script><![endif]--><meta name="author" content="The Nikola Team">
- <meta property="og:site_name" content="Riff">
- <meta property="og:title" content="Extending Nikola">
- <meta property="og:url" content="http://media.pagelibre.org/riff/site/pages/extending.html">
- <meta property="og:description" content="Version:
- 8.2.3
- Author:
- Roberto Alsina <ralsina@netmanagers.com.ar>
-
-
- Contents
-
- Available Plugin Categories
-
- Command Plugins
- TemplateSystem Plugins
- Task Plugins
- PageCompiler Plugins
- MetadataExtractor P">
- <meta property="og:type" content="article">
- <meta property="article:published_time" content="2012-03-30T23:00:00-03:00">
- </head>
- <body>
- <a href="#content" class="sr-only sr-only-focusable">Skip to main content</a>
-
- <!-- Menubar -->
-
- <div class="blog-masthead">
- <div class="container">
- <!-- This keeps the margins nice -->
- <nav class="blog-nav" role="navigation"><a href="../index.html" class="blog-nav-item">Accueil</a>
- <a href="about.html" class="blog-nav-item">About Riff</a>
- <a href="../rss.xml" class="blog-nav-item">RSS feed</a>
-
-
-
-
-
-
-
- </nav>
- </div>
- <!-- /.container -->
- </div>
- <!-- End of Menubar -->
-
- <div class="container" id="content" role="main">
- <div class="body-content">
- <div class="blog-header">
- <h1 class="blog-title">
- <a href="http://media.pagelibre.org/riff/site/">
-
- <span id="blog-title">Riff</span>
- </a>
- </h1>
- <p class="lead blog-description">Riff la radio rock</p>
-
- </div>
- <!--Body content-->
- <div class="row">
- <div class="col-sm-8 blog-main">
-
- <article class="post-text storypage" itemscope="itemscope" itemtype="http://schema.org/Article"><header><h2 class="p-name entry-title blog-post-title" itemprop="headline name"><a href="#" class="u-url">Extending Nikola</a></h2>
-
-
-
- </header><div class="e-content entry-content" itemprop="articleBody text">
- <dl class="docinfo simple">
- <dt class="version">Version<span class="colon">:</span>
- </dt>
- <dd class="version">8.2.3</dd>
- <dt class="author">Author<span class="colon">:</span>
- </dt>
- <dd class="author"><p>Roberto Alsina <<a class="reference external" href="mailto:ralsina@netmanagers.com.ar">ralsina@netmanagers.com.ar</a>></p></dd>
- </dl>
- <nav class="contents alert alert-primary float-md-right" id="contents" role="doc-toc"><p class="topic-title">Contents</p>
- <ul class="simple">
- <li>
- <p><a class="reference internal" href="extending.html#available-plugin-categories" id="toc-entry-1">Available Plugin Categories</a></p>
- <ul>
- <li><p><a class="reference internal" href="extending.html#command-plugins" id="toc-entry-2">Command Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#templatesystem-plugins" id="toc-entry-3">TemplateSystem Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#task-plugins" id="toc-entry-4">Task Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#pagecompiler-plugins" id="toc-entry-5">PageCompiler Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#metadataextractor-plugins" id="toc-entry-6">MetadataExtractor Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#restextension-plugins" id="toc-entry-7">RestExtension Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#markdownextension-plugins" id="toc-entry-8">MarkdownExtension Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#signalhandler-plugins" id="toc-entry-9">SignalHandler Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#configplugin-plugins" id="toc-entry-10">ConfigPlugin Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#commentsystem-plugins" id="toc-entry-11">CommentSystem Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#shortcode-plugins" id="toc-entry-12">Shortcode Plugins</a></p></li>
- <li><p><a class="reference internal" href="extending.html#postscanner-plugins" id="toc-entry-13">PostScanner Plugins</a></p></li>
- </ul>
- </li>
- <li><p><a class="reference internal" href="extending.html#plugin-index" id="toc-entry-14">Plugin Index</a></p></li>
- <li><p><a class="reference internal" href="extending.html#path-link-resolution-mechanism" id="toc-entry-15">Path/Link Resolution Mechanism</a></p></li>
- <li><p><a class="reference internal" href="extending.html#template-hooks" id="toc-entry-16">Template Hooks</a></p></li>
- <li>
- <p><a class="reference internal" href="extending.html#shortcodes" id="toc-entry-17">Shortcodes</a></p>
- <ul>
- <li><p><a class="reference internal" href="extending.html#template-based-shortcodes" id="toc-entry-18">Template-based Shortcodes</a></p></li>
- </ul>
- </li>
- <li><p><a class="reference internal" href="extending.html#state-and-cache" id="toc-entry-19">State and Cache</a></p></li>
- <li><p><a class="reference internal" href="extending.html#logging" id="toc-entry-20">Logging</a></p></li>
- <li><p><a class="reference internal" href="extending.html#template-and-dependency-injection" id="toc-entry-21">Template and Dependency Injection</a></p></li>
- </ul></nav><p class="lead">Nikola is extensible. Almost all its functionality is based on plugins,
- and you can add your own or replace the provided ones.</p>
- <p>Plugins consist of a metadata file (with <code class="docutils literal">.plugin</code> extension) and
- a Python module (a <code class="docutils literal">.py</code> file) or package (a folder containing
- a <code class="docutils literal">__init__.py</code> file.</p>
- <p>To use a plugin in your site, you just have to put it in a <code class="docutils literal">plugins</code>
- folder in your site.</p>
- <p>Plugins come in various flavours, aimed at extending different aspects
- of Nikola.</p>
- <section id="available-plugin-categories"><h2><a class="toc-backref" href="extending.html#toc-entry-1" role="doc-backlink">Available Plugin Categories</a></h2>
- <section id="command-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-2" role="doc-backlink">Command Plugins</a></h3>
- <p>When you run <code class="docutils literal">nikola <span class="pre">--help</span></code> you will see something like this:</p>
- <pre class="code console"><a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-1"></a><span class="gp">$</span> nikola <span class="nb">help</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-2"></a><span class="go">Nikola is a tool to create static websites and blogs. For full documentation and more</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-3"></a><span class="go">information, please visit https://getnikola.com/</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-4"></a>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-5"></a>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-6"></a><span class="go">Available commands:</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-7"></a><span class="go">nikola auto automatically detect site changes, rebuild</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-8"></a><span class="go"> and optionally refresh a browser</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-9"></a><span class="go">nikola bootswatch_theme given a swatch name from bootswatch.com and a</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-10"></a><span class="go"> parent theme, creates a custom theme</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-11"></a><span class="go">nikola build run tasks</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-12"></a><span class="go">nikola check check links and files in the generated site</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-13"></a><span class="go">nikola clean clean action / remove targets</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-14"></a><span class="go">nikola console start an interactive python console with access to</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-15"></a><span class="go"> your site and configuration</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-16"></a><span class="go">nikola deploy deploy the site</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-17"></a><span class="go">nikola dumpdb dump dependency DB</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-18"></a><span class="go">nikola forget clear successful run status from internal DB</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-19"></a><span class="go">nikola help show help</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-20"></a><span class="go">nikola ignore ignore task (skip) on subsequent runs</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-21"></a><span class="go">nikola import_blogger import a blogger dump</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-22"></a><span class="go">nikola import_feed import a RSS/Atom dump</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-23"></a><span class="go">nikola import_wordpress import a WordPress dump</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-24"></a><span class="go">nikola init create a Nikola site in the specified folder</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-25"></a><span class="go">nikola list list tasks from dodo file</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-26"></a><span class="go">nikola mincss apply mincss to the generated site</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-27"></a><span class="go">nikola new_post create a new blog post or site page</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-28"></a><span class="go">nikola run run tasks</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-29"></a><span class="go">nikola serve start the test webserver</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-30"></a><span class="go">nikola strace use strace to list file_deps and targets</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-31"></a><span class="go">nikola theme manage themes</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-32"></a><span class="go">nikola version print the Nikola version number</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-33"></a>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-34"></a><span class="go">nikola help show help / reference</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-35"></a><span class="go">nikola help <command> show command usage</span>
- <a name="rest_code_6fc228dc86544900b3254eb5bab7e47e-36"></a><span class="go">nikola help <task-name> show task usage</span>
- </pre>
- <p>That will give you a list of all available commands in your version of Nikola.
- Each and every one of those is a plugin. Let's look at a typical example:</p>
- <p>First, the <code class="docutils literal">serve.plugin</code> file:</p>
- <pre class="code ini"><a name="rest_code_ba62f591ee56474b8dad401ec415b819-1"></a><span class="k">[Core]</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-2"></a><span class="na">Name</span> <span class="o">=</span> <span class="s">serve</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-3"></a><span class="na">Module</span> <span class="o">=</span> <span class="s">serve</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-4"></a>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-5"></a><span class="k">[Documentation]</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-6"></a><span class="na">Author</span> <span class="o">=</span> <span class="s">Roberto Alsina</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-7"></a><span class="na">Version</span> <span class="o">=</span> <span class="s">0.1</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-8"></a><span class="na">Website</span> <span class="o">=</span> <span class="s">https://getnikola.com</span>
- <a name="rest_code_ba62f591ee56474b8dad401ec415b819-9"></a><span class="na">Description</span> <span class="o">=</span> <span class="s">Start test server.</span>
- </pre>
- <aside class="admonition note"><p class="admonition-title">Note</p>
- <p>If you want to publish your plugin on the Plugin Index, <a class="reference external" href="https://github.com/getnikola/plugins/blob/master/README.md">read
- the docs for the Index</a>
- (and the .plugin file examples and explanations).</p>
- </aside><p>For your own plugin, just change the values in a sensible way. The
- <code class="docutils literal">Module</code> will be used to find the matching Python module, in this case
- <code class="docutils literal">serve.py</code>, from which this is the interesting bit:</p>
- <pre class="code python"><a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-1"></a><span class="kn">from</span> <span class="nn">nikola.plugin_categories</span> <span class="kn">import</span> <span class="n">Command</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-2"></a>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-3"></a><span class="c1"># You have to inherit Command for this to be a</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-4"></a><span class="c1"># command plugin:</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-5"></a>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-6"></a><span class="k">class</span> <span class="nc">CommandServe</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-7"></a> <span class="sd">"""Start test server."""</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-8"></a>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-9"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">"serve"</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-10"></a> <span class="n">doc_usage</span> <span class="o">=</span> <span class="s2">"[options]"</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-11"></a> <span class="n">doc_purpose</span> <span class="o">=</span> <span class="s2">"start the test webserver"</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-12"></a>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-13"></a> <span class="n">cmd_options</span> <span class="o">=</span> <span class="p">(</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-14"></a> <span class="p">{</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-15"></a> <span class="s1">'name'</span><span class="p">:</span> <span class="s1">'port'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-16"></a> <span class="s1">'short'</span><span class="p">:</span> <span class="s1">'p'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-17"></a> <span class="s1">'long'</span><span class="p">:</span> <span class="s1">'port'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-18"></a> <span class="s1">'default'</span><span class="p">:</span> <span class="mi">8000</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-19"></a> <span class="s1">'type'</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-20"></a> <span class="s1">'help'</span><span class="p">:</span> <span class="s1">'Port number'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-21"></a> <span class="p">},</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-22"></a> <span class="p">{</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-23"></a> <span class="s1">'name'</span><span class="p">:</span> <span class="s1">'address'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-24"></a> <span class="s1">'short'</span><span class="p">:</span> <span class="s1">'a'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-25"></a> <span class="s1">'long'</span><span class="p">:</span> <span class="s1">'--address'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-26"></a> <span class="s1">'type'</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-27"></a> <span class="s1">'default'</span><span class="p">:</span> <span class="s1">'127.0.0.1'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-28"></a> <span class="s1">'help'</span><span class="p">:</span> <span class="s1">'Address to bind'</span><span class="p">,</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-29"></a> <span class="p">},</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-30"></a> <span class="p">)</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-31"></a>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-32"></a> <span class="k">def</span> <span class="nf">_execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-33"></a> <span class="sd">"""Start test server."""</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-34"></a> <span class="n">out_dir</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'OUTPUT_FOLDER'</span><span class="p">]</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-35"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">out_dir</span><span class="p">):</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-36"></a> <span class="nb">print</span><span class="p">(</span><span class="s2">"Error: Missing '</span><span class="si">{0}</span><span class="s2">' folder?"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">out_dir</span><span class="p">))</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-37"></a> <span class="k">return</span> <span class="mi">1</span> <span class="c1"># Exit code on failure. (return 0 not necessary)</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-38"></a> <span class="k">else</span><span class="p">:</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-39"></a> <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">out_dir</span><span class="p">)</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-40"></a> <span class="n">httpd</span> <span class="o">=</span> <span class="n">HTTPServer</span><span class="p">((</span><span class="n">options</span><span class="p">[</span><span class="s1">'address'</span><span class="p">],</span> <span class="n">options</span><span class="p">[</span><span class="s1">'port'</span><span class="p">]),</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-41"></a> <span class="n">OurHTTPRequestHandler</span><span class="p">)</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-42"></a> <span class="n">sa</span> <span class="o">=</span> <span class="n">httpd</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">getsockname</span><span class="p">()</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-43"></a> <span class="nb">print</span><span class="p">(</span><span class="s2">"Serving HTTP on"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="s2">"port"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"..."</span><span class="p">)</span>
- <a name="rest_code_e3a6b6d51a3347a7adb07cea08cec1b1-44"></a> <span class="n">httpd</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
- </pre>
- <p>As mentioned above, a plugin can have options, which the user can see by doing
- <code class="docutils literal">nikola help command</code> and can later use, for example:</p>
- <pre class="code console"><a name="rest_code_3c9de002787e43998e18ec2797969dbc-1"></a><span class="gp">$</span> nikola <span class="nb">help</span> serve
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-2"></a><span class="go">nikola serve [options]</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-3"></a><span class="go">start the test webserver</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-4"></a>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-5"></a><span class="go">Options:</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-6"></a><span class="go"> -p ARG, --port=ARG</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-7"></a><span class="go"> Port number [default: 8000]</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-8"></a><span class="go"> -a ARG, --address=ARG</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-9"></a><span class="go"> Address to bind [default: 127.0.0.1]</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-10"></a>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-11"></a><span class="gp">$</span> nikola serve -p <span class="m">9000</span>
- <a name="rest_code_3c9de002787e43998e18ec2797969dbc-12"></a><span class="go">Serving HTTP on 127.0.0.1 port 9000 ...</span>
- </pre>
- <p>So, what can you do with commands? Well, anything you want, really. I have implemented
- a sort of planet using it. So, be creative, and if you do something interesting,
- let me know ;-)</p>
- </section><section id="templatesystem-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-3" role="doc-backlink">TemplateSystem Plugins</a></h3>
- <p>Nikola supports Mako and Jinja2. If you prefer some other templating
- system, then you will have to write a <code class="docutils literal">TemplateSystem</code> plugin. Here's how they work.
- First, you have to create a <code class="docutils literal">.plugin</code> file. Here's the one for the Mako plugin:</p>
- <pre class="code ini"><a name="rest_code_c5c3f7f326704b998816809be8814ef2-1"></a><span class="k">[Core]</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-2"></a><span class="na">Name</span> <span class="o">=</span> <span class="s">mako</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-3"></a><span class="na">Module</span> <span class="o">=</span> <span class="s">mako</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-4"></a>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-5"></a><span class="k">[Documentation]</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-6"></a><span class="na">Author</span> <span class="o">=</span> <span class="s">Roberto Alsina</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-7"></a><span class="na">Version</span> <span class="o">=</span> <span class="s">0.1</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-8"></a><span class="na">Website</span> <span class="o">=</span> <span class="s">https://getnikola.com</span>
- <a name="rest_code_c5c3f7f326704b998816809be8814ef2-9"></a><span class="na">Description</span> <span class="o">=</span> <span class="s">Support for Mako templates.</span>
- </pre>
- <aside class="admonition note"><p class="admonition-title">Note</p>
- <p>If you want to publish your plugin on the Plugin Index, <a class="reference external" href="https://github.com/getnikola/plugins/blob/master/README.md">read
- the docs for the Index</a>
- (and the .plugin file examples and explanations).</p>
- </aside><p>You will have to replace "mako" with your template system's name, and other data
- in the obvious ways.</p>
- <p>The "Module" option is the name of the module, which has to look something like this,
- a stub for a hypothetical system called "Templater":</p>
- <pre class="code python"><a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-1"></a><span class="kn">from</span> <span class="nn">nikola.plugin_categories</span> <span class="kn">import</span> <span class="n">TemplateSystem</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-2"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-3"></a><span class="c1"># You have to inherit TemplateSystem</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-4"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-5"></a><span class="k">class</span> <span class="nc">TemplaterTemplates</span><span class="p">(</span><span class="n">TemplateSystem</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-6"></a> <span class="sd">"""Wrapper for Templater templates."""</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-7"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-8"></a> <span class="c1"># name has to match Name in the .plugin file</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-9"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">"templater"</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-10"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-11"></a> <span class="c1"># A list of directories where the templates will be</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-12"></a> <span class="c1"># located. Most template systems have some sort of</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-13"></a> <span class="c1"># template loading tool that can use this.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-14"></a> <span class="k">def</span> <span class="nf">set_directories</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">directories</span><span class="p">,</span> <span class="n">cache_folder</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-15"></a> <span class="sd">"""Sets the list of folders where templates are located and cache."""</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-16"></a> <span class="k">pass</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-17"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-18"></a> <span class="c1"># You *must* implement this, even if to return []</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-19"></a> <span class="c1"># It should return a list of all the files that,</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-20"></a> <span class="c1"># when changed, may affect the template's output.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-21"></a> <span class="c1"># usually this involves template inheritance and</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-22"></a> <span class="c1"># inclusion.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-23"></a> <span class="k">def</span> <span class="nf">template_deps</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_name</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-24"></a> <span class="sd">"""Returns filenames which are dependencies for a template."""</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-25"></a> <span class="k">return</span> <span class="p">[]</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-26"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-27"></a> <span class="k">def</span> <span class="nf">render_template</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_name</span><span class="p">,</span> <span class="n">output_name</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-28"></a> <span class="sd">"""Renders template to a file using context.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-29"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-30"></a><span class="sd"> This must save the data to output_name *and* return it</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-31"></a><span class="sd"> so that the caller may do additional processing.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-32"></a><span class="sd"> """</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-33"></a> <span class="k">pass</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-34"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-35"></a> <span class="c1"># The method that does the actual rendering.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-36"></a> <span class="c1"># template_name is the name of the template file,</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-37"></a> <span class="c1"># context is a dictionary containing the data the template</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-38"></a> <span class="c1"># uses for rendering.</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-39"></a> <span class="k">def</span> <span class="nf">render_template_to_string</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-40"></a> <span class="sd">"""Renders template to a string using context. """</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-41"></a> <span class="k">pass</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-42"></a>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-43"></a> <span class="k">def</span> <span class="nf">inject_directory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">directory</span><span class="p">):</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-44"></a> <span class="sd">"""Injects the directory with the lowest priority in the</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-45"></a><span class="sd"> template search mechanism."""</span>
- <a name="rest_code_5a519bdb6ea7424d9da26e9afd8e3eba-46"></a> <span class="k">pass</span>
- </pre>
- <p>You can see a real example in <a class="reference external" href="https://github.com/getnikola/nikola/blob/master/nikola/plugins/template/jinja.py">the Jinja plugin</a></p>
- </section><section id="task-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-4" role="doc-backlink">Task Plugins</a></h3>
- <p>If you want to do something that depends on the data in your site, you
- probably want to do a <code class="docutils literal">Task</code> plugin, which will make it be part of the
- <code class="docutils literal">nikola build</code> command. These are the currently available tasks, all
- provided by plugins:</p>
- <aside class="sidebar"><p class="sidebar-title">Other Tasks</p>
- <p>There are also <code class="docutils literal">LateTask</code> plugins, which are executed later,
- and <code class="docutils literal">TaskMultiplier</code> plugins that take a task and create
- more tasks out of it.</p>
- </aside><pre class="code console"><a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-1"></a><span class="gp">$</span> nikola list
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-2"></a><span class="go">Scanning posts....done!</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-3"></a><span class="go">copy_assets</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-4"></a><span class="go">copy_files</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-5"></a><span class="go">create_bundles</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-6"></a><span class="go">post_render</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-7"></a><span class="go">redirect</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-8"></a><span class="go">render_galleries</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-9"></a><span class="go">render_listings</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-10"></a><span class="go">render_pages</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-11"></a><span class="go">render_posts</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-12"></a><span class="go">render_site</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-13"></a><span class="go">render_sources</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-14"></a><span class="go">render_taxonomies</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-15"></a><span class="go">robots_file</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-16"></a><span class="go">scale_images</span>
- <a name="rest_code_fc9ffb7c69224daeb0a3e5d7b2feb52d-17"></a><span class="go">sitemap</span>
- </pre>
- <p>These have access to the <code class="docutils literal">site</code> object which contains your timeline and
- your configuration.</p>
- <p>The critical bit of Task plugins is their <code class="docutils literal">gen_tasks</code> method, which <code class="docutils literal">yields</code>
- <a class="reference external" href="https://pydoit.org/tasks.html">doit tasks</a>.</p>
- <p>The details of how to handle dependencies, etc., are a bit too much for this
- document, so I'll just leave you with an example, the <code class="docutils literal">copy_assets</code> task.
- First the <code class="docutils literal">task_copy_assets.plugin</code> file, which you should copy and edit
- in the logical ways:</p>
- <pre class="code ini"><a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-1"></a><span class="k">[Core]</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-2"></a><span class="na">Name</span> <span class="o">=</span> <span class="s">copy_assets</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-3"></a><span class="na">Module</span> <span class="o">=</span> <span class="s">task_copy_assets</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-4"></a>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-5"></a><span class="k">[Documentation]</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-6"></a><span class="na">Author</span> <span class="o">=</span> <span class="s">Roberto Alsina</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-7"></a><span class="na">Version</span> <span class="o">=</span> <span class="s">0.1</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-8"></a><span class="na">Website</span> <span class="o">=</span> <span class="s">https://getnikola.com</span>
- <a name="rest_code_8abe88df87fb424cbe0e5131ed77debd-9"></a><span class="na">Description</span> <span class="o">=</span> <span class="s">Copy theme assets into output.</span>
- </pre>
- <aside class="admonition note"><p class="admonition-title">Note</p>
- <p>If you want to publish your plugin on the Plugin Index, <a class="reference external" href="https://github.com/getnikola/plugins/blob/master/README.md">read
- the docs for the Index</a>
- (and the .plugin file examples and explanations).</p>
- </aside><p>And the <code class="docutils literal">task_copy_assets.py</code> file, in its entirety:</p>
- <pre class="code python"><a name="rest_code_c033780b5b47427f9b622b01c7471f12-1"></a><span class="kn">import</span> <span class="nn">os</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-2"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-3"></a><span class="kn">from</span> <span class="nn">nikola.plugin_categories</span> <span class="kn">import</span> <span class="n">Task</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-4"></a><span class="kn">from</span> <span class="nn">nikola</span> <span class="kn">import</span> <span class="n">utils</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-5"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-6"></a><span class="c1"># Have to inherit Task to be a task plugin</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-7"></a><span class="k">class</span> <span class="nc">CopyAssets</span><span class="p">(</span><span class="n">Task</span><span class="p">):</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-8"></a> <span class="sd">"""Copy theme assets into output."""</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-9"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-10"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">"copy_assets"</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-11"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-12"></a> <span class="c1"># This yields the tasks</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-13"></a> <span class="k">def</span> <span class="nf">gen_tasks</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-14"></a> <span class="sd">"""Create tasks to copy the assets of the whole theme chain.</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-15"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-16"></a><span class="sd"> If a file is present on two themes, use the version</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-17"></a><span class="sd"> from the "youngest" theme.</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-18"></a><span class="sd"> """</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-19"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-20"></a> <span class="c1"># I put all the configurations and data the plugin uses</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-21"></a> <span class="c1"># in a dictionary because utils.config_changed will</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-22"></a> <span class="c1"># make it so that if these change, this task will be</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-23"></a> <span class="c1"># marked out of date, and run again.</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-24"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-25"></a> <span class="n">kw</span> <span class="o">=</span> <span class="p">{</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-26"></a> <span class="s2">"themes"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">THEMES</span><span class="p">,</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-27"></a> <span class="s2">"output_folder"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'OUTPUT_FOLDER'</span><span class="p">],</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-28"></a> <span class="s2">"filters"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'FILTERS'</span><span class="p">],</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-29"></a> <span class="p">}</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-30"></a>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-31"></a> <span class="n">tasks</span> <span class="o">=</span> <span class="p">{}</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-32"></a> <span class="k">for</span> <span class="n">theme_name</span> <span class="ow">in</span> <span class="n">kw</span><span class="p">[</span><span class="s1">'themes'</span><span class="p">]:</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-33"></a> <span class="n">src</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">utils</span><span class="o">.</span><span class="n">get_theme_path</span><span class="p">(</span><span class="n">theme_name</span><span class="p">),</span> <span class="s1">'assets'</span><span class="p">)</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-34"></a> <span class="n">dst</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">kw</span><span class="p">[</span><span class="s1">'output_folder'</span><span class="p">],</span> <span class="s1">'assets'</span><span class="p">)</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-35"></a> <span class="k">for</span> <span class="n">task</span> <span class="ow">in</span> <span class="n">utils</span><span class="o">.</span><span class="n">copy_tree</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dst</span><span class="p">):</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-36"></a> <span class="k">if</span> <span class="n">task</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="ow">in</span> <span class="n">tasks</span><span class="p">:</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-37"></a> <span class="k">continue</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-38"></a> <span class="n">tasks</span><span class="p">[</span><span class="n">task</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]]</span> <span class="o">=</span> <span class="n">task</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-39"></a> <span class="n">task</span><span class="p">[</span><span class="s1">'uptodate'</span><span class="p">]</span> <span class="o">=</span> <span class="n">task</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'uptodate'</span><span class="p">,</span> <span class="p">[])</span> <span class="o">+</span> \
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-40"></a> <span class="p">[</span><span class="n">utils</span><span class="o">.</span><span class="n">config_changed</span><span class="p">(</span><span class="n">kw</span><span class="p">)]</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-41"></a> <span class="n">task</span><span class="p">[</span><span class="s1">'basename'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-42"></a> <span class="c1"># If your task generates files, please do this.</span>
- <a name="rest_code_c033780b5b47427f9b622b01c7471f12-43"></a> <span class="k">yield</span> <span class="n">utils</span><span class="o">.</span><span class="n">apply_filters</span><span class="p">(</span><span class="n">task</span><span class="p">,</span> <span class="n">kw</span><span class="p">[</span><span class="s1">'filters'</span><span class="p">])</span>
- </pre></section><section id="pagecompiler-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-5" role="doc-backlink">PageCompiler Plugins</a></h3>
- <p>These plugins implement markup languages, they take sources for posts or pages and
- create HTML or other output files. A good example is <a class="reference external" href="https://github.com/getnikola/plugins/tree/master/v8/misaka">the misaka plugin</a> or the built-in
- compiler plugins.</p>
- <p>They must provide:</p>
- <dl class="simple">
- <dt><code class="docutils literal">compile</code></dt>
- <dd>
- <p>Function that builds a file.</p>
- </dd>
- <dt><code class="docutils literal">create_post</code></dt>
- <dd>
- <p>Function that creates an empty file with some metadata in it.</p>
- </dd>
- </dl>
- <p>If the compiler produces something other than HTML files, it should also implement <code class="docutils literal">extension</code> which
- returns the preferred extension for the output file.</p>
- <p>These plugins can also be used to extract metadata from a file. To do so, the
- plugin must set <code class="docutils literal">supports_metadata</code> to <code class="docutils literal">True</code> and implement <code class="docutils literal">read_metadata</code> that will return a dict containing the
- metadata contained in the file. Optionally, it may list <code class="docutils literal">metadata_conditions</code> (see <a class="reference internal" href="extending.html#metadataextractor-plugins">MetadataExtractor Plugins</a> below)</p>
- </section><section id="metadataextractor-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-6" role="doc-backlink">MetadataExtractor Plugins</a></h3>
- <p>Plugins that extract metadata from posts. If they are based on post content,
- they must implement <code class="docutils literal">_extract_metadata_from_text</code> (takes source of a post
- returns a dict of metadata). They may also implement
- <code class="docutils literal">split_metadata_from_text</code>, <code class="docutils literal">extract_text</code>. If they are based on filenames,
- they only need <code class="docutils literal">extract_filename</code>. If <code class="docutils literal">support_write</code> is set to True,
- <code class="docutils literal">write_metadata</code> must be implemented.</p>
- <p>Every extractor must be configured properly. The <code class="docutils literal">name</code>, <code class="docutils literal">source</code> (from the
- <code class="docutils literal">MetaSource</code> enum in <code class="docutils literal">metadata_extractors</code>) and <code class="docutils literal">priority</code>
- (<code class="docutils literal">MetaPriority</code>) fields are mandatory. There might also be a list of
- <code class="docutils literal">conditions</code> (tuples of <code class="docutils literal">MetaCondition, arg</code>), used to check if an
- extractor can provide metadata, a compiled regular expression used to split
- metadata (<code class="docutils literal">split_metadata_re</code>, may be <code class="docutils literal">None</code>, used by default
- <code class="docutils literal">split_metadata_from_text</code>), a list of <code class="docutils literal">requirements</code> (3-tuples: import
- name, pip name, friendly name), <code class="docutils literal">map_from</code> (name of <code class="docutils literal">METADATA_MAPPING</code> to
- use, if any) and <code class="docutils literal">supports_write</code> (whether the extractor supports writing
- metadata in the desired format).</p>
- <p>For more details, see the definition in <code class="docutils literal">plugin_categories.py</code> and default extractors in <code class="docutils literal">metadata_extractors.py</code>.</p>
- </section><section id="restextension-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-7" role="doc-backlink">RestExtension Plugins</a></h3>
- <p>Implement directives for reStructuredText, see <a class="reference external" href="https://github.com/getnikola/nikola/blob/master/nikola/plugins/compile/rest/media.py">media.py</a> for a simple example.</p>
- <p>If your output depends on a config value, you need to make your post record a
- dependency on a pseudo-path, like this:</p>
- <pre class="code text"><a name="rest_code_9ac74e87bd9840bcb263f3d32ac5ffc4-1"></a>####MAGIC####CONFIG:OPTIONNAME
- </pre>
- <p>Then, whenever the <code class="docutils literal">OPTIONNAME</code> option is changed in conf.py, the file will be rebuilt.</p>
- <p>If your directive depends or may depend on the whole timeline (like the
- <code class="docutils literal"><span class="pre">post-list</span></code> directive, where adding new posts to the site could make it
- stale), you should record a dependency on the pseudo-path
- <code class="docutils literal"><span class="pre">####MAGIC####TIMELINE</span></code>.</p>
- </section><section id="markdownextension-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-8" role="doc-backlink">MarkdownExtension Plugins</a></h3>
- <p>Implement Markdown extensions, see <a class="reference external" href="https://github.com/getnikola/nikola/blob/master/nikola/plugins/compile/markdown/mdx_nikola.py">mdx_nikola.py</a> for a simple example.</p>
- <p>Note that Python markdown extensions are often also available as separate
- packages. This is only meant to ship extensions along with Nikola.</p>
- </section><section id="signalhandler-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-9" role="doc-backlink">SignalHandler Plugins</a></h3>
- <p>These plugins extend the <code class="docutils literal">SignalHandler</code> class and connect to one or more
- signals via <a class="reference external" href="https://pythonhosted.org/blinker/">blinker</a>.</p>
- <p>The easiest way to do this is to reimplement <code class="docutils literal">set_site()</code> and just connect to
- whatever signals you want there.</p>
- <p>Currently Nikola emits the following signals:</p>
- <dl>
- <dt><code class="docutils literal">sighandlers_loaded</code></dt>
- <dd>
- <p>Right after SignalHandler plugin activation.</p>
- </dd>
- <dt><code class="docutils literal">initialized</code></dt>
- <dd>
- <p>When all tasks are loaded.</p>
- </dd>
- <dt><code class="docutils literal">configured</code></dt>
- <dd>
- <p>When all the configuration file is processed. Note that plugins are activated before this is emitted.</p>
- </dd>
- <dt><code class="docutils literal">scanned</code></dt>
- <dd>
- <p>After posts are scanned.</p>
- </dd>
- <dt>
- <code class="docutils literal">new_post</code> / <code class="docutils literal">new_page</code>
- </dt>
- <dd>
- <p>When a new post is created, using the <code class="docutils literal">nikola new_post</code>/<code class="docutils literal">nikola new_page</code> commands. The signal
- data contains the path of the file, and the metadata file (if there is one).</p>
- </dd>
- <dt>
- <code class="docutils literal">existing_post</code> / <code class="docutils literal">existing_page</code>
- </dt>
- <dd>
- <p>When a new post fails to be created due to a title conflict. Contains the same data as <code class="docutils literal">new_post</code>.</p>
- </dd>
- <dt><code class="docutils literal">deployed</code></dt>
- <dd>
- <p>When the <code class="docutils literal">nikola deploy</code> command is run, and there is at least one new
- entry/post since <code class="docutils literal">last_deploy</code>. The signal data is of the form:</p>
- <pre class="literal-block">{
- 'last_deploy: # datetime object for the last deployed time,
- 'new_deploy': # datetime object for the current deployed time,
- 'clean': # whether there was a record of a last deployment,
- 'deployed': # all files deployed after the last deploy,
- 'undeployed': # all files not deployed since they are either future posts/drafts
- }</pre>
- </dd>
- <dt><code class="docutils literal">compiled</code></dt>
- <dd>
- <p>When a post/page is compiled from its source to html, before anything else is done with it. The signal
- data is in the form:</p>
- <pre class="literal-block">{
- 'source': # the path to the source file
- 'dest': # the path to the cache file for the post/page
- 'post': # the Post object for the post/page
- }</pre>
- </dd>
- </dl>
- <p>One example is the <a class="reference external" href="https://github.com/getnikola/plugins/tree/master/v7/deploy_hooks">deploy_hooks plugin.</a></p>
- </section><section id="configplugin-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-10" role="doc-backlink">ConfigPlugin Plugins</a></h3>
- <p>Does nothing specific, can be used to modify the site object (and thus the config).</p>
- <p>Put all the magic you want in <code class="docutils literal">set_site()</code>, and don’t forget to run the one
- from <code class="docutils literal">super()</code>. Example plugin: <a class="reference external" href="https://github.com/getnikola/plugins/tree/master/v7/navstories">navstories</a></p>
- </section><section id="commentsystem-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-11" role="doc-backlink">CommentSystem Plugins</a></h3>
- <p>Can be used to add a new comment system. (It doesn’t do anything by itself.) It’s expected to provide templates named <code class="docutils literal">comment_helper_foo.tmpl</code>.</p>
- <p>Example plugin: <a class="reference external" href="https://github.com/getnikola/plugins/tree/master/v8/cactuscomments">cactuscomments</a></p>
- </section><section id="shortcode-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-12" role="doc-backlink">Shortcode Plugins</a></h3>
- <p>Shortcode Plugins are a simple way to create a custom shortcode handler.
- By default, the <code class="docutils literal">set_site</code> method will register the <code class="docutils literal">handler</code> method as a
- shortcode with the plugin’s <code class="docutils literal">name</code> as the shortcode name.</p>
- <p>See the <a class="reference internal" href="extending.html#shortcodes">Shortcodes</a> section for more details on shortcodes.</p>
- </section><section id="postscanner-plugins"><h3><a class="toc-backref" href="extending.html#toc-entry-13" role="doc-backlink">PostScanner Plugins</a></h3>
- <p>Get posts and pages from "somewhere" to be added to the timeline.
- There are currently two plugins for this: the built-in <code class="docutils literal">scan_posts</code>, and
- <code class="docutils literal">pkgindex_scan</code> (in the Plugin Index), which is used to treat .plugin/.theme
- + README.md as posts to generate the Plugin and Theme Indexes.</p>
- </section></section><section id="plugin-index"><h2><a class="toc-backref" href="extending.html#toc-entry-14" role="doc-backlink">Plugin Index</a></h2>
- <p>There is a <a class="reference external" href="https://plugins.getnikola.com/">plugin index</a>, which stores all
- of the plugins for Nikola people wanted to share with the world.</p>
- <p>You may want to read the <a class="reference external" href="https://github.com/getnikola/plugins/blob/master/README.md">README for the Index</a> if you want to
- publish your package there.</p>
- </section><section id="path-link-resolution-mechanism"><h2><a class="toc-backref" href="extending.html#toc-entry-15" role="doc-backlink">Path/Link Resolution Mechanism</a></h2>
- <p>Any plugin can register a function using <code class="docutils literal">Nikola.register_path_handler</code> to
- allow resolution of paths and links. These are useful for templates, which
- can access them via <code class="docutils literal">_link</code>.</p>
- <p>For example, you can always get a link to the path for the feed of the "foo" tag
- by using <code class="docutils literal"><span class="pre">_link('tag_rss',</span> 'foo')</code> or the <code class="docutils literal"><span class="pre">link://tag_rss/foo</span></code> URL.</p>
- <p>Here's the relevant code from the tag plugin.</p>
- <pre class="code python"><a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-1"></a><span class="c1"># In set_site</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-2"></a><span class="n">site</span><span class="o">.</span><span class="n">register_path_handler</span><span class="p">(</span><span class="s1">'tag_rss'</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">tag_rss_path</span><span class="p">)</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-3"></a>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-4"></a><span class="c1"># And these always take name and lang as arguments and return a list of</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-5"></a><span class="c1"># path elements.</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-6"></a><span class="k">def</span> <span class="nf">tag_rss_path</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">lang</span><span class="p">):</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-7"></a> <span class="k">return</span> <span class="p">[</span><span class="n">_f</span> <span class="k">for</span> <span class="n">_f</span> <span class="ow">in</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'TRANSLATIONS'</span><span class="p">][</span><span class="n">lang</span><span class="p">],</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-8"></a> <span class="bp">self</span><span class="o">.</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'TAG_PATH'</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">slugify_name</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">lang</span><span class="p">)</span> <span class="o">+</span> <span class="s2">".xml"</span><span class="p">]</span> <span class="k">if</span>
- <a name="rest_code_c3b874e131b54f6e96535b5ef0c56564-9"></a> <span class="n">_f</span><span class="p">]</span>
- </pre></section><section id="template-hooks"><h2><a class="toc-backref" href="extending.html#toc-entry-16" role="doc-backlink">Template Hooks</a></h2>
- <p>Plugins can use a hook system for adding stuff into templates. In order to use
- it, a plugin must register itself. The following hooks currently exist:</p>
- <ul class="simple">
- <li><p><code class="docutils literal">extra_head</code> (not equal to the config option!)</p></li>
- <li><p><code class="docutils literal">body_end</code> (not equal to the config option!)</p></li>
- <li><p><code class="docutils literal">page_header</code></p></li>
- <li><p><code class="docutils literal">menu</code></p></li>
- <li><p><code class="docutils literal">menu_alt</code> (right-side menu in bootstrap, after <code class="docutils literal">menu</code> in base)</p></li>
- <li><p><code class="docutils literal">page_footer</code></p></li>
- </ul>
- <p>For example, in order to register a script into <code class="docutils literal">extra_head</code>:</p>
- <pre class="code python"><a name="rest_code_85abaedb49c6458da061ed02e63e3471-1"></a><span class="c1"># In set_site</span>
- <a name="rest_code_85abaedb49c6458da061ed02e63e3471-2"></a><span class="n">site</span><span class="o">.</span><span class="n">template_hooks</span><span class="p">[</span><span class="s1">'extra_head'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'<script src="/assets/js/fancyplugin.js">'</span><span class="p">)</span>
- </pre>
- <p>There is also another API available. It allows use of dynamically generated
- HTML:</p>
- <pre class="code python"><a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-1"></a><span class="c1"># In set_site</span>
- <a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-2"></a><span class="k">def</span> <span class="nf">generate_html_bit</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">ftype</span><span class="o">=</span><span class="s1">'js'</span><span class="p">):</span>
- <a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-3"></a> <span class="sd">"""Generate HTML for an asset."""</span>
- <a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-4"></a> <span class="k">return</span> <span class="s1">'<script src="/assets/</span><span class="si">{t}</span><span class="s1">/</span><span class="si">{n}</span><span class="s1">.</span><span class="si">{t}</span><span class="s1">">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">name</span><span class="p">,</span> <span class="n">t</span><span class="o">=</span><span class="n">ftype</span><span class="p">)</span>
- <a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-5"></a>
- <a name="rest_code_3d80b5b30b83451486e9468e8cca60f5-6"></a><span class="n">site</span><span class="o">.</span><span class="n">template_hooks</span><span class="p">[</span><span class="s1">'extra_head'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">generate_html_bit</span><span class="p">,</span> <span class="kc">False</span><span class="p">,</span> <span class="s1">'fancyplugin'</span><span class="p">,</span> <span class="n">ftype</span><span class="o">=</span><span class="s1">'js'</span><span class="p">)</span>
- </pre>
- <p>The second argument to <code class="docutils literal">append()</code> is used to determine whether the function
- needs access to the current template context and the site. If it is set to
- <code class="docutils literal">True</code>, the function will also receive <code class="docutils literal">site</code> and <code class="docutils literal">context</code> keyword
- arguments. Example use:</p>
- <pre class="code python"><a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-1"></a><span class="c1"># In set_site</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-2"></a><span class="k">def</span> <span class="nf">greeting</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">endswith</span><span class="o">=</span><span class="s1">''</span><span class="p">,</span> <span class="n">site</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">context</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-3"></a> <span class="sd">"""Greet someone."""</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-4"></a> <span class="k">if</span> <span class="n">context</span><span class="p">[</span><span class="s1">'lang'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'en'</span><span class="p">:</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-5"></a> <span class="n">greet</span> <span class="o">=</span> <span class="sa">u</span><span class="s1">'Hello'</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-6"></a> <span class="k">elif</span> <span class="n">context</span><span class="p">[</span><span class="s1">'lang'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'es'</span><span class="p">:</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-7"></a> <span class="n">greet</span> <span class="o">=</span> <span class="sa">u</span><span class="s1">'¡Hola'</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-8"></a>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-9"></a> <span class="n">t</span> <span class="o">=</span> <span class="sa">u</span><span class="s1">' BLOG_TITLE = </span><span class="si">{0}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'BLOG_TITLE'</span><span class="p">](</span><span class="n">context</span><span class="p">[</span><span class="s1">'lang'</span><span class="p">]))</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-10"></a>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-11"></a> <span class="k">return</span> <span class="sa">u</span><span class="s1">'<h3></span><span class="si">{greet}</span><span class="s1"> </span><span class="si">{addr}{endswith}</span><span class="s1"></h3>'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">greet</span><span class="o">=</span><span class="n">greet</span><span class="p">,</span> <span class="n">addr</span><span class="o">=</span><span class="n">addr</span><span class="p">,</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-12"></a> <span class="n">endswith</span><span class="o">=</span><span class="n">endswith</span><span class="p">)</span> <span class="o">+</span> <span class="n">t</span>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-13"></a>
- <a name="rest_code_3b60727dbf4e432d81b289c0645bfb85-14"></a><span class="n">site</span><span class="o">.</span><span class="n">template_hooks</span><span class="p">[</span><span class="s1">'page_header'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">greeting</span><span class="p">,</span> <span class="kc">True</span><span class="p">,</span> <span class="sa">u</span><span class="s1">'Nikola Tesla'</span><span class="p">,</span> <span class="n">endswith</span><span class="o">=</span><span class="sa">u</span><span class="s1">'!'</span><span class="p">)</span>
- </pre>
- <p>Dependencies for template hooks:</p>
- <ul class="simple">
- <li><p>if the input is a string, the string value, alongside arguments to <code class="docutils literal">append</code>, is used for calculating dependencies</p></li>
- <li><p>if the input is a callable, it attempts <code class="docutils literal">input.template_registry_identifier</code>, then <code class="docutils literal">input.__doc__</code>, and if neither is available, it uses a static string.</p></li>
- </ul>
- <p>Make sure to provide at least a docstring, or a identifier, to ensure rebuilds work properly.</p>
- </section><section id="shortcodes"><h2><a class="toc-backref" href="extending.html#toc-entry-17" role="doc-backlink">Shortcodes</a></h2>
- <p>Some (hopefully all) markup compilers support shortcodes in these forms:</p>
- <pre class="code text"><a name="rest_code_81c68590ecd6426193834bc742049523-1"></a>{{% foo %}} # No arguments
- <a name="rest_code_81c68590ecd6426193834bc742049523-2"></a>{{% foo bar %}} # One argument, containing "bar"
- <a name="rest_code_81c68590ecd6426193834bc742049523-3"></a>{{% foo bar baz=bat %}} # Two arguments, one containing "bar", one called "baz" containing "bat"
- <a name="rest_code_81c68590ecd6426193834bc742049523-4"></a>
- <a name="rest_code_81c68590ecd6426193834bc742049523-5"></a>{{% foo %}}Some text{{% /foo %}} # one argument called "data" containing "Some text"
- </pre>
- <p>So, if you are creating a plugin that generates markup, it may be a good idea
- to register it as a shortcode in addition of to restructured text directive or
- markdown extension, thus making it available to all markup formats.</p>
- <p>To implement your own shortcodes from a plugin, you can create a plugin inheriting <code class="docutils literal">ShortcodePlugin</code>.
- By default, the <code class="docutils literal">set_site</code> method will register the <code class="docutils literal">handler</code> method as a
- shortcode with the plugin’s <code class="docutils literal">name</code> as the shortcode name. To have other
- shortcode names, you can call
- <code class="docutils literal">Nikola.register_shortcode(name, func)</code> with the following arguments:</p>
- <dl class="simple">
- <dt>
- <code class="docutils literal">name</code>:</dt>
- <dd>
- <p>Name of the shortcode ("foo" in the examples above)</p>
- </dd>
- <dt>
- <code class="docutils literal">func</code>:</dt>
- <dd>
- <p>A function that will handle the shortcode</p>
- </dd>
- </dl>
- <p>The shortcode handler <strong>must</strong> return a two-element tuple, <code class="docutils literal">(output, dependencies)</code></p>
- <dl class="simple">
- <dt>
- <code class="docutils literal">output</code>:</dt>
- <dd>
- <p>The text that will replace the shortcode in the document.</p>
- </dd>
- <dt>
- <code class="docutils literal">dependencies</code>:</dt>
- <dd>
- <p>A list of all the files on disk which will make the output be considered
- out of date. For example, if the shortcode uses a template, it should be
- the path to the template file.</p>
- </dd>
- </dl>
- <p>The shortcode handler <strong>must</strong> accept the following named arguments (or
- variable keyword arguments):</p>
- <dl class="simple">
- <dt>
- <code class="docutils literal">site</code>:</dt>
- <dd>
- <p>An instance of the Nikola class, to access site state</p>
- </dd>
- <dt>
- <code class="docutils literal">data</code>:</dt>
- <dd>
- <p>If the shortcut is used as opening/closing tags, it will be the text
- between them, otherwise <code class="docutils literal">None</code>.</p>
- </dd>
- <dt>
- <code class="docutils literal">lang</code>:</dt>
- <dd>
- <p>The current language.</p>
- </dd>
- </dl>
- <p>If the shortcode tag has arguments of the form <code class="docutils literal">foo=bar</code> they will be
- passed as named arguments. Everything else will be passed as positional
- arguments in the function call.</p>
- <p>So, for example:</p>
- <pre class="literal-block">{{% foo bar baz=bat beep %}}Some text{{% /foo %}}</pre>
- <p>Assuming you registered <code class="docutils literal">foo_handler</code> as the handler function for the
- shortcode named <code class="docutils literal">foo</code>, this will result in the following call when the above
- shortcode is encountered:</p>
- <pre class="literal-block">foo_handler("bar", "beep", baz="bat", data="Some text", site=whatever)</pre>
- <section id="template-based-shortcodes"><h3><a class="toc-backref" href="extending.html#toc-entry-18" role="doc-backlink">Template-based Shortcodes</a></h3>
- <p>Another way to define a new shortcode is to add a template file to the
- <code class="docutils literal">shortcodes</code> directory of your site. The template file must have the
- shortcode name as the basename and the extension <code class="docutils literal">.tmpl</code>. For example, if you
- want to add a new shortcode named <code class="docutils literal">foo</code>, create the template file as
- <code class="docutils literal">shortcodes/foo.tmpl</code>.</p>
- <p>When the shortcode is encountered, the matching template will be rendered with
- its context provided by the arguments given in the shortcode. Keyword arguments
- are passed directly, i.e. the key becomes the variable name in the template
- namespace with a matching string value. Non-keyword arguments are passed as
- string values in a tuple named <code class="docutils literal">_args</code>. As for normal shortcodes with a
- handler function, <code class="docutils literal">site</code> and <code class="docutils literal">data</code> will be added to the keyword arguments.</p>
- <p>Example:</p>
- <p>The following shortcode:</p>
- <pre class="code text"><a name="rest_code_78887cdd58254883b05f3fd58cf55913-1"></a>{{% foo bar="baz" spam %}}
- </pre>
- <p>With a template in <code class="docutils literal">shortcodes/foo.tmpl</code> with this content (using Jinja2
- syntax in this example)</p>
- <pre class="code jinja"><a name="rest_code_fb1d3a1ec39d459a889fc8c7fcc88c32-1"></a><span class="x"><div class="</span><span class="cp">{{</span> <span class="nv">_args</span><span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="k">if</span> <span class="nv">_args</span> <span class="k">else</span> <span class="s1">'ham'</span> <span class="cp">}}</span><span class="x">"></span><span class="cp">{{</span> <span class="nv">bar</span> <span class="cp">}}</span><span class="x"></div></span>
- </pre>
- <p>Will result in this output</p>
- <pre class="code html"><a name="rest_code_13ea22a2fa9842d6af6fed3495660b25-1"></a><span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"spam"</span><span class="p">></span>baz<span class="p"></</span><span class="nt">div</span><span class="p">></span>
- </pre></section></section><section id="state-and-cache"><h2><a class="toc-backref" href="extending.html#toc-entry-19" role="doc-backlink">State and Cache</a></h2>
- <p>Sometimes your plugins will need to cache things to speed up further actions. Here are the conventions for that:</p>
- <ul class="simple">
- <li><p>If it's a file, put it somewhere in <code class="docutils literal"><span class="pre">self.site.config['CACHE_FOLDER']</span></code> (defaults to <code class="docutils literal">cache/</code>.</p></li>
- <li><p>If it's a value, use <code class="docutils literal">self.site.cache.set(key, value)</code> to set it and <code class="docutils literal">self.site.cache.get(key)</code> to get it.
- The key should be a string, the value should be json-encodable (so, be careful with datetime objects)</p></li>
- </ul>
- <p>The values and files you store there can <strong>and will</strong> be deleted sometimes by the user. They should always be
- things you can reconstruct without lossage. They are throwaways.</p>
- <p>On the other hand, sometimes you want to save something that is <strong>not</strong> a throwaway. These are things that may
- change the output, so the user should not delete them. We call that <strong>state</strong>. To save state:</p>
- <ul class="simple">
- <li><p>If it's a file, put it somewhere in the working directory. Try not to do that please.</p></li>
- <li><p>If it's a value, use <code class="docutils literal">self.site.state.set(key, value)</code> to set it and <code class="docutils literal">self.state.cache.get(key)</code> to get it.
- The key should be a string, the value should be json-encodable (so, be careful with datetime objects)</p></li>
- </ul>
- <p>The <code class="docutils literal">cache</code> and <code class="docutils literal">state</code> objects are rather simplistic, and that's intentional. They have no default values: if
- the key is not there, you will get <code class="docutils literal">None</code> and like it. They are meant to be both threadsafe, but hey, who can
- guarantee that sort of thing?</p>
- <p>There are no sections, and no access protection, so let's not use it to store passwords and such. Use responsibly.</p>
- </section><section id="logging"><h2><a class="toc-backref" href="extending.html#toc-entry-20" role="doc-backlink">Logging</a></h2>
- <p>Plugins often need to produce messages to the screen. All plugins get a logger object (<code class="docutils literal">self.logger</code>) by default,
- configured to work with Nikola (logging level, colorful output, plugin name as the logger name). If you need, you can
- also use the global (<code class="docutils literal">nikola.utils.LOGGER</code>) logger, or you can instantiate custom loggers with
- <code class="docutils literal">nikola.utils.get_logger</code> or the <code class="docutils literal">nikola.log</code> module.</p>
- </section><section id="template-and-dependency-injection"><h2><a class="toc-backref" href="extending.html#toc-entry-21" role="doc-backlink">Template and Dependency Injection</a></h2>
- <p>Plugins have access to two injection facilities.</p>
- <p>If your plugin needs custom templates for its features (adding pages, displaying stuff, etc.), you can put them in the
- <code class="docutils literal">templates/mako</code> and <code class="docutils literal">templates/jinja</code> subfolders in your plugin’s folder. Note that those templates have a very low
- priority, so that users can override your plugin’s templates with their own.</p>
- <p>If your plugin needs to inject dependencies, the <code class="docutils literal">inject_dependency(target, dependency)</code> function can be used to add a
- <code class="docutils literal">dependency</code> for tasks which basename == <code class="docutils literal">target</code>. This facility should be limited to cases which really need it,
- consider other facilities first (eg. adding post dependencies).</p>
- </section>
- </div>
-
-
- </article>
- </div>
- <div class="col-sm-3 col-sm-offset-1 blog-sidebar">
- <div class="sidebar-module sidebar-module-inset">
- <h4>About</h4>
- <div id="shoutcastdiv">
- <script type="text/javascript">
- refreshdiv();
- </script>
- </div>
- </div>
- <div class="sidebar-module">
- <h4>Links</h4>
- <ol class="list-unstyled">
- <li><a href="http://getbootstrap.com/examples/blog/">Bootstrap Blog Theme</a></li>
- <li><a href="https://getnikola.com/">Nikola</a></li>
- <li><a href="https://twitter.com/mdo">@mdo</a></li>
- <li><a href="https://twitter.com/Kwpolska">@Kwpolska</a></li>
- <li><a href="https://twitter.com/GetNikola">@GetNikola</a></li>
- </ol>
- </div>
-
-
- </div>
- <!--End of body content-->
- </div>
- </div>
- </div>
-
- <footer class="blog-footer" id="footer">
- Contents © 2023 <a href="mailto:contact@riff-radio.org">Riff</a> - Powered by <a href="https://getnikola.com" rel="nofollow">Nikola</a>
-
- </footer><script src="../assets/js/all-nocdn.js"></script><!-- fancy dates --><script>
- moment.locale("en");
- fancydates(0, "YYYY-MM-DD HH:mm");
- </script><!-- end fancy dates --><script>
- baguetteBox.run('div#content', {
- ignoreClass: 'islink',
- captions: function(element) {
- return element.getElementsByTagName('img')[0].alt;
- }});
- </script><script type="text/javascript" src="../refresh.js"></script>
- </body>
- </html>
|