123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- # -----------------------------------------------------------------------------
- # Bootstrap RST
- # Copyright (c) 2014, Nicolas P. Rougier
- # Distributed under the (new) BSD License. See LICENSE.txt for more info.
- # -----------------------------------------------------------------------------
- import sys, os, re
- from docutils import nodes, utils
- from docutils.parsers.rst.directives import images
- from docutils.transforms import TransformError, Transform, parts
- from docutils.parsers.rst import Directive, directives, states, roles
- from docutils.nodes import fully_normalize_name, whitespace_normalize_name
- from docutils.parsers.rst.roles import set_classes
- from docutils.io import StringOutput
- from docutils.core import Publisher
- from pelican import signals
- from pelican.readers import RstReader, PelicanHTMLTranslator
- from .roles import *
- from .directives import *
- class HTMLTranslator(PelicanHTMLTranslator):
- """
- This is a translator class for the docutils system.
- """
- def visit_h1(self, node):
- self.body.append('<h1>%s</h1>' % node.children[0])
- raise nodes.SkipNode
- def visit_h2(self, node):
- self.body.append('<h2>%s</h2>' % node.children[0])
- raise nodes.SkipNode
- def visit_h3(self, node):
- self.body.append('<h3>%s</h3>' % node.children[0])
- raise nodes.SkipNode
- def visit_h4(self, node):
- self.body.append('<h4>%s</h4>' % node.children[0])
- raise nodes.SkipNode
- def visit_h5(self, node):
- self.body.append('<h5>%s</h5>' % node.children[0])
- raise nodes.SkipNode
- def visit_h6(self, node):
- self.body.append('<h6>%s</h6>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_default(self, node):
- self.body.append(
- '<span class="label label-default">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_primary(self, node):
- self.body.append(
- '<span class="label label-primary">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_success(self, node):
- self.body.append(
- '<span class="label label-success">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_info(self, node):
- self.body.append(
- '<span class="label label-info">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_warning(self, node):
- self.body.append(
- '<span class="label label-warning">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_label_danger(self, node):
- self.body.append(
- '<span class="label label-danger">%s</span>' % node.children[0])
- raise nodes.SkipNode
- def visit_page_row(self, node):
- self.body.append(self.starttag(node,'div'))
- def depart_page_row(self, node):
- self.body.append('</div>\n')
- def visit_page_column(self, node):
- self.body.append(self.starttag(node,'div'))
- def depart_page_column(self, node):
- self.body.append('</div>\n')
- def visit_button(self, node):
- btn_classes = { 'primary' : 'btn-primary', 'success' : 'btn-success',
- 'info' : 'btn-info', 'warning' : 'btn-warning',
- 'danger' : 'btn-danger', 'link' : 'btn-link',
- 'outline' : 'btn-outline', 'tiny' : 'btn-xs',
- 'small' : 'btn-sm', 'large' : 'btn-lg',
- 'block' : 'btn-block', 'active' : 'btn-active' }
- classes = 'btn '
- flag = False
- for node_class in node['classes']:
- if node_class in ['primary', 'success', 'warning'
- 'info', 'link', 'danger', 'outline']:
- flag = True
- btn_class = btn_classes.get(node_class, None)
- if btn_class:
- classes += btn_class + ' '
- if flag == False:
- classes += 'btn-default'
- target = node['target']
- properties = ''
- # Disabled
- if 'disabled' in node['classes']:
- if target:
- properties += ' disabled="disabled"'
- else:
- classes += ' disabled'
- # Data toggle
- if 'toggle' in node['classes']:
- classes += ' dropdown-toggle '
- properties += ' data-toggle="dropdown"'
- if target:
- properties += ' role="button"'
- anchor = '<a href="%s" class="%s" %s>' % (target,classes,properties)
- self.body.append(anchor)
- else:
- properties += ' type="button"'
- button = '<button class="%s" %s>' % (classes,properties)
- self.body.append(button)
- def depart_button(self, node):
- if node['target']:
- self.body.append('</a>\n')
- else:
- self.body.append('</button>\n')
- def visit_progress(self, node):
- prg_classes = { 'success' : 'progress-bar-success',
- 'info' : 'progress-bar-info',
- 'warning' : 'progress-bar-warning',
- 'danger' : 'progress-bar-danger' }
- label = node['label']
- classes = 'progress-bar'
- flag = False
- for nodeclass in node['classes']:
- flag = True
- classes += ' ' + prg_classes.get(nodeclass, '')
- if flag == False:
- classes += ' progress-bar-default'
- properties = 'role="progress-bar"'
- properties += ' aria-valuenow="%d"' % int(node['value'])
- properties += ' aria-valuemin="%d"' % int(node['value_min'])
- properties += ' aria-valuemax="%d"' % int(node['value_max'])
- properties += ' style="width: %d%%";' % int(node['value'])
- if 'active' in node['classes']:
- self.body.append('<div class="progress progress-striped active">')
- elif 'striped' in node['classes']:
- self.body.append('<div class="progress progress-striped">')
- else:
- self.body.append('<div class="progress">')
- self.body.append(
- '<div class="%s" %s>%s</div>' % (classes,properties,label))
- self.body.append('</div>')
- raise nodes.SkipNode
- def visit_alert(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='alert'))
- if node.dismissable:
- self.body.append(
- u"""<button type="button" class="close" data-dismiss="alert" """
- u"""aria-hidden="true">×</button>""")
- def depart_alert(self, node):
- self.body.append('</div>\n')
- def visit_callout(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='bs-callout'))
- def depart_callout(self, node):
- self.body.append('</div>\n')
- # overwritten
- def visit_definition_list(self, node):
- list_class = node.parent.get('list-class', [])
- list_class.append('docutils')
- list_class = ' '.join(list_class)
- self.body.append(self.starttag(node, 'dl', CLASS=list_class))
- # overwritten
- def visit_sidebar(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='col-md-3 col-md-push-9'))
- self.body.append(self.starttag(node, 'div', CLASS='bs-docs-sidebar hidden-print affix-top'))
- self.body.append(self.starttag(node, 'div', CLASS='sidebar'))
- self.set_first_last(node)
- self.in_sidebar = True
- # overwritten
- def depart_sidebar(self, node):
- self.body.append('</div>\n')
- self.body.append('</div>\n')
- self.body.append('</div>\n')
- # Opening tag for body
- self.body.append(self.starttag(node, 'div', CLASS='col-md-9 col-md-pull-3'))
- self.in_sidebar = False
- # overwritten : removed compact paragraph
- # def visit_paragraph(self, node):
- # if self.should_be_compact_paragraph(node):
- # self.context.append('')
- # else:
- # self.body.append(self.starttag(node, 'p', ''))
- # self.context.append('</p>\n')
- # overwritten: remove border=1, replace docutils/table class
- def visit_table(self, node):
- self.context.append(self.compact_p)
- self.compact_p = True
- #classes = ' '.join(['docutils', self.settings.table_style]).strip()
- classes = ' '.join(['table', self.settings.table_style]).strip()
- self.body.append(self.starttag(node, 'table', CLASS=classes))
- # overwritten : removed 'container' class
- def visit_container(self, node):
- self.body.append(self.starttag(node, 'div', CLASS=''))
- # overwritten: get rid of <hr> tag
- def depart_header(self, node):
- start = self.context.pop()
- header = [self.starttag(node, 'div', CLASS='header')]
- header.extend(self.body[start:])
- header.append('\n</div>\n')
- self.body_prefix.extend(header)
- self.header.extend(header)
- del self.body[start:]
- # overwritten: get rid of <hr> tag
- def depart_footer(self, node):
- start = self.context.pop()
- footer = [self.starttag(node, 'div', CLASS='footer')]
- footer.extend(self.body[start:])
- footer.append('\n</div>\n')
- self.footer.extend(footer)
- self.body_suffix[:0] = footer
- del self.body[start:]
- # overwritten
- def depart_document(self, node):
- self.head_prefix.extend([self.doctype,
- self.head_prefix_template %
- {'lang': self.settings.language_code}])
- self.html_prolog.append(self.doctype)
- self.meta.insert(0, self.content_type % self.settings.output_encoding)
- self.head.insert(0, self.content_type % self.settings.output_encoding)
- if self.math_header:
- self.head.append(self.math_header)
- # skip content-type meta tag with interpolated charset value:
- self.html_head.extend(self.head[1:])
- # self.body_prefix.append(self.starttag(node, 'div', CLASS='document'))
- self.body_prefix.append(self.starttag(node, 'div', CLASS='container'))
- # self.body_suffix.insert(0, '</div>\n')
- self.fragment.extend(self.body) # self.fragment is the "naked" body
- self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
- + self.docinfo + self.body
- + self.body_suffix[:-1])
- assert not self.context, 'len(context) = %s' % len(self.context)
- # -----------------------------------------------------------------------------
- class RSTReader(RstReader):
- """
- A custom RST reader that behaves exactly like its parent class RstReader
- with the difference that it uses our HTMLTranslator
- """
- 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 = Publisher(destination_class=StringOutput)
- pub.set_components('standalone', 'restructuredtext', 'html')
- pub.writer.translator_class = HTMLTranslator
- pub.process_programmatic_settings(None, extra_params, None)
- pub.set_source(source_path=source_path)
- pub.publish()
- return pub
- def add_reader(readers):
- readers.reader_classes['rst'] = RSTReader
- def register():
- signals.readers_init.connect(add_reader)
|