aboutsummaryrefslogtreecommitdiffstats
path: root/docs/extending.txt
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-02-03 19:17:00 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-02-03 19:17:00 -0500
commit3a0d66f07b112b6d2bdc2b57bbf717a89a351ce6 (patch)
treea7cf56282e54f05785243bc1e903d6594f2c06ba /docs/extending.txt
parent787b97a4cb24330b36f11297c6d3a7a473a907d0 (diff)
New upstream version 8.1.2.upstream/8.1.2
Diffstat (limited to 'docs/extending.txt')
-rw-r--r--docs/extending.txt550
1 files changed, 0 insertions, 550 deletions
diff --git a/docs/extending.txt b/docs/extending.txt
deleted file mode 100644
index bb94003..0000000
--- a/docs/extending.txt
+++ /dev/null
@@ -1,550 +0,0 @@
-.. title: Extending Nikola
-.. slug: extending
-.. date: 2012-03-30 23:00:00 UTC-03:00
-.. tags:
-.. link:
-.. description:
-
-Extending Nikola
-================
-
-:Version: 7.6.4
-:Author: Roberto Alsina <ralsina@netmanagers.com.ar>
-
-.. class:: alert alert-info pull-right
-
-.. contents::
-
-
-.. class:: lead
-
-Nikola is extensible. Almost all its functionality is based on plugins,
-and you can add your own or replace the provided ones.
-
-Plugins consist of a metadata file (with ``.plugin`` extension) and
-a Python module (a ``.py`` file) or package (a folder containing
-a ``__init__.py`` file.
-
-To use a plugin in your site, you just have to put it in a ``plugins``
-folder in your site.
-
-Plugins come in various flavours, aimed at extending different aspects
-of Nikola.
-
-Command Plugins
----------------
-
-When you run ``nikola --help`` you will see something like this:
-
-.. code-block:: console
-
- $ nikola help
- Nikola is a tool to create static websites and blogs. For full documentation and more
- information, please visit https://getnikola.com/
-
-
- Available commands:
- nikola auto automatically detect site changes, rebuild
- and optionally refresh a browser
- nikola bootswatch_theme given a swatch name from bootswatch.com and a
- parent theme, creates a custom theme
- nikola build run tasks
- nikola check check links and files in the generated site
- nikola clean clean action / remove targets
- nikola console start an interactive python console with access to
- your site and configuration
- nikola deploy deploy the site
- nikola dumpdb dump dependency DB
- nikola forget clear successful run status from internal DB
- nikola help show help
- nikola ignore ignore task (skip) on subsequent runs
- nikola import_blogger import a blogger dump
- nikola import_feed import a RSS/Atom dump
- nikola import_wordpress import a WordPress dump
- nikola init create a Nikola site in the specified folder
- nikola install_theme install theme into current site
- nikola list list tasks from dodo file
- nikola mincss apply mincss to the generated site
- nikola new_post create a new blog post or site page
- nikola run run tasks
- nikola serve start the test webserver
- nikola strace use strace to list file_deps and targets
- nikola version print the Nikola version number
-
- nikola help show help / reference
- nikola help <command> show command usage
- nikola help <task-name> show task usage
-
-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:
-
-First, the ``serve.plugin`` file:
-
-.. code-block:: ini
-
- [Core]
- Name = serve
- Module = serve
-
- [Documentation]
- Author = Roberto Alsina
- Version = 0.1
- Website = https://getnikola.com
- Description = Start test server.
-
-.. note:: If you want to publish your plugin on the Plugin Index, `read
- the docs for the Index
- <https://github.com/getnikola/plugins/blob/master/README.md>`__
- (and the .plugin file examples and explanations).
-
-For your own plugin, just change the values in a sensible way. The
-``Module`` will be used to find the matching Python module, in this case
-``serve.py``, from which this is the interesting bit:
-
-.. code-block:: python
-
- from nikola.plugin_categories import Command
-
- # You have to inherit Command for this to be a
- # command plugin:
-
- class CommandServe(Command):
- """Start test server."""
-
- name = "serve"
- doc_usage = "[options]"
- doc_purpose = "start the test webserver"
-
- cmd_options = (
- {
- 'name': 'port',
- 'short': 'p',
- 'long': 'port',
- 'default': 8000,
- 'type': int,
- 'help': 'Port nummber (default: 8000)',
- },
- {
- 'name': 'address',
- 'short': 'a',
- 'long': '--address',
- 'type': str,
- 'default': '127.0.0.1',
- 'help': 'Address to bind (default: 127.0.0.1)',
- },
- )
-
- def _execute(self, options, args):
- """Start test server."""
- out_dir = self.site.config['OUTPUT_FOLDER']
- if not os.path.isdir(out_dir):
- print("Error: Missing '{0}' folder?".format(out_dir))
- else:
- os.chdir(out_dir)
- httpd = HTTPServer((options['address'], options['port']),
- OurHTTPRequestHandler)
- sa = httpd.socket.getsockname()
- print("Serving HTTP on", sa[0], "port", sa[1], "...")
- httpd.serve_forever()
-
-As mentioned above, a plugin can have options, which the user can see by doing
-``nikola help command`` and can later use, for example:
-
-.. code-block:: console
-
- $ nikola help serve
- Purpose: start the test webserver
- Usage: nikola serve [options]
-
- Options:
- -p ARG, --port=ARG Port nummber (default: 8000)
- -a ARG, ----address=ARG Address to bind (default: 127.0.0.1)
-
- $ nikola serve -p 9000
- Serving HTTP on 127.0.0.1 port 9000 ...
-
-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 ;-)
-
-TemplateSystem Plugins
-----------------------
-
-Nikola supports Mako and Jinja2. If you prefer some other templating
-system, then you will have to write a TemplateSystem plugin. Here's how they work.
-First, you have to create a .plugin file. Here's the one for the Mako plugin:
-
-.. code-block:: ini
-
- [Core]
- Name = mako
- Module = mako
-
- [Documentation]
- Author = Roberto Alsina
- Version = 0.1
- Website = https://getnikola.com
- Description = Support for Mako templates.
-
-.. note:: If you want to publish your plugin on the Plugin Index, `read
- the docs for the Index
- <https://github.com/getnikola/plugins/blob/master/README.md>`__
- (and the .plugin file examples and explanations).
-
-You will have to replace "mako" with your template system's name, and other data
-in the obvious ways.
-
-The "Module" option is the name of the module, which has to look something like this,
-a stub for a hypothetical system called "Templater":
-
-.. code-block:: python
-
- from nikola.plugin_categories import TemplateSystem
-
- # You have to inherit TemplateSystem
-
- class TemplaterTemplates(TemplateSystem):
- """Wrapper for Templater templates."""
-
- # name has to match Name in the .plugin file
- name = "templater"
-
- # A list of directories where the templates will be
- # located. Most template systems have some sort of
- # template loading tool that can use this.
- def set_directories(self, directories, cache_folder):
- """Sets the list of folders where templates are located and cache."""
- pass
-
- # You *must* implement this, even if to return []
- # It should return a list of all the files that,
- # when changed, may affect the template's output.
- # usually this involves template inheritance and
- # inclusion.
- def template_deps(self, template_name):
- """Returns filenames which are dependencies for a template."""
- return []
-
- def render_template(self, template_name, output_name, context):
- """Renders template to a file using context.
-
- This must save the data to output_name *and* return it
- so that the caller may do additional processing.
- """
- pass
-
- # The method that does the actual rendering.
- # template_name is the name of the template file,
- # context is a dictionary containing the data the template
- # uses for rendering.
- def render_template_to_string(self, template, context):
- """Renders template to a string using context. """
- pass
-
- def inject_directory(self, directory):
- """Injects the directory with the lowest priority in the
- template search mechanism."""
- pass
-
-You can see a real example in `the Jinja plugin <https://github.com/getnikola/nikola/blob/master/nikola/plugins/template/jinja.py>`__
-
-Task Plugins
-------------
-
-If you want to do something that depends on the data in your site, you
-probably want to do a Task plugin, which will make it be part of the
-``nikola build`` command. There are the currently available tasks, all
-provided by plugins:
-T
-.. sidebar:: Other Tasks
-
- There are also ``LateTask`` plugins, which are executed later,
- and ``TaskMultiplier`` plugins that take a task and create
- more tasks out of it.
-
-.. code-block:: console
-
- $ nikola list
- Scanning posts....done!
- build_bundles
- build_less
- copy_assets
- copy_files
- post_render
- redirect
- render_archive
- render_galleries
- render_galleries_clean
- render_indexes
- render_listings
- render_pages
- render_posts
- render_rss
- render_site
- render_sources
- render_tags
- sitemap
-
-These have access to the ``site`` object which contains your timeline and
-your configuration.
-
-The critical bit of Task plugins is their ``gen_tasks`` method, which ``yields``
-`doit tasks <http://pydoit.org/tasks.html>`_.
-
-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 ``copy_assets`` task.
-First the ``task_copy_assets.plugin`` file, which you should copy and edit
-in the logical ways:
-
-.. code-block:: ini
-
- [Core]
- Name = copy_assets
- Module = task_copy_assets
-
- [Documentation]
- Author = Roberto Alsina
- Version = 0.1
- Website = https://getnikola.com
- Description = Copy theme assets into output.
-
-
-.. note:: If you want to publish your plugin on the Plugin Index, `read
- the docs for the Index
- <https://github.com/getnikola/plugins/blob/master/README.md>`_
- (and the .plugin file examples and explanations).
-
-And the ``task_copy_assets.py`` file, in its entirety:
-
-.. code-block:: python
-
- import os
-
- from nikola.plugin_categories import Task
- from nikola import utils
-
- # Have to inherit Task to be a task plugin
- class CopyAssets(Task):
- """Copy theme assets into output."""
-
- name = "copy_assets"
-
- # This yields the tasks
- def gen_tasks(self):
- """Create tasks to copy the assets of the whole theme chain.
-
- If a file is present on two themes, use the version
- from the "youngest" theme.
- """
-
- # I put all the configurations and data the plugin uses
- # in a dictionary because utils.config_changed will
- # make it so that if these change, this task will be
- # marked out of date, and run again.
-
- kw = {
- "themes": self.site.THEMES,
- "output_folder": self.site.config['OUTPUT_FOLDER'],
- "filters": self.site.config['FILTERS'],
- }
-
- tasks = {}
- for theme_name in kw['themes']:
- src = os.path.join(utils.get_theme_path(theme_name), 'assets')
- dst = os.path.join(kw['output_folder'], 'assets')
- for task in utils.copy_tree(src, dst):
- if task['name'] in tasks:
- continue
- tasks[task['name']] = task
- task['uptodate'] = task.get('uptodate', []) + \
- [utils.config_changed(kw)]
- task['basename'] = self.name
- # If your task generates files, please do this.
- yield utils.apply_filters(task, kw['filters'])
-
-PageCompiler Plugins
---------------------
-
-These plugins implement markup languages, they take sources for posts or pages and
-create HTML or other output files. A good example is `the misaka plugin. <https://github.com/getnikola/plugins/tree/master/v7/misaka>`__
-
-They must provide:
-
-``compile_html``
- Function that builds a file.
-
-``create_post``
- Function that creates an empty file with some metadata in it.
-
-If the compiler produces something other than HTML files, it should also implement ``extension`` which
-returns the preferred extension for the output file.
-
-These plugins can also be used to extract metadata from file. To do so, the
-plugin may implement ``read_metadata`` that will return a dict containing the
-metadata contained in the file.
-
-RestExtension Plugins
----------------------
-
-Implement directives for reStructuredText, see `media.py <https://github.com/getnikola/nikola/blob/master/nikola/plugins/compile/rest/media.py>`__ for a simple example.
-
-If your output depends on a config value, you need to make your post record a dependency on a pseudo-path, like this:
-
-.. code-block:: text
-
- ####MAGIC####CONFIG:OPTIONNAME
-
-Then, whenever the ``OPTIONNAME`` option is changed in conf.py, the file will be rebuilt.
-
-If your directive depends or may depend on the whole timeline (like the post-list directive, where adding new posts
-to the site could make it stale), you should record a dependency on the
-pseudo-path ``####MAGIC####TIMELINE``.
-
-MarkdownExtension Plugins
--------------------------
-
-Implement Markdown extensions, see `mdx_nikola.py <https://github.com/getnikola/nikola/blob/master/nikola/plugins/compile/markdown/mdx_nikola.py>`__ for a simple example.
-
-Note that python markdown extensions are often also available as separate packages. This is only meant to ship extensions
-along with Nikola.
-
-SignalHandler Plugins
----------------------
-
-These plugins extend the ``SignalHandler`` class and connect to one or more
-signals via `blinker <http://pythonhosted.org/blinker/>`_.
-
-The easiest way to do this is to reimplement ``set_site()`` and just connect to
-whatever signals you want there.
-
-Currently Nikola emits the following signals:
-
-``sighandlers_loaded``
- Right after SignalHandler plugin activation.
-``initialized``
- When all tasks are loaded.
-``configured``
- When all the configuration file is processed. Note that plugins are activated before this is emitted.
-``scanned``
- After posts are scanned.
-``new_post`` / ``new_page``
- When a new post is created, using the ``nikola new_post``/``nikola new_page`` commands. The signal
- data contains the path of the file, and the metadata file (if there is one).
-``existing_post`` / ``existing_page``
- When a new post fails to be created due to a title conflict. Contains the same data as ``new_post``.
-``deployed``
- When the ``nikola deploy`` command is run, and there is at least one new
- entry/post since ``last_deploy``. The signal data is of the form::
-
- {
- '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
- }
-
-One example is the `deploy_hooks plugin. <https://github.com/getnikola/plugins/tree/master/v6/deploy_hooks>`__
-
-ConfigPlugin Plugins
---------------------
-
-Does nothing specific, can be used to modify the site object (and thus the config).
-
-Put all the magic you want in ``set_site()``, and don’t forget to run the one
-from ``super()``. Example plugin: `navstories <https://github.com/getnikola/plugins/tree/master/v7/navstories>`__
-
-PostScanner Plugins
--------------------
-
-Get posts and stories from "somewhere" to be added to the timeline.
-The only currently existing plugin of this kind reads them from disk.
-
-
-Plugin Index
-============
-
-There is a `plugin index <https://plugins.getnikola.com/>`__, which stores all
-of the plugins for Nikola people wanted to share with the world.
-
-You may want to read the `README for the Index
-<https://github.com/getnikola/plugins/blob/master/README.md>`_ if you want to
-publish your package there.
-
-Path/Link Resolution Mechanism
-==============================
-
-Any plugin can register a function using ``Nikola.register_path_handler`` to
-allow resolution of paths and links. These are useful for templates, which
-can access them via _link.
-
-For example, you can always get a link to the path for the feed of the "foo" tag
-by using ``_link('tag_rss', 'foo')`` or the ``link://tag_rss/foo`` URL.
-
-Here's the relevant code from the tag plugin.
-
-.. code-block:: python
-
- # In set_site
- site.register_path_handler('tag_rss', self.tag_rss_path)
-
- # And these always take name and lang as arguments and returl a list of
- # path elements.
- def tag_rss_path(self, name, lang):
- return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
- self.site.config['TAG_PATH'], self.slugify_name(name) + ".xml"] if
- _f]
-
-Template Hooks
-==============
-
-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:
-
-* ``extra_head`` (not equal to the config option!)
-* ``body_end`` (not equal to the config option!)
-* ``page_header``
-* ``menu``
-* ``menu_alt`` (right-side menu in bootstrap, after ``menu`` in base)
-* ``page_footer``
-
-For example, in order to register a script into ``extra_head``:
-
-.. code-block:: python
-
- # In set_site
- site.template_hooks['extra_head'].append('<script src="/assets/js/fancyplugin.js">')
-
-There is also another API available. It allows use of dynamically generated
-HTML:
-
-.. code-block:: python
-
- # In set_site
- def generate_html_bit(name, ftype='js'):
- return '<script src="/assets/{t}/{n}.{t}">'.format(n=name, t=ftype)
-
- site.template_hooks['extra_head'].append(generate_html_bit, False, 'fancyplugin', type='js')
-
-
-The second argument to ``append()`` is used to determine whether the function
-needs access to the current template context and the site. If it it set to
-``True``, the function will also receive ``site`` and ``context`` keyword
-arguments. Example use:
-
-
-.. code-block:: python
-
- # In set_site
- def greeting(addr, endswith='', site=None, context=None):
- if context['lang'] == 'en':
- greet = u'Hello'
- elif context['lang'] == 'es':
- greet = u'¡Hola'
-
- t = u' BLOG_TITLE = {0}'.format(site.config['BLOG_TITLE'](context['lang']))
-
- return u'<h3>{greet} {addr}{endswith}</h3>'.format(greet=greet, addr=addr,
- endswith=endswith) + t
-
- site.template_hooks['page_header'].append(greeting, True, u'Nikola Tesla', endswith=u'!')