#!/usr/bin/env python # -*- coding: utf-8 -*- """ Twitter Bootstrap RST directives Plugin For Pelican =================================================== This plugin defines rst directives for different CSS and Javascript components from the twitter bootstrap framework. """ from uuid import uuid1 from cgi import escape from docutils import nodes, utils import docutils from docutils.parsers import rst from docutils.parsers.rst import directives, roles, Directive from pelican import signals from pelican.readers import RstReader, PelicanHTMLTranslator class CleanHTMLTranslator(PelicanHTMLTranslator): """ A custom HTML translator based on the Pelican HTML translator. Used to clean up some components html classes that could conflict with the bootstrap CSS classes. Also defines new tags that are not handleed by the current implementation of docutils. The most obvious example is the Container component """ def visit_literal(self, node): classes = node.get('classes', node.get('class', [])) if 'code' in classes: self.body.append(self.starttag(node, 'code')) elif 'kbd' in classes: self.body.append(self.starttag(node, 'kbd')) else: self.body.append(self.starttag(node, 'pre')) def depart_literal(self, node): classes = node.get('classes', node.get('class', [])) if 'code' in classes: self.body.append('\n') elif 'kbd' in classes: self.body.append('\n') else: self.body.append('\n') def visit_container(self, node): self.body.append(self.starttag(node, 'div')) class CleanRSTReader(RstReader): """ A custom RST reader that behaves exactly like its parent class RstReader with the difference that it uses the CleanHTMLTranslator """ def _get_publisher(self, source_path): extra_params = {'initial_header_level': '2', 'syntax_highlight': 'short', 'input_encoding': 'utf-8'} user_params = self.settings.get('DOCUTILS_SETTINGS') if user_params: extra_params.update(user_params) pub = docutils.core.Publisher( destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') pub.writer.translator_class = CleanHTMLTranslator pub.process_programmatic_settings(None, extra_params, None) pub.set_source(source_path=source_path) pub.publish() return pub def keyboard_role(name, rawtext, text, lineno, inliner, options={}, content=[]): """ This function creates an inline console input block as defined in the twitter bootstrap documentation overrides the default behaviour of the kbd role *usage:* :kbd:`` *Example:* :kbd:`
` This code is not highlighted """ new_element = nodes.literal(rawtext, text) new_element.set_class('kbd') return [new_element], [] def code_role(name, rawtext, text, lineno, inliner, options={}, content=[]): """ This function creates an inline code block as defined in the twitter bootstrap documentation overrides the default behaviour of the code role *usage:* :code:`` *Example:* :code:`
` This code is not highlighted """ new_element = nodes.literal(rawtext, text) new_element.set_class('code') return [new_element], [] def glyph_role(name, rawtext, text, lineno, inliner, options={}, content=[]): """ This function defines a glyph inline role that show a glyph icon from the twitter bootstrap framework *Usage:* :glyph:`` *Example:* Love this music :glyph:`music` :) Can be subclassed to include a target *Example:* .. role:: story_time_glyph(glyph) :target: http://www.youtube.com/watch?v=5g8ykQLYnX0 :class: small text-info Love this music :story_time_glyph:`music` :) """ target = options.get('target', None) glyph_name = 'glyphicon-{}'.format(text) if target: target = utils.unescape(target) new_element = nodes.reference(rawtext, ' ', refuri=target) else: new_element = nodes.container() classes = options.setdefault('class', []) classes += ['glyphicon', glyph_name] for custom_class in classes: new_element.set_class(custom_class) return [new_element], [] glyph_role.options = { 'target': rst.directives.unchanged, } glyph_role.content = False class Label(rst.Directive): ''' generic Label directive class definition. This class define a directive that shows bootstrap Labels around its content *usage:* .. label-::