public
Description: Markdown processing with Nu. Use with any Nu or Objective-C project. Created by Grayson Hansard.
Homepage: http://programming.nu/posts/2007/10/10/markdown-in-nu
Clone URL: git://github.com/timburks/numarkdown.git
Fixed errors in regex replacement. All tests now PASS.

When we replace patterns matched with a regex, we should
do the replacements from right to left.  To make this easier,
I added an eachInReverse: method to NSArray.  It should be
called on the results of [NuRegex findAllInString:] along
with [NSMutableString replaceCharactersInRange: withString:]
to perform the replacement.  With this change, all of
John Gruber's Markdown tests now pass exactly -- this is
based on a character-by-character comparison of NuMarkdown
and Markdown.pl output.

I may have missed a few places where eachInReverse: should
be used, and there's quite a bit of cleanup and polish that
we can do on the code now that we have a significant set
of regression tests that pass.  But for now, here are the
changes that got us golden.
timburks (author)
Tue Nov 06 18:50:49 -0800 2007
commit  501b033fa28f0e5243829dd2dc452437fc1c9b8c
tree    7a96323c4aba19761db84e0f9dc3ccf1eb56cf5e
parent  c73dcfcd76d7dced8c800eba896beb471e8f1a79
...
62
63
64
65
 
66
67
68
 
69
70
71
...
77
78
79
80
 
81
82
83
 
84
85
86
...
98
99
100
101
 
102
103
104
 
105
106
107
...
119
120
121
122
123
124
 
 
 
 
125
126
127
...
147
148
149
150
151
152
153
154
 
 
 
 
 
 
155
156
157
...
244
245
246
247
 
248
249
250
251
 
252
253
254
...
512
513
514
515
 
516
517
 
518
519
520
...
610
611
612
 
613
614
 
 
615
616
617
...
62
63
64
 
65
66
67
 
68
69
70
71
...
77
78
79
 
80
81
82
 
83
84
85
86
...
98
99
100
 
101
102
103
 
104
105
106
107
...
119
120
121
 
 
 
122
123
124
125
126
127
128
...
148
149
150
 
 
 
 
 
151
152
153
154
155
156
157
158
159
...
246
247
248
 
249
250
251
252
 
253
254
255
256
...
514
515
516
 
517
518
 
519
520
521
522
...
612
613
614
615
616
 
617
618
619
620
621
0
@@ -62,10 +62,10 @@
0
       [ \t]*        # trailing spaces/tabs
0
       (?=\n+|\Z)      # followed by a newline or end of document
0
     )END -"mx"))
