diff options
Diffstat (limited to 'docs/extending.txt')
| -rw-r--r-- | docs/extending.txt | 269 |
1 files changed, 202 insertions, 67 deletions
diff --git a/docs/extending.txt b/docs/extending.txt index 750ec98..f5c7aae 100644 --- a/docs/extending.txt +++ b/docs/extending.txt @@ -1,7 +1,14 @@ +.. title: Extending Nikola +.. slug: extending +.. date: 2012/03/30 23:00 +.. tags: +.. link: +.. description: + Extending Nikola ================ -:Version: 5 +:Version: 6.2.1 :Author: Roberto Alsina <ralsina@netmanagers.com.ar> .. class:: alert alert-info pull-right @@ -9,11 +16,6 @@ Extending Nikola .. contents:: -.. note:: This is a draft - - I am not sure of the best way to do some things, including how - to document this. Suggestions are welcome. - Nikola is extensible. Almost all its functionality is based on plugins, and you can add your own or replace the provided ones. @@ -32,20 +34,42 @@ Command Plugins When you run ``nikola --help`` you will see something like this:: - $ nikola --help - Usage: nikola command [options] + $ nikola help + Nikola is a tool to create static websites and blogs. For full documentation and more + information, please visit http://getnikola.com - Available commands: - nikola bootswatch_theme: Given a swatch name and a parent theme, creates a custom theme. - nikola build: Build the site. - nikola import_wordpress: Import a wordpress site from a XML dump. - nikola init: Create a new site. - nikola install_theme: Install a theme into the current site. - nikola new_post: Create a new post. - nikola serve: Start test server. - - For detailed help for a command, use nikola command --help + 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: @@ -56,17 +80,22 @@ First, the ``command_serve.plugin`` file: [Core] Name = serve - Module = command_serve + Module = serve [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://nikola.ralsina.com.ar + Website = http://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 -``command_serve.py``, from which this is the interesting bit: +``serve.py``, from which this is the interesting bit: .. code-block:: python @@ -78,57 +107,52 @@ For your own plugin, just change the values in a sensible way. The class CommandBuild(Command): """Start test server.""" - # This has to match the Name option in the .plugin file - name = "serve" - - # This is the function that does stuff - - def run(self, *args): + 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.""" - - # use OptionParser if you want your command to have options - - parser = OptionParser(usage="nikola %s [options]" % self.name) - parser.add_option("-p", "--port", dest="port", - help="Port numer (default: 8000)", default=8000, - type="int") - parser.add_option("-a", "--address", dest="address", - help="Address to bind (default: 127.0.0.1)", - default='127.0.0.1') - (options, args) = parser.parse_args(list(args)) - - # You can use self.site.config to access your - # configuration options. self.site is an instance - # of the Nikola class and contains all your site's - # data. - out_dir = self.site.config['OUTPUT_FOLDER'] - - # Then do something interesting. In this case, - # it starts a webserver - if not os.path.isdir(out_dir): - print "Error: Missing '%s' folder?" % out_dir + print("Error: Missing '{0}' folder?".format(out_dir)) else: os.chdir(out_dir) - httpd = HTTPServer((options.address, options.port), - OurHTTPRequestHandler) + httpd = HTTPServer((options['address'], options['port']), + OurHTTPRequestHandler) sa = httpd.socket.getsockname() - print "Serving HTTP on", sa[0], "port", sa[1], "..." + 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 command --help`` and can later use as ``nikola command --option``:: +``nikola help command`` and can later use, for example:: - $ nikola serve --help - Usage: nikola serve [options] + $ nikola help serve + Purpose: start the test webserver + Usage: nikola serve [options] Options: - -h, --help show this help message and exit - -p PORT, --port=PORT Port numer (default: 8000) - -a ADDRESS, --address=ADDRESS - Address to bind (default: 127.0.0.1) + -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 ... @@ -148,14 +172,19 @@ First, you have to create a .plugin file. Here's the one for the Mako plugin: [Core] Name = mako - Module = template_mako + Module = mako [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://nikola.ralsina.com.ar + Website = http://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. @@ -187,13 +216,13 @@ a stub for a hypothetical system called "Templater": # template loading tool that can use this. def set_directories(self, directories): - """Createa template lookup.""" + """Create a template lookup.""" pass # The method that does the actual rendering. # template_name is the name of the template file, # output_name is the file for the output, context - # is a dictionary containing the data the template + # is a dictionary containing the data the template # uses for rendering. def render_template(self, template_name, output_name, @@ -208,17 +237,27 @@ 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:: +provided by plugins: - $ nikola list +.. 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. +:: + + $ nikola list + Scanning posts....done! build_bundles + build_less copy_assets copy_files - deploy + post_render redirect render_archive render_galleries + render_galleries_clean render_indexes render_listings render_pages @@ -249,9 +288,15 @@ in the logical ways: [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://nikola.ralsina.com.ar + Website = http://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 @@ -299,3 +344,93 @@ And the ``task_copy_assets.py`` file, in its entirety: 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. + +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. + +RestExtension Plugins +--------------------- + +Implement directives for reStructuredText, see ``media.py`` for a simple example. + +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`` + Right after plugin activation +``configured`` + When all the configuration file is processed. Note that plugins are activated before this is emitted. +``new_post`` + When a new post is created, using the ``nikola new_post`` command. The signal + data contains the path of the file, and the metadata file (if there is one). +``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 + } + + +Plugin Index +============ + +There is a `plugin index <http://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] + |
