__init__.py :  » Development » Docutils » docutils » docutils » writers » s5_html » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Docutils 
Docutils » docutils » docutils » writers » s5_html » __init__.py
# $Id: __init__.py 5889 2009-04-01 20:00:21Z gbrandl $
# Authors: Chris Liechti <cliechti@gmx.net>;
#          David Goodger <goodger@python.org>
# Copyright: This module has been placed in the public domain.

"""
S5/HTML Slideshow Writer.
"""

__docformat__ = 'reStructuredText'


import sys
import os
import re
import docutils
from docutils import frontend,nodes,utils
from docutils.writers import html4css1
from docutils.parsers.rst import directives
from docutils._compat import b

themes_dir_path = utils.relative_path(
    os.path.join(os.getcwd(), 'dummy'),
    os.path.join(os.path.dirname(__file__), 'themes'))

def find_theme(name):
    # Where else to look for a theme?
    # Check working dir?  Destination dir?  Config dir?  Plugins dir?
    path = os.path.join(themes_dir_path, name)
    if not os.path.isdir(path):
        raise docutils.ApplicationError(
            'Theme directory not found: %r (path: %r)' % (name, path))
    return path


class Writer(html4css1.Writer):

    settings_spec = html4css1.Writer.settings_spec + (
        'S5 Slideshow Specific Options',
        'For the S5/HTML writer, the --no-toc-backlinks option '
        '(defined in General Docutils Options above) is the default, '
        'and should not be changed.',
        (('Specify an installed S5 theme by name.  Overrides --theme-url.  '
          'The default theme name is "default".  The theme files will be '
          'copied into a "ui/<theme>" directory, in the same directory as the '
          'destination file (output HTML).  Note that existing theme files '
          'will not be overwritten (unless --overwrite-theme-files is used).',
          ['--theme'],
          {'default': 'default', 'metavar': '<name>',
           'overrides': 'theme_url'}),
         ('Specify an S5 theme URL.  The destination file (output HTML) will '
          'link to this theme; nothing will be copied.  Overrides --theme.',
          ['--theme-url'],
          {'metavar': '<URL>', 'overrides': 'theme'}),
         ('Allow existing theme files in the ``ui/<theme>`` directory to be '
          'overwritten.  The default is not to overwrite theme files.',
          ['--overwrite-theme-files'],
          {'action': 'store_true', 'validator': frontend.validate_boolean}),
         ('Keep existing theme files in the ``ui/<theme>`` directory; do not '
          'overwrite any.  This is the default.',
          ['--keep-theme-files'],
          {'dest': 'overwrite_theme_files', 'action': 'store_false'}),
         ('Set the initial view mode to "slideshow" [default] or "outline".',
          ['--view-mode'],
          {'choices': ['slideshow', 'outline'], 'default': 'slideshow',
           'metavar': '<mode>'}),
         ('Normally hide the presentation controls in slideshow mode. '
          'This is the default.',
          ['--hidden-controls'],
          {'action': 'store_true', 'default': True,
           'validator': frontend.validate_boolean}),
         ('Always show the presentation controls in slideshow mode.  '
          'The default is to hide the controls.',
          ['--visible-controls'],
          {'dest': 'hidden_controls', 'action': 'store_false'}),
         ('Enable the current slide indicator ("1 / 15").  '
          'The default is to disable it.',
          ['--current-slide'],
          {'action': 'store_true', 'validator': frontend.validate_boolean}),
         ('Disable the current slide indicator.  This is the default.',
          ['--no-current-slide'],
          {'dest': 'current_slide', 'action': 'store_false'}),))

    settings_default_overrides = {'toc_backlinks': 0}

    config_section = 's5_html writer'
    config_section_dependencies = ('writers', 'html4css1 writer')

    def __init__(self):
        html4css1.Writer.__init__(self)
        self.translator_class = S5HTMLTranslator