0
- ((r findAllInString:str) each:
0
+ ((r findAllInString:str) eachInReverse:
0
       (do (m)
0
           ($g_html_blocks setObject:(m group) forKey:-"!!#{(m hash)}!!")
0
- (str replaceOccurrencesOfString:(m group) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
+ (str replaceCharactersInRange:(m range) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
      
0
      (set r (eregex <<-END
0
     (            # save in $1
0
@@ -77,10 +77,10 @@
0
       [ \t]*        # trailing spaces/tabs
0
       (?=\n+|\Z)  # followed by a newline or end of document
0
     )END -"mx"))
0
- ((r findAllInString:str) each:
0
+ ((r findAllInString:str) eachInReverse:
0
       (do (m)
0
           ($g_html_blocks setObject:(m group) forKey:-"!!#{(m hash)}!!")
0
- (str replaceOccurrencesOfString:(m group) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
+ (str replaceCharactersInRange:(m range) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
      
0
      ; Special case just for <hr />. It was easier to make a special case than
0
      ; to make the other regex more complicated
0
@@ -98,10 +98,10 @@
0
       /?>          # the matching end tag
0
       [ \t]*
0
       (?=\n{2,}|\Z)    # followed by a blank line or end of document
0
- )END -"mx") findAllInString:str) each:
0
+ )END -"mx") findAllInString:str) eachInReverse:
0
       (do (m)    
0
           ($g_html_blocks setObject:(m group) forKey:-"!!#{(m hash)}!!")
0
- (str replaceOccurrencesOfString:(m group) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
+ (str replaceCharactersInRange:(m range) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
      
0
      ; Special case for standalone HTML comments
0
      (((eregex <<-END
0
@@ -119,9 +119,10 @@
0
       )
0
       [ \t]*
0
       (?=\n{2,}|\Z)    # followed by a blank line or end of document
0
- )END -"mx") findAllInString:str) each:(do (m)
0
- ($g_html_blocks setObject:(m group) forKey:-"!!#{(m hash)}!!")
0
- (str replaceOccurrencesOfString:(m group) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
+ )END -"mx") findAllInString:str) eachInReverse:
0
+ (do (m)
0
+ ($g_html_blocks setObject:(m group) forKey:-"!!#{(m hash)}!!")
0
+ (str replaceCharactersInRange:(m range) withString:"\n\n!!#{(m hash)}!!\n\n")))
0
      str)
0
 
0
 (function markdown_EncodeAmpsAndAngles (str)
0
@@ -147,11 +148,12 @@
0
       [")]
0
       [ \t]*
0
     )?  # title is optional
0
- (?:\n+|\Z)END -"mx") findAllInString:str) each:(do (m)
0
- ($g_urls setObject:(markdown_EncodeAmpsAndAngles (m groupAtIndex:2)) forKey:(m groupAtIndex:1))
0
- (if (!= (m groupAtIndex:3) nil)
0
- ($g_titles setObject:(m groupAtIndex:3) forKey:(m groupAtIndex:1)))
0
- (str replaceOccurrencesOfString:(m group) withString:-"")))
0
+ (?:\n+|\Z)END -"mx") findAllInString:str) each:
0
+ (do (m)
0
+ ($g_urls setObject:(markdown_EncodeAmpsAndAngles (m groupAtIndex:2)) forKey:(m groupAtIndex:1))
0
+ (if (!= (m groupAtIndex:3) nil)
0
+ ($g_titles setObject:(m groupAtIndex:3) forKey:(m groupAtIndex:1)))
0
+ (str replaceOccurrencesOfString:(m group) withString:-"")))
0
      str)
0
 
0
 (function markdown_EncodeCode (str)
0
@@ -244,11 +246,11 @@
0
     (.+?)    # $2 = The code block
0
     (?<!`)
0
     \1      # Matching closer
0
- (?!`)END -"sx") findAllInString:str) each:
0
+ (?!`)END -"sx") findAllInString:str) eachInReverse:
0
       (do (m)
0
           (set temp (/^[ \t]*/ replaceWithString:"" inString:(m groupAtIndex:2)))
0
           (set temp (/[ \t]*$/ replaceWithString:"" inString:temp))
0
- (str replaceOccurrencesOfString:(m group) withString:-"<code>#{(markdown_EncodeCode temp)}</code>")))
0
+ (str replaceCharactersInRange:(m range) withString:-"<code>#{(markdown_EncodeCode temp)}</code>")))
0
      str)
0
 
0
 (function markdown_EncodeItalicsAndBolds (str)
0
@@ -512,9 +514,9 @@
0
      result)
0
 
0
 (function markdown_Detab (str)
0
- ((/(.*?)\t/ findAllInString:str) each:
0
+ ((/(.*?)\t/ findAllInString:str) eachInReverse:
0
       (do (m)
0
- (str replaceOccurrencesOfString:(m group)
0
+ (str replaceCharactersInRange:(m range)
0
                withString:"#{(m groupAtIndex:1)}#{(NSString spaces:(- 4 (NuMath integerMod:((m groupAtIndex:1) length) by:4)))}")))
0
      str)
0
 
0
@@ -610,8 +612,10 @@
0
      (set str (markdown_Detab str))
0
      ;; Strip any lines consisting only of spaces and tabs.
0
      (set str (/^[ \t]+$/m replaceWithString:"" inString:str))
0
+
0
      ;; Turn block-level HTML blocks into hash entries
0
- (set str (markdown_HashHTMLBlocks str))
0
+ (set str (markdown_HashHTMLBlocks str))
0
+
0
      ;; Strip link definitions, store in hashes.
0
      (set str (markdown_StripLinkDefinitions str))
0
      

Comments

    No one has commented yet.