# WikiWikiWeb-style markup # contributed by Tres Seaver """ tests: >>> assert 2==2 """ import re import string import urllib name_pattern_1 = r'[A-Z]+[a-z]+[A-Z][A-Za-z]' name_pattern_2 = r'[A-Z][A-Z]+[a-z][A-Za-z]' bracket_pattern = r'\[[\\\w.:_ ]+\]' full_wikilink_pattern = re.compile( r'!?(%s*|%s*|%s)' % ( name_pattern_1 , name_pattern_2 , bracket_pattern ) ) abbrev_wikilink_pattern = re.compile( r'!?(%s*|%s*)' % ( name_pattern_1 , name_pattern_2 ) ) strip_bracket_pattern = re.compile( r'^\[(.*)\]$' ) def Wiki_ize( self, text='', full_pattern=0 ): """ Transform a html page into a wiki page by changing WikiNames into hyperlinks; pass full_pattern=1 to pick up square bracket links, too (default not to avoid fighting with StructuredText). tests: >>> assert 2==2 """ pattern = full_pattern and full_wikilink_pattern or abbrev_wikilink_pattern wikifier = _Wikifier( self ) text = pattern.sub( wikifier._wikilink_replace, text ) return text class _Wikifier : def __init__( self, other ) : self.other_ = other def _wikilink_replace( self, matchobj ): """replace an occurrence of wikilink_pattern with a suitable hyperlink """ # any matches preceded by ! should be left alone if re.match( '^!', matchobj.group( 0 ) ): return matchobj.group( 1 ) # discard enclosing [] if any wikiname = strip_bracket_pattern.sub( r'\1', matchobj.group( 1 ) ) # if something of this name exists, link to it; # otherwise, provide a "?" creation link if hasattr( self.other_.aq_parent, wikiname ): return '' + wikiname + '' else: return '%s?' \ % ( wikiname , urllib.quote( self.other_.id ) , urllib.quote( wikiname ) ) class WMMLTranslator : """ |FSM/translator for texts marked up using WikiWikiMarkupLanguage, as | defined at http://www.c2.org/cgi/wiki?TextFormattingRules: | |Paragraphs | | Don't Indent paragraphs | | Words wrap and fill as needed | | Use blank lines as separators | | Four or more minus signs make a horizontal rule | |Lists | | tab-* for first level | | tab-tab-* for second level, etc. | | Use * for bullet lists, 1. for numbered lists (mix at will) | | tab-Term:-tab Definition for definition lists | | One line for each item | | Other leading whitespace signals preformatted text, changes font. | |Fonts | | Indent with one or more spaces to use a monospace font: | | This is in monospace # note it is off the margin | |This is not # it is on the left margin there | |Indented Paragraphs (Quotes) | | tab-space-:-tab -- often used (with emphasis) for quotations. | (See SimulatingQuoteBlocks) | |Emphasis | | Use doubled single-quotes ('') for emphasis (usually italics) | | Use tripled single-quotes (''') for strong emphasis (usually bold) | | Use five single-quotes ('), or triples within doubles, for some other | kind of emphasis (BoldItalicInWiki), but be careful about the bugs in | the Wiki emphasis logic... | | At most one per line. But as many as you need in a paragraph; just use | multiple lines without intervening blank lines. | | Don't cross line boundaries | |References | | JoinCapitalizedWords to make local references | | [1], [2], [3], [4] refer to remote references. Click EditLinks on the | edit form to enter URLs | | Or precede URLs with "http:", "ftp:" or "mailto:" to create links | automatically as in: http://c2.com/ | | URLs ending with .gif are inlined if inserted as a remote reference | | ISBN 0-13-748310-4 links to a bookseller. (The pattern is: | "ISBN", optional colon, space, ten digits with optional hypens, | the whole thing optionally in square brackets. The last digit can be | an "X".) We are an AmazonAssociate. | | I S B N: 0123456789 becomes ISBN 0123456789 | [I S B N 0123456789] becomes ISBN 0123456789 | [I S B N: 123-456-789-X] becomes ISBN 123-456-789-X """ # # Patterns used to parse markup. # blankLine = re.compile( '^$' ) anyGroup = "(.*)" notTick = "([^']*)" emphasis = re.compile( "%s''%s''" % ( (notTick,) * 2 ) ) strong = re.compile( "%s'''%s'''" % ( (notTick,) * 2 ) ) hrule = re.compile( '^----[-]*%s' % anyGroup ) nTabs = "([\t]*)" tabList = re.compile( '^%s%s' % ( nTabs, anyGroup ) ) bulletPrefix = '^(\*)' digitPrefix = '^([1-9][0-9]*[\.]?)' dictPrefix = "^([A-Za-z '-]*):" itemSuffix = "[ \t]+" + anyGroup bulletItem = re.compile( bulletPrefix + itemSuffix ) digitItem = re.compile( digitPrefix + itemSuffix ) dictItem = re.compile( dictPrefix + itemSuffix ) codePrefix = '^([ ]+)' codeLine = re.compile( codePrefix + anyGroup ) httpPrefix = '(http:)' ftpPrefix = '(ftp:)' mailtoPrefix = '(mailto:)' urlSuffix = '([^ ]+)' httpURL = re.compile( httpPrefix + urlSuffix ) ftpURL = re.compile( ftpPrefix + urlSuffix ) mailtoURL = re.compile( mailtoPrefix + urlSuffix ) # def __init__( self, other ) : def __init__( self ) : """ """ # self.other = other self.listStack = [] self.translatedLines = [] self.topList = self.translatedLines self.topCode = '' def nestingLevel( self ) : """ How deep is the nesting stack? """ return len( self.listStack ) def pushList( self, code ) : """ Start a new nested line list (e.g., for