Changeset 1771 for trunk/pylucid_project/PyLucid/system/markups/creole.py
- Timestamp:
- 09/22/08 15:40:45 (18 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/pylucid_project/PyLucid/system/markups/creole.py
r1769 r1771 77 77 #-------------------------------------------------------------------------- 78 78 79 macro_block = r'''(?P<macro_block> 80 \s* << (?P<macro_block_start>\w+) \s* (?P<macro_block_args>.*?) >> 81 (?P<macro_block_text>(.|\n)+?) 82 <</(?P=macro_block_start)>> \s* 83 )''' 84 79 85 macro = r'''(?P<macro> 80 86 << 81 (?P<macro_name> \w+) 82 (\( (?P<macro_args> .*?) \))? \s* 83 ([|] \s* (?P<macro_text> .+?) \s* )? 87 (?P<macro_name> \w+) (?P<macro_args>.*?) 84 88 >> 85 89 )''' … … 95 99 # For the block elements: 96 100 separator = r'(?P<separator> ^ \s* ---- \s* $ )' # horizontal line 97 line = r' (?P<line> ^ \s* $ )' # empty line that separates paragraphs101 line = r'''(?P<line> ^\s*$ )''' # empty line that separates paragraphs 98 102 head = r'''(?P<head> 99 103 ^ 100 104 (?P<head_head>=+) \s* 101 105 (?P<head_text> .*? ) 102 =* \s*$103 ) \n*'''106 =*$ 107 )''' 104 108 text = r'(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?' 105 109 list = r'''(?P<list> … … 124 128 pre_escape = r' ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $' 125 129 126 # Pass-through all django template blocktags 127 passthrough_block = r'''^ \s*(?P<passthrough_block> 128 {%.*?%} 129 (.|\n)+? 130 {%.*?%} 131 ) \s*$ 132 ''' 133 passthrough_line = r'''(?P<passthrough_line> 130 # Pass-through all django template blocktags 131 pass_block = r'''(?P<pass_block> 132 {% \s* (?P<pass_block_start>.+?) \s* (?P<pass_block_args>.*?) \s* %} 133 (\n|.)*? 134 {% \s* end(?P=pass_block_start) \s* %} 135 )''' 136 137 pass_line = r'''\n(?P<pass_line> 138 (\n|\s)* 134 139 ({%.*?%})| 135 140 ({{.*?}}) 136 )''' 141 (\n|\s)* 142 )''' 143 pass_inline = r'''(?P<pass_inline> 144 ({%.*?%})| 145 ({{.*?}}) 146 )''' 147 137 148 #Pass-through html code lines 138 149 html = r'''(?P<html> 139 ^ \s*<.*?> \s*$150 ^[ \t]*<[a-zA-Z].*?<(/[a-zA-Z ]+?)>[ \t]*$ 140 151 )''' 141 152 … … 153 164 ) \s* 154 165 ''' % '|'.join([link, macro, image, code]) 155 166 156 167 #-------------------------------------------------------------------------- 157 blockelements = (158 "head", "list", "pre", "code", "table", "separator", "macro",159 "passthrough_block", "html"160 )168 # blockelements = ( 169 # "head", "list", "pre", "code", "table", "separator", "macro", 170 # "pass_block", "pass_line", "html" 171 # ) 161 172 162 173 class Parser: … … 177 188 block_re = re.compile( 178 189 '|'.join([ 179 Rules.passthrough_block, 190 Rules.pass_block, 191 Rules.pass_line, 192 Rules.macro_block, 180 193 Rules.html, 181 194 Rules.line, Rules.head, Rules.separator, Rules.pre, Rules.list, … … 189 202 Rules.link, Rules.url, Rules.macro, 190 203 Rules.code, Rules.image, 191 Rules.pass through_line,204 Rules.pass_inline, 192 205 Rules.strong, Rules.emph, Rules.linebreak, 193 206 Rules.escape, Rules.char … … 201 214 self.cur = self.root # The most recent document node 202 215 self.text = None # The node to add inline characters to 216 self.last_text_break = None # Last break node, inserted by _text_repl() 203 217 204 218 #-------------------------------------------------------------------------- 219 220 def cleanup_break(self, old_cur): 221 """ 222 remove unused end line breaks. 223 Should be called before a new block element. 224 e.g.: 225 <p>line one<br /> 226 line two<br /> <--- remove this br-tag 227 </p> 228 """ 229 if self.cur.children: 230 last_child = self.cur.children[-1] 231 if last_child.kind == "break": 232 del(self.cur.children[-1]) 205 233 206 234 def _upto(self, node, kinds): … … 210 238 Start at the node node. 211 239 """ 240 self.cleanup_break(node) # remove unused end line breaks. 212 241 while node.parent is not None and not node.kind in kinds: 213 242 node = node.parent 243 214 244 return node 215 245 … … 221 251 # same method needs several names, because of group names in regexps. 222 252 223 def _pass through_block_repl(self, groups):224 """ Pass-through all django template blocktags """ 253 def _pass_block_repl(self, groups): 254 """ Pass-through all django template blocktags """ 225 255 self._upto_block() 226 DocNode("passthrough_block", self.root, groups["passthrough_block"]) 256 self.cur = self.root 257 DocNode("pass_block", self.cur, groups["pass_block"]) 258 self.text = None 259 _pass_block_start_repl = _pass_block_repl 260 _pass_block_end_repl = _pass_block_repl 261 262 def _pass_line_repl(self, groups): 263 """ Pass-through all django tags witch is alone in a code line """ 264 self._upto_block() 265 self.cur = self.root 266 DocNode("pass_line", self.cur, groups["pass_line"]) 227 267 self.text = None 228 268 229 def _pass through_line_repl(self, groups):230 """ Pass-through all django tags"""231 DocNode("pass through_line", self.cur, groups["passthrough_line"])232 self.text = None 233 269 def _pass_inline_repl(self, groups): 270 """ Pass-through all inline django tags""" 271 DocNode("pass_inline", self.cur, groups["pass_inline"]) 272 self.text = None 273 234 274 def _html_repl(self, groups): 235 275 """ Pass-through html code """ … … 239 279 240 280 def _text_repl(self, groups): 241 # print "_text_repl()", self.cur.kind, groups.get('break') != None 281 # print "_text_repl()", self.cur.kind, groups.get('break') != None 242 282 if self.cur.kind in ('table', 'table_row', 'bullet_list', 243 283 'number_list'): 244 284 self._upto_block() 245 285 246 286 if self.cur.kind in ('document', 'section', 'blockquote'): 247 287 self.cur = DocNode('paragraph', self.cur) 248 249 self.parse_inline(groups.get('text', ''))250 288 289 self.parse_inline(groups.get('text', u"")) 290 251 291 if groups.get('break') and self.cur.kind in ('paragraph', 252 292 'emphasis', 'strong', 'code'): 253 DocNode('break', self.cur, '')254 293 self.last_text_break = DocNode('break', self.cur, u"") 294 255 295 self.text = None 256 296 _break_repl = _text_repl … … 260 300 if not groups.get('escaped_url'): 261 301 # this url is NOT escaped 262 target = groups.get('url_target', '')302 target = groups.get('url_target', u"") 263 303 node = DocNode('link', self.cur) 264 304 node.content = target … … 268 308 # this url is escaped, we render it as text 269 309 if self.text is None: 270 self.text = DocNode('text', self.cur, u '')310 self.text = DocNode('text', self.cur, u"") 271 311 self.text.content += groups.get('url_target') 272 312 _url_target_repl = _url_repl … … 276 316 def _link_repl(self, groups): 277 317 """Handle all kinds of links.""" 278 target = groups.get('link_target', '')279 text = (groups.get('link_text', '') or '').strip()318 target = groups.get('link_target', u"") 319 text = (groups.get('link_text', u"") or u"").strip() 280 320 parent = self.cur 281 321 self.cur = DocNode('link', self.cur) … … 288 328 _link_text_repl = _link_repl 289 329 330 def _add_macro(self, macro_name, macro_args, macro_text=u""): 331 # self._upto_block() 332 node = DocNode("macro", self.cur, macro_text.strip()) 333 node.macro_name = macro_name 334 node.macro_args = macro_args.strip() 335 self.text = None 336 337 def _macro_block_repl(self, groups): 338 """Handles macros using the placeholder syntax.""" 339 #self.debug_groups(groups) 340 self._upto_block() 341 self.cur = self.root 342 self._add_macro( 343 macro_name = groups['macro_block_start'], 344 macro_text = groups.get('macro_block_text', u""), 345 macro_args = groups.get('macro_block_args', u""), 346 ) 347 self.text = None 348 _macro_block_start_repl = _macro_block_repl 349 _macro_block_args_repl = _macro_block_repl 350 _macro_block_text_repl = _macro_block_repl 351 290 352 def _macro_repl(self, groups): 291 353 """Handles macros using the placeholder syntax.""" 292 name = groups.get('macro_name', '') 293 text = (groups.get('macro_text', '') or '').strip() 294 node = DocNode('macro', self.cur, name) 295 node.args = groups.get('macro_args', '') or '' 296 DocNode('text', node, text or name) 297 self.text = None 354 macro_name = groups.get('macro_name', u"") 355 macro_args = groups.get('macro_args', u"") 356 self._add_macro(macro_name, macro_args) 357 self.text = None 358 359 # text = (groups.get('macro_text', u"") or u"").strip() 360 # node = DocNode('macro', self.cur, name) 361 # node.args = groups.get('macro_args', u"") or '' 362 # DocNode('text', node, text or name) 363 # self.text = None 298 364 _macro_name_repl = _macro_repl 299 365 _macro_args_repl = _macro_repl 300 _macro_text_repl = _macro_repl366 # _macro_text_repl = _macro_repl 301 367 302 368 def _image_repl(self, groups): 303 369 """Handles images and attachemnts included in the page.""" 304 target = groups.get('image_target', '').strip()305 text = (groups.get('image_text', '') or '').strip()370 target = groups.get('image_target', u"").strip() 371 text = (groups.get('image_text', u"") or u"").strip() 306 372 node = DocNode("image", self.cur, target) 307 373 DocNode('text', node, text or node.content) … … 315 381 316 382 def _item_repl(self, groups): 317 bullet = groups.get('item_head', u '')318 text = groups.get('item_text', u '')383 bullet = groups.get('item_head', u"") 384 text = groups.get('item_text', u"") 319 385 if bullet[-1] == '#': 320 386 kind = 'number_list' … … 371 437 self.text = None 372 438 else: 373 text = m.group('head').strip('= ') 439 text = m.group('head').strip('= ') 374 440 self.cur = DocNode('table_head', tr) 375 self.text = DocNode('text', self.cur, u '')441 self.text = DocNode('text', self.cur, u"") 376 442 self.parse_inline(text) 377 443 378 444 self.cur = tb 379 445 self.text = None … … 382 448 self._upto_block() 383 449 kind = groups.get('pre_kind', None) 384 text = groups.get('pre_text', u '')450 text = groups.get('pre_text', u"") 385 451 def remove_tilde(m): 386 452 return m.group('indent') + m.group('rest') … … 396 462 """ Transfer newline from the original markup into the html code """ 397 463 self._upto_block() 398 DocNode('line', self.cur, "")464 DocNode('line', self.cur, u"") 399 465 400 466 def _code_repl(self, groups): 401 DocNode('code', self.cur, groups.get('code_text', u '').strip())467 DocNode('code', self.cur, groups.get('code_text', u"").strip()) 402 468 self.text = None 403 469 _code_text_repl = _code_repl … … 424 490 def _escape_repl(self, groups): 425 491 if self.text is None: 426 self.text = DocNode('text', self.cur, u '')427 self.text.content += groups.get('escaped_char', u '')492 self.text = DocNode('text', self.cur, u"") 493 self.text.content += groups.get('escaped_char', u"") 428 494 429 495 def _char_repl(self, groups): 430 496 if self.text is None: 431 self.text = DocNode('text', self.cur, u'') 432 self.text.content += groups.get('char', u'') 433 434 #-------------------------------------------------------------------------- 435 436 def check_break(self): 437 """ 438 remove unused end line breaks. Should be called on every block element. 439 e.g.: 440 <p>line one<br /> 441 line two<br /> <--- remove this br-tag 442 </p> 443 """ 444 if self.cur.children == []: 445 return 446 if self.cur.children[-1].kind == "break": 447 del(self.cur.children[-1]) 448 497 self.text = DocNode('text', self.cur, u"") 498 self.text.content += groups.get('char', u"") 499 449 500 #-------------------------------------------------------------------------- 450 501 … … 455 506 if text is not None: 456 507 #if name != "char": print "%15s: %r" % (name, text) 457 if name in Rules.blockelements: 458 self.check_break() 508 #print "%15s: %r" % (name, text) 459 509 replace = getattr(self, '_%s_repl' % name) 460 510 replace(groups) … … 476 526 477 527 #-------------------------------------------------------------------------- 478 def debug(self ):528 def debug(self, start_node=None): 479 529 """ 480 530 Display the current document tree 481 531 """ 482 532 print "_"*80 483 print " document tree:" 533 534 if start_node == None: 535 start_node = self.root 536 print " document tree:" 537 else: 538 print " tree from %s:" % start_node 539 484 540 print "="*80 485 541 def emit(node, ident=0): 486 542 for child in node.children: 487 print u"%s%s " % (u" "*ident, child)543 print u"%s%s: %r" % (u" "*ident, child.kind, child.content) 488 544 emit(child, ident+4) 489 emit(s elf.root)545 emit(start_node) 490 546 print "*"*80 491 547 492 548 def debug_groups(self, groups): 493 549 print "_"*80 … … 511 567 self.parent = parent 512 568 self.kind = kind 569 570 if content: 571 content = unicode(content) 513 572 self.content = content 573 514 574 if self.parent is not None: 515 575 self.parent.children.append(self) … … 517 577 def __str__(self): 518 578 # return "DocNode kind '%s', content: %r" % (self.kind, self.content) 519 return "%s: %r" % (self.kind, self.content) 579 return "<DocNode %s: %r>" % (self.kind, self.content) 580 def __repr__(self): 581 return u"<DocNode %s: %r>" % (self.kind, self.content) 582 583 def debug(self): 584 print "_"*80 585 print "\tDocNode - debug:" 586 print "str(): %s" % self 587 print "attributes:" 588 for i in dir(self): 589 if i.startswith("_"): 590 continue 591 print "%20s: %r" % (i, getattr(self, i, "---")) 520 592 521 593 … … 549 621 picture [[www.domain.tld | {{ foo.JPG | Foo }} ]] as a link 550 622 551 END""" 552 623 END 624 625 ==== Headline 1 626 627 {% a tag 1 %} 628 629 ==== Headline 2 630 631 {% a tag 2 %} 632 633 the end 634 """ 635 636 txt = r""" 637 ==== Headline 1 638 639 The current page name: >{{ PAGE.name }}< great? 640 641 {% a tag 1 %} 642 643 ==== Headline 2 644 645 {% a tag 2 %} 646 647 some text 648 649 {% something arg1="foo" arg2="bar" arg2=3 %} 650 foobar 651 {% endsomething %} 652 653 the end 654 """ 655 656 txt = r"""A {% lucidTag page_update_list count=10 %} PyLucid plugin 657 658 {% sourcecode py %} 659 import sys 660 661 sys.stdout("Hello World!") 662 {% endsourcecode %} 663 A [[www.domain.tld|link]].""" 664 665 txt = r""" 666 ==== Headline 1 667 668 On {% a tag 1 %} line 669 line two 670 671 ==== Headline 2 672 673 {% a tag 2 %} 674 675 A block: 676 {% block %} 677 <Foo:> {{ Bar }} 678 {% endblock %} 679 end block 680 681 {% block1 arg="jo" %} 682 eofjwqp 683 {% endblock1 %} 684 685 A block without the right end block: 686 {% block1 %} 687 111 688 {% endblock2 %} 689 BBB 690 691 A block without endblock: 692 {% block3 %} 693 222 694 {% block3 %} 695 CCC 696 697 the end""" 698 # txt = r''' 699 #<<jojo>> 700 #owrej 701 #<<code>> 702 #some code 703 #<</code>> 704 #a macro: 705 #<<code ext=.css>> 706 #/* Stylesheet */ 707 #form * { 708 # vertical-align:middle; 709 #} 710 #<</code>> 711 #the end 712 #<<code>> 713 #<<code>> 714 #jup 715 #<</code>> 716 #''' 717 718 719 print "-"*80 553 720 p = Parser(txt) 554 721 document = p.parse() 555 722 p.debug() 556 723 557 724 def test_rules(rules, txt): 558 725 def display_match(match): … … 563 730 re.sub(rules, display_match, txt) 564 731 565 print "_"*80566 print "plain block rules match:"567 test_rules(Parser("").block_re, txt)568 569 print "_"*80570 print "plain inline rules match:"571 test_rules(Parser("").inline_re, txt)732 # print "_"*80 733 # print "plain block rules match:" 734 # test_rules(Parser("").block_re, txt) 735 # 736 # print "_"*80 737 # print "plain inline rules match:" 738 # test_rules(Parser("").inline_re, txt) 572 739 573 740 print "---END---"