root/galaxy-central/eggs/docutils-0.4-py2.6.egg/docutils/writers/s5_html/__init__.py @ 3

リビジョン 3, 12.7 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# Author: Chris Liechti
2# Contact: cliechti@gmx.net
3# Author: David Goodger
4# Contact: goodger@python.org
5# Revision: $Revision: 4223 $
6# Date: $Date: 2005-12-18 00:52:30 +0100 (Sun, 18 Dec 2005) $
7# Copyright: This module has been placed in the public domain.
8
9"""
10S5/HTML Slideshow Writer.
11"""
12
13__docformat__ = 'reStructuredText'
14
15
16import sys
17import os
18import re
19import docutils
20from docutils import frontend, nodes, utils
21from docutils.writers import html4css1
22from docutils.parsers.rst import directives
23
24themes_dir_path = utils.relative_path(
25    os.path.join(os.getcwd(), 'dummy'),
26    os.path.join(os.path.dirname(__file__), 'themes'))
27
28def find_theme(name):
29    # Where else to look for a theme?
30    # Check working dir?  Destination dir?  Config dir?  Plugins dir?
31    path = os.path.join(themes_dir_path, name)
32    if not os.path.isdir(path):
33        raise docutils.ApplicationError(
34            'Theme directory not found: %r (path: %r)' % (name, path))
35    return path
36
37
38class Writer(html4css1.Writer):
39
40    settings_spec = html4css1.Writer.settings_spec + (
41        'S5 Slideshow Specific Options',
42        'For the S5/HTML writer, the --no-toc-backlinks option '
43        '(defined in General Docutils Options above) is the default, '
44        'and should not be changed.',
45        (('Specify an installed S5 theme by name.  Overrides --theme-url.  '
46          'The default theme name is "default".  The theme files will be '
47          'copied into a "ui/<theme>" directory, in the same directory as the '
48          'destination file (output HTML).  Note that existing theme files '
49          'will not be overwritten (unless --overwrite-theme-files is used).',
50          ['--theme'],
51          {'default': 'default', 'metavar': '<name>',
52           'overrides': 'theme_url'}),
53         ('Specify an S5 theme URL.  The destination file (output HTML) will '
54          'link to this theme; nothing will be copied.  Overrides --theme.',
55          ['--theme-url'],
56          {'metavar': '<URL>', 'overrides': 'theme'}),
57         ('Allow existing theme files in the ``ui/<theme>`` directory to be '
58          'overwritten.  The default is not to overwrite theme files.',
59          ['--overwrite-theme-files'],
60          {'action': 'store_true'}),
61         ('Keep existing theme files in the ``ui/<theme>`` directory; do not '
62          'overwrite any.  This is the default.',
63          ['--keep-theme-files'],
64          {'dest': 'overwrite_theme_files', 'action': 'store_false'}),
65         ('Enable the current slide indicator ("1 / 15").  '
66          'The default is to disable it.',
67          ['--current-slide'],
68          {'action': 'store_true'}),
69         ('Disable the current slide indicator.  This is the default.',
70          ['--no-current-slide'],
71          {'dest': 'current_slide', 'action': 'store_false'}),))
72
73    settings_default_overrides = {'toc_backlinks': 0}
74
75    config_section = 's5_html writer'
76    config_section_dependencies = ('writers', 'html4css1 writer')
77
78    def __init__(self):
79        html4css1.Writer.__init__(self)
80        self.translator_class = S5HTMLTranslator
81
82
83class S5HTMLTranslator(html4css1.HTMLTranslator):
84
85    doctype = (
86        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
87        ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
88
89    s5_stylesheet_template = """\
90<!-- configuration parameters -->
91<meta name="defaultView" content="slideshow" />
92<meta name="controlVis" content="hidden" />
93<!-- style sheet links -->
94<script src="%(path)s/slides.js" type="text/javascript"></script>
95<link rel="stylesheet" href="%(path)s/slides.css"
96      type="text/css" media="projection" id="slideProj" />
97<link rel="stylesheet" href="%(path)s/outline.css"
98      type="text/css" media="screen" id="outlineStyle" />
99<link rel="stylesheet" href="%(path)s/print.css"
100      type="text/css" media="print" id="slidePrint" />
101<link rel="stylesheet" href="%(path)s/opera.css"
102      type="text/css" media="projection" id="operaFix" />\n"""
103    # The script element must go in front of the link elements to
104    # avoid a flash of unstyled content (FOUC), reproducible with
105    # Firefox.
106
107    disable_current_slide = """
108<style type="text/css">
109#currentSlide {display: none;}
110</style>\n"""
111
112    layout_template = """\
113<div class="layout">
114<div id="controls"></div>
115<div id="currentSlide"></div>
116<div id="header">
117%(header)s
118</div>
119<div id="footer">
120%(title)s%(footer)s
121</div>
122</div>\n"""
123# <div class="topleft"></div>
124# <div class="topright"></div>
125# <div class="bottomleft"></div>
126# <div class="bottomright"></div>
127
128    default_theme = 'default'
129    """Name of the default theme."""
130
131    base_theme_file = '__base__'
132    """Name of the file containing the name of the base theme."""
133
134    direct_theme_files = (
135        'slides.css', 'outline.css', 'print.css', 'opera.css', 'slides.js')
136    """Names of theme files directly linked to in the output HTML"""
137
138    indirect_theme_files = (
139        's5-core.css', 'framing.css', 'pretty.css', 'blank.gif', 'iepngfix.htc')
140    """Names of files used indirectly; imported or used by files in
141    `direct_theme_files`."""
142
143    required_theme_files = indirect_theme_files + direct_theme_files
144    """Names of mandatory theme files."""
145
146    def __init__(self, *args):
147        html4css1.HTMLTranslator.__init__(self, *args)
148        #insert S5-specific stylesheet and script stuff:
149        self.theme_file_path = None
150        self.setup_theme()
151        self.stylesheet.append(self.s5_stylesheet_template
152                               % {'path': self.theme_file_path})
153        if not self.document.settings.current_slide:
154            self.stylesheet.append(self.disable_current_slide)
155        self.add_meta('<meta name="version" content="S5 1.1" />\n')
156        self.s5_footer = []
157        self.s5_header = []
158        self.section_count = 0
159        self.theme_files_copied = None
160
161    def setup_theme(self):
162        if self.document.settings.theme:
163            self.copy_theme()
164        elif self.document.settings.theme_url:
165            self.theme_file_path = self.document.settings.theme_url
166        else:
167            raise docutils.ApplicationError(
168                'No theme specified for S5/HTML writer.')
169
170    def copy_theme(self):
171        """
172        Locate & copy theme files.
173
174        A theme may be explicitly based on another theme via a '__base__'
175        file.  The default base theme is 'default'.  Files are accumulated
176        from the specified theme, any base themes, and 'default'.
177        """
178        settings = self.document.settings
179        path = find_theme(settings.theme)
180        theme_paths = [path]
181        self.theme_files_copied = {}
182        required_files_copied = {}
183        # This is a link (URL) in HTML, so we use "/", not os.sep:
184        self.theme_file_path = '%s/%s' % ('ui', settings.theme)
185        if settings._destination:
186            dest = os.path.join(
187                os.path.dirname(settings._destination), 'ui', settings.theme)
188            if not os.path.isdir(dest):
189                os.makedirs(dest)
190        else:
191            # no destination, so we can't copy the theme
192            return
193        default = 0
194        while path:
195            for f in os.listdir(path):  # copy all files from each theme
196                if f == self.base_theme_file:
197                    continue            # ... except the "__base__" file
198                if ( self.copy_file(f, path, dest)
199                     and f in self.required_theme_files):
200                    required_files_copied[f] = 1
201            if default:
202                break                   # "default" theme has no base theme
203            # Find the "__base__" file in theme directory:
204            base_theme_file = os.path.join(path, self.base_theme_file)
205            # If it exists, read it and record the theme path:
206            if os.path.isfile(base_theme_file):
207                lines = open(base_theme_file).readlines()
208                for line in lines:
209                    line = line.strip()
210                    if line and not line.startswith('#'):
211                        path = find_theme(line)
212                        if path in theme_paths: # check for duplicates (cycles)
213                            path = None         # if found, use default base
214                        else:
215                            theme_paths.append(path)
216                        break
217                else:                   # no theme name found
218                    path = None         # use default base
219            else:                       # no base theme file found
220                path = None             # use default base
221            if not path:
222                path = find_theme(self.default_theme)
223                theme_paths.append(path)
224                default = 1
225        if len(required_files_copied) != len(self.required_theme_files):
226            # Some required files weren't found & couldn't be copied.
227            required = list(self.required_theme_files)
228            for f in required_files_copied.keys():
229                required.remove(f)
230            raise docutils.ApplicationError(
231                'Theme files not found: %s'
232                % ', '.join(['%r' % f for f in required]))
233
234    files_to_skip_pattern = re.compile(r'~$|\.bak$|#$|\.cvsignore$')
235
236    def copy_file(self, name, source_dir, dest_dir):
237        """
238        Copy file `name` from `source_dir` to `dest_dir`.
239        Return 1 if the file exists in either `source_dir` or `dest_dir`.
240        """
241        source = os.path.join(source_dir, name)
242        dest = os.path.join(dest_dir, name)
243        if self.theme_files_copied.has_key(dest):
244            return 1
245        else:
246            self.theme_files_copied[dest] = 1
247        if os.path.isfile(source):
248            if self.files_to_skip_pattern.search(source):
249                return None
250            settings = self.document.settings
251            if os.path.exists(dest) and not settings.overwrite_theme_files:
252                settings.record_dependencies.add(dest)
253            else:
254                src_file = open(source, 'rb')
255                src_data = src_file.read()
256                src_file.close()
257                dest_file = open(dest, 'wb')
258                dest_dir = dest_dir.replace(os.sep, '/')
259                dest_file.write(src_data.replace(
260                    'ui/default', dest_dir[dest_dir.rfind('ui/'):]))
261                dest_file.close()
262                settings.record_dependencies.add(source)
263            return 1
264        if os.path.isfile(dest):
265            return 1
266
267    def depart_document(self, node):
268        header = ''.join(self.s5_header)
269        footer = ''.join(self.s5_footer)
270        title = ''.join(self.html_title).replace('<h1 class="title">', '<h1>')
271        layout = self.layout_template % {'header': header,
272                                         'title': title,
273                                         'footer': footer}
274        self.fragment.extend(self.body)
275        self.body_prefix.extend(layout)
276        self.body_prefix.append('<div class="presentation">\n')
277        self.body_prefix.append(
278            self.starttag({'classes': ['slide'], 'ids': ['slide0']}, 'div'))
279        if not self.section_count:
280            self.body.append('</div>\n')
281        self.body_suffix.insert(0, '</div>\n')
282        # skip content-type meta tag with interpolated charset value:
283        self.html_head.extend(self.head[1:])
284        self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
285                              + self.docinfo + self.body
286                              + self.body_suffix[:-1])
287
288    def depart_footer(self, node):
289        start = self.context.pop()
290        self.s5_footer.append('<h2>')
291        self.s5_footer.extend(self.body[start:])
292        self.s5_footer.append('</h2>')
293        del self.body[start:]
294
295    def depart_header(self, node):
296        start = self.context.pop()
297        header = ['<div id="header">\n']
298        header.extend(self.body[start:])
299        header.append('\n</div>\n')
300        del self.body[start:]
301        self.s5_header.extend(header)
302
303    def visit_section(self, node):
304        if not self.section_count:
305            self.body.append('\n</div>\n')
306        self.section_count += 1
307        self.section_level += 1
308        if self.section_level > 1:
309            # dummy for matching div's
310            self.body.append(self.starttag(node, 'div', CLASS='section'))
311        else:
312            self.body.append(self.starttag(node, 'div', CLASS='slide'))
313
314    def visit_subtitle(self, node):
315        if isinstance(node.parent, nodes.section):
316            level = self.section_level + self.initial_header_level - 1
317            if level == 1:
318                level = 2
319            tag = 'h%s' % level
320            self.body.append(self.starttag(node, tag, ''))
321            self.context.append('</%s>\n' % tag)
322        else:
323            html4css1.HTMLTranslator.visit_subtitle(self, node)
324
325    def visit_title(self, node, move_ids=0):
326        html4css1.HTMLTranslator.visit_title(self, node, move_ids=move_ids)
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。