class S5HTMLTranslator(html4css1.HTMLTranslator):

    s5_stylesheet_template = """\
<!-- configuration parameters -->
<meta name="defaultView" content="%(view_mode)s" />
<meta name="controlVis" content="%(control_visibility)s" />
<!-- style sheet links -->
<script src="%(path)s/slides.js" type="text/javascript"></script>
<link rel="stylesheet" href="%(path)s/slides.css"
      type="text/css" media="projection" id="slideProj" />
<link rel="stylesheet" href="%(path)s/outline.css"
      type="text/css" media="screen" id="outlineStyle" />
<link rel="stylesheet" href="%(path)s/print.css"
      type="text/css" media="print" id="slidePrint" />
<link rel="stylesheet" href="%(path)s/opera.css"
      type="text/css" media="projection" id="operaFix" />\n"""
    # The script element must go in front of the link elements to
    # avoid a flash of unstyled content (FOUC), reproducible with
    # Firefox.

    disable_current_slide = """
<style type="text/css">
#currentSlide {display: none;}
</style>\n"""

    layout_template = """\
<div class="layout">
<div id="controls"></div>
<div id="currentSlide"></div>
<div id="header">
%(header)s
</div>
<div id="footer">
%(title)s%(footer)s
</div>
</div>\n"""
# <div class="topleft"></div>
# <div class="topright"></div>
# <div class="bottomleft"></div>
# <div class="bottomright"></div>

    default_theme = 'default'
    """Name of the default theme."""

    base_theme_file = '__base__'
    """Name of the file containing the name of the base theme."""

    direct_theme_files = (
        'slides.css', 'outline.css', 'print.css', 'opera.css', 'slides.js')
    """Names of theme files directly linked to in the output HTML"""

    indirect_theme_files = (
        's5-core.css', 'framing.css', 'pretty.css', 'blank.gif', 'iepngfix.htc')
    """Names of files used indirectly; imported or used by files in
    `direct_theme_files`."""

    required_theme_files = indirect_theme_files + direct_theme_files
    """Names of mandatory theme files."""

    def __init__(self, *args):
        html4css1.HTMLTranslator.__init__(self, *args)
        #insert S5-specific stylesheet and script stuff:
        self.theme_file_path = None
        self.setup_theme()
        view_mode = self.document.settings.view_mode
        control_visibility = ('visible', 'hidden')[self.document.settings
                                                   .hidden_controls]
        self.stylesheet.append(self.s5_stylesheet_template
                               % {'path': self.theme_file_path,
                                  'view_mode': view_mode,
                                  'control_visibility': control_visibility})
        if not self.document.settings.current_slide:
            self.stylesheet.append(self.disable_current_slide)
        self.add_meta('<meta name="version" content="S5 1.1" />\n')
        self.s5_footer = []
        self.s5_header = []
        self.section_count = 0
        self.theme_files_copied = None

    def setup_theme(self):
        if self.document.settings.theme:
            self.copy_theme()
        elif self.document.settings.theme_url:
            self.theme_file_path = self.document.settings.theme_url
        else:
            raise docutils.ApplicationError(
                'No theme specified for S5/HTML writer.')

    def copy_theme(self):
        """
        Locate & copy theme files.

        A theme may be explicitly based on another theme via a '__base__'
        file.  The default base theme is 'default'.  Files are accumulated
        from the specified theme, any base themes, and 'default'.
        """
        settings = self.document.settings
        path = find_theme(settings.theme)
        theme_paths = [path]
        self.theme_files_copied = {}
        required_files_copied = {}
        # This is a link (URL) in HTML, so we use "/", not os.sep:
        self.theme_file_path = '%s/%s' % ('ui', settings.theme)
        if settings._destination:
            dest = os.path.join(
                os.path.dirname(settings._destination), 'ui', settings.theme)
            if not os.path.isdir(dest):
                os.makedirs(dest)
        else:
            # no destination, so we can't copy the theme
            return
        default = 0
        while path:
            for f in os.listdir(path):  # copy all files from each theme
                if f == self.base_theme_file:
                    continue            # ... except the "__base__" file
                if ( self.copy_file(f, path, dest)
                     and f in self.required_theme_files):
                    required_files_copied[f] = 1
            if default:
                break                   # "default" theme has no base theme
            # Find the "__base__" file in theme directory:
            base_theme_file = os.path.join(path, self.base_theme_file)
            # If it exists, read it and record the theme path:
            if os.path.isfile(base_theme_file):
                lines = open(base_theme_file).readlines()
                for line in lines:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        path = find_theme(line)
                        if path in theme_paths: # check for duplicates (cycles)
                            path = None         # if found, use default base
                        else:
                            theme_paths.append(path)
                        break
                else:                   # no theme name found
                    path = None         # use default base
            else:                       # no base theme file found
                path = None             # use default base
            if not path:
                path = find_theme(self.default_theme)
                theme_paths.append(path)
                default = 1
        if len(required_files_copied) != len(self.required_theme_files):
            # Some required files weren't found & couldn't be copied.
            required = list(self.required_theme_files)
            for f in required_files_copied.keys():
                required.remove(f)
            raise docutils.ApplicationError(
                'Theme files not found: %s'
                % ', '.join(['%r' % f for f in required]))

    files_to_skip_pattern = re.compile(r'~$|\.bak$|#$|\.cvsignore$')

    def copy_file(self, name, source_dir, dest_dir):
        """
        Copy file `name` from `source_dir` to `dest_dir`.
        Return 1 if the file exists in either `source_dir` or `dest_dir`.
        """
        source = os.path.join(source_dir, name)
        dest = os.path.join(dest_dir, name)
        if dest in self.theme_files_copied:
            return 1
        else:
            self.theme_files_copied[dest] = 1
        if os.path.isfile(source):
            if self.files_to_skip_pattern.search(source):
                return None
            settings = self.document.settings
            if os.path.exists(dest) and not settings.overwrite_theme_files:
                settings.record_dependencies.add(dest)
            else:
                src_file = open(source, 'rb')
                src_data = src_file.read()
                src_file.close()
                dest_file = open(dest, 'wb')
                dest_dir = dest_dir.replace(os.sep, '/')
                dest_file.write(src_data.replace(
                    b('ui/default'),
                    dest_dir[dest_dir.rfind('ui/'):].encode(
                    sys.getfilesystemencoding())))
                dest_file.close()
                settings.record_dependencies.add(source)
            return 1
        if os.path.isfile(dest):
            return 1

    def depart_document(self, node):
        header = ''.join(self.s5_header)
        footer = ''.join(self.s5_footer)
        title = ''.join(self.html_title).replace('<h1 class="title">', '<h1>')
        layout = self.layout_template % {'header': header,
                                         'title': title,
                                         'footer': footer}
        self.fragment.extend(self.body)
        self.body_prefix.extend(layout)
        self.body_prefix.append('<div class="presentation">\n')
        self.body_prefix.append(
            self.starttag({'classes': ['slide'], 'ids': ['slide0']}, 'div'))
        if not self.section_count:
            self.body.append('</div>\n')
        self.body_suffix.insert(0, '</div>\n')
        # skip content-type meta tag with interpolated charset value:
        self.html_head.extend(self.head[1:])
        self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
                              + self.docinfo + self.body
                              + self.body_suffix[:-1])

    def depart_footer(self, node):
        start = self.context.pop()
        self.s5_footer.append('<h2>')
        self.s5_footer.extend(self.body[start:])
        self.s5_footer.append('</h2>')
        del self.body[start:]

    def depart_header(self, node):
        start = self.context.pop()
        header = ['<div id="header">\n']
        header.extend(self.body[start:])
        header.append('\n</div>\n')
        del self.body[start:]
        self.s5_header.extend(header)

    def visit_section(self, node):
        if not self.section_count:
            self.body.append('\n</div>\n')
        self.section_count += 1
        self.section_level += 1
        if self.section_level > 1:
            # dummy for matching div's
            self.body.append(self.starttag(node, 'div', CLASS='section'))
        else:
            self.body.append(self.starttag(node, 'div', CLASS='slide'))

    def visit_subtitle(self, node):
        if isinstance(node.parent, nodes.section):
            level = self.section_level + self.initial_header_level - 1
            if level == 1:
                level = 2
            tag = 'h%s' % level
            self.body.append(self.starttag(node, tag, ''))
            self.context.append('</%s>\n' % tag)
        else:
            html4css1.HTMLTranslator.visit_subtitle(self, node)

    def visit_title(self, node):
        html4css1.HTMLTranslator.visit_title(self, node)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.