Attachment 'SlideSet-1.0.py'

Download

   1 # -*- coding: utf-8 -*-
   2 """
   3     MoinMoin - SlideSet action Version 1.0, 18.10.2014
   4     [a modication of SlideShow action]
   5 
   6     Format a wiki page as a series of slides separated by page breaks
   7     for printing as handouts.
   8     
   9     For documentation and examples see:
  10     
  11     http://rileylink.net/moin.cgi/MoinMoin_Matters
  12 
  13     History:
  14     
  15     Version 1.0 - 18.10.2014: initial version.
  16 
  17     @copyright: 2014 Ian Riley <ian@riley.asia>
  18     @license: GNU GPL, see COPYING for details.
  19 
  20     Based on SlideShow action
  21 
  22     @copyright: 2005 Jim Clark,
  23                 2005 Nir Soffer,
  24                 2008 MoinMoin:ThomasWaldmann,
  25                 2009 MoinMoin:ReimarBauer
  26     @license: GNU GPL, see COPYING for details.
  27 """
  28 
  29 import re, time
  30 
  31 from MoinMoin import wikiutil, i18n, error
  32 from MoinMoin.Page import Page
  33 
  34 Dependencies = ['language']
  35 
  36 
  37 class Error(error.Error):
  38     """ Raised for errors in this module """
  39 
  40 # This could be delivered in a separate plugin, but
  41 # it is more convenient to have everything in one module.
  42 
  43 class WikiSlideParser(object):
  44     """ Parse slides using wiki format
  45 
  46     Typical usage::
  47         for title, start, end in WikiSlideParser().parse(text):
  48             slides.append((title, start, end))
  49 
  50     If you want to override this parser, you can add 'slideshow_wiki'
  51     parser plugin, that provides a SlideParser class.
  52     """
  53     _heading_pattern = re.compile(r"""
  54         # TODO: check, mhz found bug here
  55         (?P<skip>{{{(?:.*\n)+?}}}) |
  56         # Match headings level 1
  57         (?P<heading>^=\s(?P<text>.*)\s=$\n?)
  58         """, re.MULTILINE | re.UNICODE | re.VERBOSE)
  59 
  60     def parse(self, text):
  61         """ Parse slide data in text
  62 
  63         Wiki slides are defined by the headings, ignoring the text
  64         before the first heading. This parser finds all headings,
  65         skipping headings in preformatted code areas.
  66 
  67         Returns an iterator over slide data. For each slide, a tuple
  68         (title, bodyStart, bodyEnd) is returned. bodyStart and bodyEnd
  69         are indexes into text.
  70         """
  71         matches = [match for match in self._heading_pattern.finditer(text)
  72                    if match.start('skip') == -1]
  73 
  74         for i in range(len(matches)):
  75             title = matches[i].group('text').strip()
  76             bodyStart = matches[i].end('heading')
  77             try:
  78                 bodyEnd = matches[i + 1].start('heading')
  79             except IndexError:
  80                 bodyEnd = len(text)
  81             yield title, bodyStart, bodyEnd
  82 
  83 
  84 class SlidePage(Page):
  85     """ A wiki page containing a slideshow
  86 
  87     The slides are parsed according to the page #format xxx processing
  88     instruction. This module implements only a wiki format slide parser.
  89 
  90     To support other formats like rst, add a 'slideshow_rst' parser
  91     plugin, providing SlideParser class, implementing the SlideParser
  92     protocol. See WikiSlideParser for details.
  93     """
  94     defaultFormat = 'wiki'
  95     defaultParser = WikiSlideParser
  96 
  97     def __init__(self, request, name, **keywords):
  98         Page.__init__(self, request, name, **keywords)
  99         self._slideIndex = None
 100         self.counter = ''
 101         self.slide_set = ''
 102 
 103     def __len__(self):
 104         """ Return the slide count """
 105         return len(self.slideIndex())
 106 
 107     def isEmpty(self):
 108         return len(self) == 0
 109 
 110     # Slide accessing methods map 1 based slides to 0 based index.
 111 
 112     def titleAt(self, number):
 113         """ Return the title of slide number """
 114         try:
 115             return self.slideIndex()[number - 1][0]
 116         except IndexError:
 117             return 1
 118 
 119     def bodyAt(self, number):
 120         """ Return the body of slide number """
 121         try:
 122             start, end = self.slideIndex()[number - 1][1:]
 123             return self.get_raw_body()[start:end]
 124         except IndexError:
 125             return self.get_raw_body()
 126 
 127     # Private ----------------------------------------------------------------
 128 
 129     def slideIndex(self):
 130         if self._slideIndex is None:
 131             self.parseSlides()
 132         return self._slideIndex
 133 
 134     def parseSlides(self):
 135         body = self.get_raw_body()
 136         self._slideIndex = []
 137         parser = self.createSlideParser()
 138         for title, bodyStart, bodyEnd in parser.parse(body):
 139             self._slideIndex.append((title, bodyStart, bodyEnd))
 140 
 141     def createSlideParser(self):
 142         """ Import plugin and return parser class
 143 
 144         If plugin is not found, and format is not defaultFormat, raise an error.
 145         For defaultFormat, use builtin defaultParser in this module.
 146         """
 147         format = self.pi['format']
 148         plugin = 'slideshow_' + format
 149         try:
 150             Parser = wikiutil.importPlugin(self.request.cfg, 'parser', plugin, 'SlideParser')
 151         except wikiutil.PluginMissingError:
 152             if format != self.defaultFormat:
 153                 raise Error('SlideShow does not support %s format.' % format)
 154             Parser = self.defaultParser
 155         return Parser()
 156 
 157 
 158 class SlideshowAction:
 159 
 160     name = 'SlideShow'
 161     maxSlideLinks = 15
 162 
 163     def __init__(self, request, pagename, template):
 164         self.request = request
 165         self.page = SlidePage(self.request, pagename)
 166         self.slide_template = slide_template
 167         self.set_template = set_template
 168 
 169         # Cache values used many times
 170         self.pageURL = self.page.url(request)
 171 
 172     def execute(self):
 173         _ = self.request.getText
 174         try:
 175             #self.setSlideNumber()
 176             language = self.page.pi['language']
 177             self.request.setContentLanguage(language)
 178             for s in range(self.last_slide()):
 179                 self.slideNumber = s + 1
 180                 self.page.slide_set += self.slide_template % self
 181             self.request.write(self.set_template % self)
 182         except Error, err:
 183             self.request.theme.add_msg(unicode(err), "error")
 184             self.page.send_page()
 185 
 186     # Private ----------------------------------------------------------------
 187 
 188     def createParser(self, format, text):
 189         if format == "wiki":
 190             format = 'text_moin_wiki'
 191         try:
 192             Parser = wikiutil.importPlugin(self.request.cfg, 'parser', format,
 193                                            'Parser')
 194         except wikiutil.PluginMissingError:
 195             from MoinMoin.parser.text import Parser
 196         parser = Parser(text, self.request)
 197         return parser
 198 
 199     def createFormatter(self, format):
 200         try:
 201             Formatter = wikiutil.importPlugin(self.request.cfg, 'formatter',
 202                                               format, 'Formatter')
 203         except wikiutil.PluginMissingError:
 204             from MoinMoin.formatter.text_plain import Formatter
 205 
 206         formatter = Formatter(self.request)
 207         self.request.formatter = formatter
 208         formatter.page = self.page
 209         return formatter
 210 
 211     def languageAttributes(self, lang):
 212         return ' lang="%s" dir="%s"' % (lang, i18n.getDirection(lang))
 213 
 214     def last_slide(self):
 215         return max(len(self.page), 1)
 216 
 217     # Replacing methods ------------------------------------------------------
 218 
 219     def __getitem__(self, name):
 220         item = getattr(self, 'item_' + name)
 221         if callable(item):
 222             return item()
 223         else:
 224             return item
 225 
 226     def item_language_attribtues(self):
 227         return self.languageAttributes(self.request.content_lang)
 228 
 229     def item_theme_url(self):
 230         return '%s/%s' % (self.request.cfg.url_prefix_static, self.request.theme.name)
 231 
 232     item_action_name = name
 233     
 234     def item_logo(self):
 235         return wikiutil.escape(self.request.getPragma('logo', defval='[ir].png'))
 236 
 237     def item_title(self):
 238         return wikiutil.escape(self.page.page_name)
 239 
 240     def item_slide_title(self):
 241         return wikiutil.escape(self.page.titleAt(self.slideNumber))
 242 
 243     def item_slide_body(self):
 244         text = self.page.bodyAt(self.slideNumber)
 245         format = self.page.pi['format']
 246         parser = self.createParser(format, text)
 247         formatter = self.createFormatter('text_html')
 248         return self.request.redirectedOutput(parser.format, formatter)
 249     
 250     def item_date(self):
 251         return wikiutil.escape(self.request.getPragma('date', defval=''))
 252 
 253     def item_author(self):
 254         return wikiutil.escape(self.request.getPragma('author', defval=''))
 255 
 256     def item_logo(self):
 257         return wikiutil.escape(self.request.getPragma('logo', defval='[ir].png'))
 258         
 259     def item_counter(self):
 260         return "%d|%d" % (self.slideNumber, self.last_slide())
 261 
 262     def item_slide_set(self):
 263         return self.page.slide_set
 264 
 265 # This is quite stupid template, but it cleans most of the code from
 266 # html. With smarter templates, there will be no html in the action code.
 267 
 268 slide_template = """
 269 <div id="slide"><h1>%(slide_title)s</h1>
 270 <div id="content">%(slide_body)s</div>
 271 <div id="slide_footer">
 272 <span id="slide_date">%(date)s</span>
 273 <span id="slide_author">%(author)s</span>
 274 <span id="slide_counter">%(counter)s</span>
 275 </div>
 276 </div>"""
 277 
 278 set_template = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 279     "http://www.w3.org/TR/html4/strict.dtd">
 280 <html%(language_attribtues)s>
 281 <head>
 282     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
 283     <meta name="robots" content="noindex,nofollow">
 284     <title>%(title)s</title>
 285     <STYLE TYPE="text/css" CHARSET="utf-8" MEDIA="all">
 286     <!--
 287       @import url(%(theme_url)s/css/%(action_name)s.css);
 288       body {
 289         margin: 0;
 290         padding: 0;
 291       }
 292       h1:before {content:url(%(theme_url)s/../common/%(logo)s);
 293         padding-right:10px; display: inline-block; vertical-align: middle;
 294       }
 295     -->
 296     </STYLE>
 297 </head>
 298 <body>%(slide_set)s
 299 </body>
 300 </html>"""
 301 
 302 def execute(pagename, request):
 303     """ Glue to current plugin system """
 304     SlideshowAction(request, pagename, set_template).execute()

You are not allowed to attach a file to this page.