Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch markdown Excluding Merge-Ins
This is equivalent to a diff from 0bb8184e3c to de1ef7e99f
2012-12-08
| ||
00:41 | Merge markdown support for embedded documentation into the trunk. check-in: 61079c3bef user: mistachkin tags: trunk | |
2012-12-07
| ||
20:58 | Merge updates from trunk. Closed-Leaf check-in: de1ef7e99f user: mistachkin tags: markdown | |
14:57 | Fix for click-to-diff in IE8, tested this time using IE9 in compatibility mode. check-in: 0bb8184e3c user: drh tags: trunk | |
14:33 | Attempt to get click-to-diff working on IE8. check-in: ce99889c68 user: drh tags: trunk | |
2012-10-07
| ||
14:28 | Update the 'makemake' script with the MinGW makefile changes for the markdown feature as well. check-in: 0db09a2061 user: mistachkin tags: markdown | |
Changes to auto.def.
9 9 with-tcl:path => {Enable Tcl integration, with Tcl in the specified path} 10 10 with-tcl-stubs=0 => {Enable Tcl integration via stubs mechanism} 11 11 internal-sqlite=1 => {Don't use the internal sqlite, use the system one} 12 12 static=0 => {Link a static executable} 13 13 lineedit=1 => {Disable line editing} 14 14 fossil-debug=0 => {Build with fossil debugging enabled} 15 15 json=0 => {Build with fossil JSON API enabled} 16 + markdown=0 => {Build with markdown engine enabled} 16 17 } 17 18 18 19 # sqlite wants these types if possible 19 20 cc-with {-includes {stdint.h inttypes.h}} { 20 21 cc-check-types uint32_t uint16_t int16_t uint8_t 21 22 } 22 23 ................................................................................ 71 72 # Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON 72 73 # is required in the CFLAGS because json*.c 73 74 # have #ifdef guards around the whole file without 74 75 # reading config.h first. 75 76 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON 76 77 define FOSSIL_ENABLE_JSON 77 78 } 79 + 80 +if {[opt-bool markdown]} { 81 + define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_MARKDOWN 82 + define FOSSIL_ENABLE_MARKDOWN 83 +} 78 84 79 85 if {[opt-bool static]} { 80 86 # XXX: This will not work on all systems. 81 87 define-append EXTRA_LDFLAGS -static 82 88 } 83 89 84 90 # Check for zlib, using the given location if specified
Changes to src/db.c.
2072 2072 { "https-login", 0, 0, 0, "off" }, 2073 2073 { "ignore-glob", 0, 40, 1, "" }, 2074 2074 { "empty-dirs", 0, 40, 1, "" }, 2075 2075 { "http-port", 0, 16, 0, "8080" }, 2076 2076 { "localauth", 0, 0, 0, "off" }, 2077 2077 { "main-branch", 0, 40, 0, "trunk" }, 2078 2078 { "manifest", 0, 0, 1, "off" }, 2079 +#ifdef FOSSIL_ENABLE_MARKDOWN 2080 + { "markdown", 0, 0, 0, "off" }, 2081 +#endif 2079 2082 { "max-upload", 0, 25, 0, "250000" }, 2080 2083 { "mtime-changes", 0, 0, 0, "on" }, 2081 2084 { "pgp-command", 0, 40, 0, "gpg --clearsign -o " }, 2082 2085 { "proxy", 0, 32, 0, "off" }, 2083 2086 { "relative-paths",0, 0, 0, "on" }, 2084 2087 { "repo-cksum", 0, 0, 0, "on" }, 2085 2088 { "self-register", 0, 0, 0, "off" }, ................................................................................ 2203 2206 ** 2204 2207 ** main-branch The primary branch for the project. Default: trunk 2205 2208 ** 2206 2209 ** manifest If enabled, automatically create files "manifest" and 2207 2210 ** (versionable) "manifest.uuid" in every checkout. The SQLite and 2208 2211 ** Fossil repositories both require this. Default: off. 2209 2212 ** 2213 +** markdown If enabled (and Fossil was compiled with markdown 2214 +** support), the markdown engine will be used to render 2215 +** embedded documentation conforming to the appropriate 2216 +** content types (e.g. "text/x-markdown"). Default: off. 2217 +** 2210 2218 ** max-upload A limit on the size of uplink HTTP requests. The 2211 2219 ** default is 250000 bytes. 2212 2220 ** 2213 2221 ** mtime-changes Use file modification times (mtimes) to detect when 2214 2222 ** files have been modified. (Default "on".) 2215 2223 ** 2216 2224 ** pgp-command Command used to clear-sign manifests at check-in.
Changes to src/doc.c.
164 164 { "latex", 5, "application/x-latex" }, 165 165 { "lha", 3, "application/octet-stream" }, 166 166 { "lsp", 3, "application/x-lisp" }, 167 167 { "lzh", 3, "application/octet-stream" }, 168 168 { "m", 1, "text/plain" }, 169 169 { "m3u", 3, "audio/x-mpegurl" }, 170 170 { "man", 3, "application/x-troff-man" }, 171 + { "markdown", 8, "text/x-markdown" }, 171 172 { "me", 2, "application/x-troff-me" }, 172 173 { "mesh", 4, "model/mesh" }, 173 174 { "mid", 3, "audio/midi" }, 174 175 { "midi", 4, "audio/midi" }, 175 176 { "mif", 3, "application/x-mif" }, 176 177 { "mime", 4, "www/mime" }, 178 + { "mkd", 3, "text/x-markdown" }, 177 179 { "mov", 3, "video/quicktime" }, 178 180 { "movie", 5, "video/x-sgi-movie" }, 179 181 { "mp2", 3, "audio/mpeg" }, 180 182 { "mp3", 3, "audio/mpeg" }, 181 183 { "mpe", 3, "video/mpeg" }, 182 184 { "mpeg", 4, "video/mpeg" }, 183 185 { "mpg", 3, "video/mpeg" }, ................................................................................ 496 498 style_header(blob_str(&title)); 497 499 wiki_convert(&tail, 0, WIKI_BUTTONS); 498 500 }else{ 499 501 style_header("Documentation"); 500 502 wiki_convert(&filebody, 0, WIKI_BUTTONS); 501 503 } 502 504 style_footer(); 505 +#ifdef FOSSIL_ENABLE_MARKDOWN 506 + }else if( fossil_strcmp(zMime, "text/x-markdown")==0 507 + && db_get_boolean("markdown", 0) ){ 508 + Blob title = BLOB_INITIALIZER; 509 + Blob tail = BLOB_INITIALIZER; 510 + markdown_to_html(&filebody, &title, &tail); 511 + if( blob_size(&title)>0 ){ 512 + style_header(blob_str(&title)); 513 + }else{ 514 + style_header("Documentation"); 515 + } 516 + blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail)); 517 + style_footer(); 518 +#endif 503 519 }else if( fossil_strcmp(zMime, "text/plain")==0 ){ 504 520 style_header("Documentation"); 505 521 @ <blockquote><pre> 506 522 @ %h(blob_str(&filebody)) 507 523 @ </pre></blockquote> 508 524 style_footer(); 509 525 }else{
Changes to src/main.mk.
66 66 $(SRCDIR)/json_timeline.c \ 67 67 $(SRCDIR)/json_user.c \ 68 68 $(SRCDIR)/json_wiki.c \ 69 69 $(SRCDIR)/leaf.c \ 70 70 $(SRCDIR)/login.c \ 71 71 $(SRCDIR)/main.c \ 72 72 $(SRCDIR)/manifest.c \ 73 + $(SRCDIR)/markdown.c \ 74 + $(SRCDIR)/markdown_html.c \ 73 75 $(SRCDIR)/md5.c \ 74 76 $(SRCDIR)/merge.c \ 75 77 $(SRCDIR)/merge3.c \ 76 78 $(SRCDIR)/moderate.c \ 77 79 $(SRCDIR)/name.c \ 78 80 $(SRCDIR)/path.c \ 79 81 $(SRCDIR)/pivot.c \ ................................................................................ 168 170 $(OBJDIR)/json_timeline_.c \ 169 171 $(OBJDIR)/json_user_.c \ 170 172 $(OBJDIR)/json_wiki_.c \ 171 173 $(OBJDIR)/leaf_.c \ 172 174 $(OBJDIR)/login_.c \ 173 175 $(OBJDIR)/main_.c \ 174 176 $(OBJDIR)/manifest_.c \ 177 + $(OBJDIR)/markdown_.c \ 178 + $(OBJDIR)/markdown_html_.c \ 175 179 $(OBJDIR)/md5_.c \ 176 180 $(OBJDIR)/merge_.c \ 177 181 $(OBJDIR)/merge3_.c \ 178 182 $(OBJDIR)/moderate_.c \ 179 183 $(OBJDIR)/name_.c \ 180 184 $(OBJDIR)/path_.c \ 181 185 $(OBJDIR)/pivot_.c \ ................................................................................ 270 274 $(OBJDIR)/json_timeline.o \ 271 275 $(OBJDIR)/json_user.o \ 272 276 $(OBJDIR)/json_wiki.o \ 273 277 $(OBJDIR)/leaf.o \ 274 278 $(OBJDIR)/login.o \ 275 279 $(OBJDIR)/main.o \ 276 280 $(OBJDIR)/manifest.o \ 281 + $(OBJDIR)/markdown.o \ 282 + $(OBJDIR)/markdown_html.o \ 277 283 $(OBJDIR)/md5.o \ 278 284 $(OBJDIR)/merge.o \ 279 285 $(OBJDIR)/merge3.o \ 280 286 $(OBJDIR)/moderate.o \ 281 287 $(OBJDIR)/name.o \ 282 288 $(OBJDIR)/path.o \ 283 289 $(OBJDIR)/pivot.o \ ................................................................................ 382 388 clean: 383 389 rm -rf $(OBJDIR)/* $(APPNAME) 384 390 385 391 386 392 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 387 393 $(OBJDIR)/mkindex $(TRANS_SRC) >$@ 388 394 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 389 - $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 395 + $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 390 396 touch $(OBJDIR)/headers 391 397 $(OBJDIR)/headers: Makefile 392 398 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h 393 399 Makefile: 394 400 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate 395 401 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c 396 402 ................................................................................ 779 785 $(OBJDIR)/manifest_.c: $(SRCDIR)/manifest.c $(OBJDIR)/translate 780 786 $(OBJDIR)/translate $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c 781 787 782 788 $(OBJDIR)/manifest.o: $(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h 783 789 $(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c 784 790 785 791 $(OBJDIR)/manifest.h: $(OBJDIR)/headers 792 +$(OBJDIR)/markdown_.c: $(SRCDIR)/markdown.c $(OBJDIR)/translate 793 + $(OBJDIR)/translate $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c 794 + 795 +$(OBJDIR)/markdown.o: $(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h 796 + $(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c 797 + 798 +$(OBJDIR)/markdown.h: $(OBJDIR)/headers 799 +$(OBJDIR)/markdown_html_.c: $(SRCDIR)/markdown_html.c $(OBJDIR)/translate 800 + $(OBJDIR)/translate $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c 801 + 802 +$(OBJDIR)/markdown_html.o: $(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h 803 + $(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c 804 + 805 +$(OBJDIR)/markdown_html.h: $(OBJDIR)/headers 786 806 $(OBJDIR)/md5_.c: $(SRCDIR)/md5.c $(OBJDIR)/translate 787 807 $(OBJDIR)/translate $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c 788 808 789 809 $(OBJDIR)/md5.o: $(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h 790 810 $(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c 791 811 792 812 $(OBJDIR)/md5.h: $(OBJDIR)/headers
Changes to src/makemake.tcl.
69 69 json_timeline 70 70 json_user 71 71 json_wiki 72 72 leaf 73 73 login 74 74 main 75 75 manifest 76 + markdown 77 + markdown_html 76 78 md5 77 79 merge 78 80 merge3 79 81 moderate 80 82 name 81 83 path 82 84 pivot ................................................................................ 371 373 #### Enable compiling with debug symbols (much larger binary) 372 374 # 373 375 # FOSSIL_ENABLE_SYMBOLS = 1 374 376 375 377 #### Enable JSON (http://www.json.org) support using "cson" 376 378 # 377 379 # FOSSIL_ENABLE_JSON = 1 380 + 381 +#### Enable markdown support 382 +# 383 +# FOSSIL_ENABLE_MARKDOWN = 1 378 384 379 385 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) 380 386 # 381 387 # FOSSIL_ENABLE_SSL = 1 382 388 383 389 #### Enable scripting support via Tcl/Tk 384 390 # ................................................................................ 512 518 endif 513 519 514 520 # With JSON support 515 521 ifdef FOSSIL_ENABLE_JSON 516 522 TCC += -DFOSSIL_ENABLE_JSON=1 517 523 RCC += -DFOSSIL_ENABLE_JSON=1 518 524 endif 525 + 526 +# With markdown support 527 +ifdef FOSSIL_ENABLE_MARKDOWN 528 +TCC += -DFOSSIL_ENABLE_MARKDOWN=1 529 +RCC += -DFOSSIL_ENABLE_MARKDOWN=1 530 +endif 519 531 520 532 #### We add the -static option here so that we can build a static 521 533 # executable that will run in a chroot jail. 522 534 # 523 535 LIB = -static 524 536 525 537 # MinGW: If available, use the Unicode capable runtime startup code.
Added src/markdown.c.
1 +/* 2 +** Copyright (c) 2012 D. Richard Hipp 3 +** 4 +** This program is free software; you can redistribute it and/or 5 +** modify it under the terms of the Simplified BSD License (also 6 +** known as the "2-Clause License" or "FreeBSD License".) 7 + 8 +** This program is distributed in the hope that it will be useful, 9 +** but without any warranty; without even the implied warranty of 10 +** merchantability or fitness for a particular purpose. 11 +** 12 +** Author contact information: 13 +** drh@hwaci.com 14 +** http://www.hwaci.com/drh/ 15 +** 16 +******************************************************************************* 17 +** 18 +** This file contains code to parse a blob containing markdown text, 19 +** using an external renderer. 20 +*/ 21 + 22 +#ifdef FOSSIL_ENABLE_MARKDOWN 23 + 24 +#include "config.h" 25 +#include "markdown.h" 26 + 27 +#include <assert.h> 28 +#include <string.h> 29 +#include <stdlib.h> 30 + 31 +#define MKD_LI_END 8 /* internal list flag */ 32 + 33 +/******************** 34 + * TYPE DEFINITIONS * 35 + ********************/ 36 + 37 +#if INTERFACE 38 + 39 +/* mkd_autolink -- type of autolink */ 40 +enum mkd_autolink { 41 + MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/ 42 + MKDA_NORMAL, /* normal http/http/ftp/etc link */ 43 + MKDA_EXPLICIT_EMAIL, /* e-mail link with explit mailto: */ 44 + MKDA_IMPLICIT_EMAIL /* e-mail link without mailto: */ 45 +}; 46 + 47 +/* mkd_renderer -- functions for rendering parsed data */ 48 +struct mkd_renderer { 49 + /* document level callbacks */ 50 + void (*prolog)(struct Blob *ob, void *opaque); 51 + void (*epilog)(struct Blob *ob, void *opaque); 52 + 53 + /* block level callbacks - NULL skips the block */ 54 + void (*blockcode)(struct Blob *ob, struct Blob *text, void *opaque); 55 + void (*blockquote)(struct Blob *ob, struct Blob *text, void *opaque); 56 + void (*blockhtml)(struct Blob *ob, struct Blob *text, void *opaque); 57 + void (*header)(struct Blob *ob, struct Blob *text, 58 + int level, void *opaque); 59 + void (*hrule)(struct Blob *ob, void *opaque); 60 + void (*list)(struct Blob *ob, struct Blob *text, int flags, void *opaque); 61 + void (*listitem)(struct Blob *ob, struct Blob *text, 62 + int flags, void *opaque); 63 + void (*paragraph)(struct Blob *ob, struct Blob *text, void *opaque); 64 + void (*table)(struct Blob *ob, struct Blob *head_row, struct Blob *rows, 65 + void *opaque); 66 + void (*table_cell)(struct Blob *ob, struct Blob *text, int flags, 67 + void *opaque); 68 + void (*table_row)(struct Blob *ob, struct Blob *cells, int flags, 69 + void *opaque); 70 + 71 + /* span level callbacks - NULL or return 0 prints the span verbatim */ 72 + int (*autolink)(struct Blob *ob, struct Blob *link, 73 + enum mkd_autolink type, void *opaque); 74 + int (*codespan)(struct Blob *ob, struct Blob *text, void *opaque); 75 + int (*double_emphasis)(struct Blob *ob, struct Blob *text, 76 + char c, void *opaque); 77 + int (*emphasis)(struct Blob *ob, struct Blob *text, char c,void*opaque); 78 + int (*image)(struct Blob *ob, struct Blob *link, struct Blob *title, 79 + struct Blob *alt, void *opaque); 80 + int (*linebreak)(struct Blob *ob, void *opaque); 81 + int (*link)(struct Blob *ob, struct Blob *link, struct Blob *title, 82 + struct Blob *content, void *opaque); 83 + int (*raw_html_tag)(struct Blob *ob, struct Blob *tag, void *opaque); 84 + int (*triple_emphasis)(struct Blob *ob, struct Blob *text, 85 + char c, void *opaque); 86 + 87 + /* low level callbacks - NULL copies input directly into the output */ 88 + void (*entity)(struct Blob *ob, struct Blob *entity, void *opaque); 89 + void (*normal_text)(struct Blob *ob, struct Blob *text, void *opaque); 90 + 91 + /* renderer data */ 92 + int max_work_stack; /* prevent arbitrary deep recursion, cf README */ 93 + const char *emph_chars; /* chars that trigger emphasis rendering */ 94 + void *opaque; /* opaque data send to every rendering callback */ 95 +}; 96 + 97 + 98 + 99 +/********* 100 + * FLAGS * 101 + *********/ 102 + 103 +/* list/listitem flags */ 104 +#define MKD_LIST_ORDERED 1 105 +#define MKD_LI_BLOCK 2 /* <li> containing block data */ 106 + 107 +/* table cell flags */ 108 +#define MKD_CELL_ALIGN_DEFAULT 0 109 +#define MKD_CELL_ALIGN_LEFT 1 110 +#define MKD_CELL_ALIGN_RIGHT 2 111 +#define MKD_CELL_ALIGN_CENTER 3 /* LEFT | RIGHT */ 112 +#define MKD_CELL_ALIGN_MASK 3 113 +#define MKD_CELL_HEAD 4 114 + 115 + 116 + 117 +/********************** 118 + * EXPORTED FUNCTIONS * 119 + **********************/ 120 + 121 +/* markdown -- parses the input buffer and renders it into the output buffer */ 122 +void markdown( 123 + struct Blob *ob, 124 + struct Blob *ib, 125 + const struct mkd_renderer *rndr); 126 + 127 + 128 +#endif /* INTERFACE */ 129 + 130 + 131 +/*************** 132 + * LOCAL TYPES * 133 + ***************/ 134 + 135 +/* link_ref -- reference to a link */ 136 +struct link_ref { 137 + struct Blob id; 138 + struct Blob link; 139 + struct Blob title; 140 +}; 141 + 142 + 143 +/* char_trigger -- function pointer to render active chars */ 144 +/* returns the number of chars taken care of */ 145 +/* data is the pointer of the beginning of the span */ 146 +/* offset is the number of valid chars before data */ 147 +struct render; 148 +typedef size_t (*char_trigger)( 149 + struct Blob *ob, 150 + struct render *rndr, 151 + char *data, 152 + size_t offset, 153 + size_t size); 154 + 155 + 156 +/* render -- structure containing one particular render */ 157 +struct render { 158 + struct mkd_renderer make; 159 + struct Blob refs; 160 + char_trigger active_char[256]; 161 + int work_active; 162 + struct Blob *work; 163 +}; 164 + 165 + 166 +/* html_tag -- structure for quick HTML tag search (inspired from discount) */ 167 +struct html_tag { 168 + char *text; 169 + int size; 170 +}; 171 + 172 + 173 + 174 +/******************** 175 + * GLOBAL VARIABLES * 176 + ********************/ 177 + 178 +/* block_tags -- recognised block tags, sorted by cmp_html_tag */ 179 +static struct html_tag block_tags[] = { 180 + { "p", 1 }, 181 + { "dl", 2 }, 182 + { "h1", 2 }, 183 + { "h2", 2 }, 184 + { "h3", 2 }, 185 + { "h4", 2 }, 186 + { "h5", 2 }, 187 + { "h6", 2 }, 188 + { "ol", 2 }, 189 + { "ul", 2 }, 190 + { "del", 3 }, 191 + { "div", 3 }, 192 + { "ins", 3 }, 193 + { "pre", 3 }, 194 + { "form", 4 }, 195 + { "math", 4 }, 196 + { "table", 5 }, 197 + { "iframe", 6 }, 198 + { "script", 6 }, 199 + { "fieldset", 8 }, 200 + { "noscript", 8 }, 201 + { "blockquote", 10 } 202 +}; 203 + 204 +#define INS_TAG (block_tags + 12) 205 +#define DEL_TAG (block_tags + 10) 206 + 207 + 208 + 209 +/*************************** 210 + * STATIC HELPER FUNCTIONS * 211 + ***************************/ 212 + 213 +/* build_ref_id -- collapse whitespace from input text to make it a ref id */ 214 +static int build_ref_id(struct Blob *id, const char *data, size_t size){ 215 + size_t beg, i; 216 + char *id_data; 217 + 218 + /* skip leading whitespace */ 219 + while( size>0 && (data[0]==' ' || data[0]=='\t' || data[0]=='\n') ){ 220 + data++; 221 + size--; 222 + } 223 + 224 + /* skip trailing whitespace */ 225 + while( size>0 && (data[size-1]==' ' 226 + || data[size-1]=='\t' 227 + || data[size-1]=='\n') 228 + ){ 229 + size--; 230 + } 231 + if( size==0 ) return -1; 232 + 233 + /* making the ref id */ 234 + i = 0; 235 + blob_reset(id); 236 + while( i<size ){ 237 + /* copy non-whitespace into the output buffer */ 238 + beg = i; 239 + while( i<size && !(data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ 240 + i++; 241 + } 242 + blob_append(id, data+beg, i-beg); 243 + 244 + /* add a single space and skip all consecutive whitespace */ 245 + if( i<size ) blob_append(id, " ", 1); 246 + while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } 247 + } 248 + 249 + /* turn upper-case ASCII into their lower-case counterparts */ 250 + id_data = blob_buffer(id); 251 + for(i=0; i<blob_size(id); i++){ 252 + if( id_data[i]>='A' && id_data[i]<='Z' ) id_data[i] += 'a' - 'A'; 253 + } 254 + return 0; 255 +} 256 + 257 + 258 +/* cmp_link_ref -- comparison function for link_ref sorted arrays */ 259 +static int cmp_link_ref(const void *key, const void *array_entry){ 260 + struct link_ref *lr = (void *)array_entry; 261 + return blob_compare((void *)key, &lr->id); 262 +} 263 + 264 + 265 +/* cmp_link_ref_sort -- comparison function for link_ref qsort */ 266 +static int cmp_link_ref_sort(const void *a, const void *b){ 267 + struct link_ref *lra = (void *)a; 268 + struct link_ref *lrb = (void *)b; 269 + return blob_compare(&lra->id, &lrb->id); 270 +} 271 + 272 + 273 +/* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */ 274 +static int cmp_html_tag(const void *a, const void *b){ 275 + const struct html_tag *hta = a; 276 + const struct html_tag *htb = b; 277 + if( hta->size!=htb->size ) return hta->size-htb->size; 278 + return strncasecmp(hta->text, htb->text, hta->size); 279 +} 280 + 281 + 282 +/* find_block_tag -- returns the current block tag */ 283 +static struct html_tag *find_block_tag(char *data, size_t size){ 284 + size_t i = 0; 285 + struct html_tag key; 286 + 287 + /* looking for the word end */ 288 + while( i<size 289 + && ((data[i]>='0' && data[i]<='9') 290 + || (data[i]>='A' && data[i]<='Z') 291 + || (data[i]>='a' && data[i]<='z')) 292 + ){ 293 + i++; 294 + } 295 + if( i>=size ) return 0; 296 + 297 + /* binary search of the tag */ 298 + key.text = data; 299 + key.size = i; 300 + return bsearch(&key, 301 + block_tags, 302 + (sizeof block_tags)/(sizeof block_tags[0]), 303 + sizeof block_tags[0], 304 + cmp_html_tag); 305 +} 306 + 307 + 308 +/* new_work_buffer -- get a new working buffer from the stack or create one */ 309 +static struct Blob *new_work_buffer(struct render *rndr){ 310 + struct Blob *ret = 0; 311 + 312 + if( rndr->work_active < rndr->make.max_work_stack ){ 313 + ret = rndr->work + rndr->work_active; 314 + rndr->work_active += 1; 315 + blob_reset(ret); 316 + } 317 + return ret; 318 +} 319 + 320 + 321 +/* release_work_buffer -- release the given working buffer */ 322 +static void release_work_buffer(struct render *rndr, struct Blob *buf){ 323 + if( !buf ) return; 324 + assert(rndr->work_active>0 && buf==(rndr->work+rndr->work_active-1)); 325 + rndr->work_active -= 1; 326 +} 327 + 328 + 329 + 330 +/**************************** 331 + * INLINE PARSING FUNCTIONS * 332 + ****************************/ 333 + 334 +/* is_mail_autolink -- looks for the address part of a mail autolink and '>' */ 335 +/* this is less strict than the original markdown e-mail address matching */ 336 +static size_t is_mail_autolink(char *data, size_t size){ 337 + size_t i = 0, nb = 0; 338 + /* address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' */ 339 + while( i<size && (data[i]=='-' 340 + || data[i]=='.' 341 + || data[i]=='_' 342 + || data[i]=='@' 343 + || (data[i]>='a' && data[i]<='z') 344 + || (data[i]>='A' && data[i]<='Z') 345 + || (data[i]>='0' && data[i]<='9')) 346 + ){ 347 + if( data[i]=='@' ) nb++; 348 + i++; 349 + } 350 + if( i>=size || data[i]!='>' || nb!=1 ) return 0; 351 + return i+1; 352 +} 353 + 354 + 355 +/* tag_length -- returns the length of the given tag, or 0 is it's not valid */ 356 +static size_t tag_length(char *data, size_t size, enum mkd_autolink *autolink){ 357 + size_t i, j; 358 + 359 + /* a valid tag can't be shorter than 3 chars */ 360 + if( size<3 ) return 0; 361 + 362 + /* begins with a '<' optionally followed by '/', followed by letter */ 363 + if( data[0]!='<' ) return 0; 364 + i = (data[1]=='/') ? 2 : 1; 365 + if( (data[i]<'a' || data[i]>'z') && (data[i]<'A' || data[i]>'Z') ){ 366 + return 0; 367 + } 368 + 369 + /* scheme test */ 370 + *autolink = MKDA_NOT_AUTOLINK; 371 + if( size>6 372 + && strncasecmp(data+1, "http", 4)==0 373 + && (data[5]==':' 374 + || ((data[5]=='s' || data[5]=='S') && data[6]==':')) 375 + ){ 376 + i = (data[5]==':') ? 6 : 7; 377 + *autolink = MKDA_NORMAL; 378 + }else if( size>5 && strncasecmp(data+1, "ftp:", 4)==0 ){ 379 + i = 5; 380 + *autolink = MKDA_NORMAL; 381 + }else if( size>7 && strncasecmp(data+1, "mailto:", 7)==0 ){ 382 + i = 8; 383 + /* not changing *autolink to go to the address test */ 384 + } 385 + 386 + /* completing autolink test: no whitespace or ' or " */ 387 + if( i>=size || i=='>' ){ 388 + *autolink = MKDA_NOT_AUTOLINK; 389 + }else if( *autolink ){ 390 + j = i; 391 + while( i<size 392 + && data[i]!='>' 393 + && data[i]!='\'' 394 + && data[i]!='"' 395 + && data[i]!=' ' 396 + && data[i]!='\t' 397 + && data[i]!='\t' 398 + ){ 399 + i++; 400 + } 401 + if( i>=size ) return 0; 402 + if( i>j && data[i]=='>' ) return i+1; 403 + /* one of the forbidden chars has been found */ 404 + *autolink = MKDA_NOT_AUTOLINK; 405 + }else if( (j = is_mail_autolink(data+i, size-i))!=0 ){ 406 + *autolink = (i==8) ? MKDA_EXPLICIT_EMAIL : MKDA_IMPLICIT_EMAIL; 407 + return i+j; 408 + } 409 + 410 + /* looking for sometinhg looking like a tag end */ 411 + while( i<size && data[i]!='>' ){ i++; } 412 + if( i>=size ) return 0; 413 + return i+1; 414 +} 415 + 416 + 417 +/* parse_inline -- parses inline markdown elements */ 418 +static void parse_inline( 419 + struct Blob *ob, 420 + struct render *rndr, 421 + char *data, 422 + size_t size 423 +){ 424 + size_t i = 0, end = 0; 425 + char_trigger action = 0; 426 + struct Blob work = BLOB_INITIALIZER; 427 + 428 + while( i<size ){ 429 + /* copying inactive chars into the output */ 430 + while( end<size 431 + && (action = rndr->active_char[(unsigned char)data[end]])==0 432 + ){ 433 + end++; 434 + } 435 + if( end>i ){ 436 + if( rndr->make.normal_text ){ 437 + blob_init(&work, data+i, end-i); 438 + rndr->make.normal_text(ob, &work, rndr->make.opaque); 439 + }else{ 440 + blob_append(ob, data+i, end-i); 441 + } 442 + } 443 + if( end>=size ) break; 444 + i = end; 445 + 446 + /* calling the trigger */ 447 + end = action(ob, rndr, data+i, i, size-i); 448 + if( !end ){ 449 + /* no action from the callback */ 450 + end = i+1; 451 + }else{ 452 + i += end; 453 + end = i; 454 + } 455 + } 456 +} 457 + 458 + 459 +/* find_emph_char -- looks for the next emph char, skipping other constructs */ 460 +static size_t find_emph_char(char *data, size_t size, char c){ 461 + size_t i = 1; 462 + 463 + while( i<size ){ 464 + while( i<size && data[i]!=c && data[i]!='`' && data[i]!='[' ){ i++; } 465 + if( i>=size ) return 0; 466 + if( data[i]==c ) return i; 467 + 468 + /* not counting escaped chars */ 469 + if( i && data[i-1]=='\\' ){ 470 + i++; 471 + continue; 472 + } 473 + 474 + /* skipping a code span */ 475 + if( data[i]=='`' ){ 476 + size_t span_nb = 0, bt; 477 + size_t tmp_i = 0; 478 + 479 + /* counting the number of opening backticks */ 480 + while( i<size && data[i]=='`' ){ 481 + i++; 482 + span_nb++; 483 + } 484 + if( i>=size ) return 0; 485 + 486 + /* finding the matching closing sequence */ 487 + bt = 0; 488 + while( i<size && bt<span_nb ){ 489 + if( !tmp_i && data[i]==c ) tmp_i = i; 490 + if( data[i]=='`' ) bt += 1; else bt = 0; 491 + i++; 492 + } 493 + if( i>=size ) return tmp_i; 494 + i++; 495 + 496 + /* skipping a link */ 497 + }else if( data[i]=='[' ){ 498 + size_t tmp_i = 0; 499 + char cc; 500 + i++; 501 + while( i<size && data[i]!=']' ){ 502 + if( !tmp_i && data[i]==c ) tmp_i = i; 503 + i++; 504 + } 505 + i++; 506 + while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ 507 + i++; 508 + } 509 + if( i>=size ) return tmp_i; 510 + if( data[i]!='[' && data[i]!='(' ){ /* not a link*/ 511 + if( tmp_i ) return tmp_i; else continue; 512 + } 513 + cc = data[i]; 514 + i++; 515 + while( i<size && data[i]!=cc ){ 516 + if( !tmp_i && data[i]==c ) tmp_i = i; 517 + i++; 518 + } 519 + if( i>=size ) return tmp_i; 520 + i++; 521 + } 522 + } 523 + return 0; 524 +} 525 + 526 + 527 +/* parse_emph1 -- parsing single emphase */ 528 +/* closed by a symbol not preceded by whitespace and not followed by symbol */ 529 +static size_t parse_emph1( 530 + struct Blob *ob, 531 + struct render *rndr, 532 + char *data, 533 + size_t size, 534 + char c 535 +){ 536 + size_t i = 0, len; 537 + struct Blob *work = 0; 538 + int r; 539 + 540 + if( !rndr->make.emphasis ) return 0; 541 + 542 + /* skipping one symbol if coming from emph3 */ 543 + if( size>1 && data[0]==c && data[1]==c ) i = 1; 544 + 545 + while( i<size ){ 546 + len = find_emph_char(data+i, size-i, c); 547 + if( !len ) return 0; 548 + i += len; 549 + if( i>=size ) return 0; 550 + 551 + if( i+1<size && data[i+1]==c ){ 552 + i++; 553 + continue; 554 + } 555 + if( data[i]==c 556 + && data[i-1]!=' ' 557 + && data[i-1]!='\t' 558 + && data[i-1]!='\n' 559 + ){ 560 + work = new_work_buffer(rndr); 561 + if( !work ) return 0; 562 + parse_inline(work, rndr, data, i); 563 + r = rndr->make.emphasis(ob, work, c, rndr->make.opaque); 564 + release_work_buffer(rndr, work); 565 + return r ? i+1 : 0; 566 + } 567 + } 568 + return 0; 569 +} 570 + 571 + 572 +/* parse_emph2 -- parsing single emphase */ 573 +static size_t parse_emph2( 574 + struct Blob *ob, 575 + struct render *rndr, 576 + char *data, 577 + size_t size, 578 + char c 579 +){ 580 + size_t i = 0, len; 581 + struct Blob *work = 0; 582 + int r; 583 + 584 + if( !rndr->make.double_emphasis ) return 0; 585 + 586 + while( i<size ){ 587 + len = find_emph_char(data+i, size-i, c); 588 + if( !len ) return 0; 589 + i += len; 590 + if( i+1<size 591 + && data[i]==c 592 + && data[i+1]==c 593 + && i 594 + && data[i-1]!=' ' 595 + && data[i-1]!='\t' 596 + && data[i-1]!='\n' 597 + ){ 598 + work = new_work_buffer(rndr); 599 + if( !work ) return 0; 600 + parse_inline(work, rndr, data, i); 601 + r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque); 602 + release_work_buffer(rndr, work); 603 + return r ? i+2 : 0; 604 + } 605 + i++; 606 + } 607 + return 0; 608 +} 609 + 610 + 611 +/* parse_emph3 -- parsing single emphase */ 612 +/* finds the first closing tag, and delegates to the other emph */ 613 +static size_t parse_emph3( 614 + struct Blob *ob, 615 + struct render *rndr, 616 + char *data, 617 + size_t size, 618 + char c 619 +){ 620 + size_t i = 0, len; 621 + int r; 622 + 623 + while( i<size ){ 624 + len = find_emph_char(data+i, size-i, c); 625 + if( !len ) return 0; 626 + i += len; 627 + 628 + /* skip whitespace preceded symbols */ 629 + if( data[i]!=c || data[i-1]==' ' || data[i-1]=='\t' || data[i-1]=='\n' ){ 630 + continue; 631 + } 632 + 633 + if( i+2<size 634 + && data[i+1]==c 635 + && data[i+2] == c 636 + && rndr->make.triple_emphasis 637 + ){ 638 + /* triple symbol found */ 639 + struct Blob *work = new_work_buffer(rndr); 640 + if( !work ) return 0; 641 + parse_inline(work, rndr, data, i); 642 + r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque); 643 + release_work_buffer(rndr, work); 644 + return r ? i+3 : 0; 645 + }else if( i+1<size && data[i+1]==c ){ 646 + /* double symbol found, handing over to emph1 */ 647 + len = parse_emph1(ob, rndr, data-2, size+2, c); 648 + return len ? len-2 : 0; 649 + }else{ 650 + /* single symbol found, handing over to emph2 */ 651 + len = parse_emph2(ob, rndr, data-1, size+1, c); 652 + return len ? len-1 : 0; 653 + } 654 + } 655 + return 0; 656 +} 657 + 658 + 659 +/* char_emphasis -- single and double emphasis parsing */ 660 +static size_t char_emphasis( 661 + struct Blob *ob, 662 + struct render *rndr, 663 + char *data, 664 + size_t offset, 665 + size_t size 666 +){ 667 + char c = data[0]; 668 + size_t ret; 669 + 670 + if( size>2 && data[1]!=c ){ 671 + /* whitespace cannot follow an opening emphasis */ 672 + if( data[1]==' ' 673 + || data[1]=='\t' 674 + || data[1]=='\n' 675 + || (ret = parse_emph1(ob, rndr, data+1, size-1, c))==0 676 + ){ 677 + return 0; 678 + } 679 + return ret+1; 680 + } 681 + 682 + if( size>3 && data[1]==c && data[2]!=c ){ 683 + if( data[2]==' ' 684 + || data[2]=='\t' 685 + || data[2]=='\n' 686 + || (ret = parse_emph2(ob, rndr, data+2, size-2, c))==0 687 + ){ 688 + return 0; 689 + } 690 + return ret+2; 691 + } 692 + 693 + if( size>4 && data[1]==c && data[2]==c && data[3]!=c ){ 694 + if( data[3]==' ' 695 + || data[3]=='\t' 696 + || data[3]=='\n' 697 + || (ret = parse_emph3(ob, rndr, data+3, size-3, c))==0 698 + ){ 699 + return 0; 700 + } 701 + return ret+3; 702 + } 703 + return 0; 704 +} 705 + 706 + 707 +/* char_linebreak -- '\n' preceded by two spaces (assuming linebreak != 0) */ 708 +static size_t char_linebreak( 709 + struct Blob *ob, 710 + struct render *rndr, 711 + char *data, 712 + size_t offset, 713 + size_t size 714 +){ 715 + if( offset<2 || data[-1]!=' ' || data[-2]!=' ' ) return 0; 716 + /* removing the last space from ob and rendering */ 717 + if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]==' ' ) ob->nUsed--; 718 + return rndr->make.linebreak(ob, rndr->make.opaque) ? 1 : 0; 719 +} 720 + 721 + 722 +/* char_codespan -- '`' parsing a code span (assuming codespan != 0) */ 723 +static size_t char_codespan( 724 + struct Blob *ob, 725 + struct render *rndr, 726 + char *data, 727 + size_t offset, 728 + size_t size 729 +){ 730 + size_t end, nb = 0, i, f_begin, f_end; 731 + 732 + /* counting the number of backticks in the delimiter */ 733 + while( nb<size && data[nb]=='`' ){ nb++; } 734 + 735 + /* finding the next delimiter */ 736 + i = 0; 737 + for(end=nb; end<size && i<nb; end++){ 738 + if( data[end]=='`' ) i++; else i = 0; 739 + } 740 + if( i<nb && end>=size ) return 0; /* no matching delimiter */ 741 + 742 + /* trimming outside whitespaces */ 743 + f_begin = nb; 744 + while( f_begin<end && (data[f_begin]==' ' || data[f_begin]=='\t') ){ 745 + f_begin++; 746 + } 747 + f_end = end-nb; 748 + while( f_end>nb && (data[f_end-1]==' ' || data[f_end-1]=='\t') ){ f_end--; } 749 + 750 + /* real code span */ 751 + if( f_begin<f_end ){ 752 + struct Blob work = BLOB_INITIALIZER; 753 + blob_init(&work, data+f_begin, f_end-f_begin); 754 + if( !rndr->make.codespan(ob, &work, rndr->make.opaque) ) end = 0; 755 + }else{ 756 + if( !rndr->make.codespan(ob, 0, rndr->make.opaque) ) end = 0; 757 + } 758 + return end; 759 +} 760 + 761 + 762 +/* char_escape -- '\\' backslash escape */ 763 +static size_t char_escape( 764 + struct Blob *ob, 765 + struct render *rndr, 766 + char *data, 767 + size_t offset, 768 + size_t size 769 +){ 770 + struct Blob work = BLOB_INITIALIZER; 771 + if( size>1 ){ 772 + if( rndr->make.normal_text ){ 773 + blob_init(&work, data+1,1); 774 + rndr->make.normal_text(ob, &work, rndr->make.opaque); 775 + }else{ 776 + blob_append(ob, data+1, 1); 777 + } 778 + } 779 + return 2; 780 +} 781 + 782 + 783 +/* char_entity -- '&' escaped when it doesn't belong to an entity */ 784 +/* valid entities are assumed to be anything mathing &#?[A-Za-z0-9]+; */ 785 +static size_t char_entity( 786 + struct Blob *ob, 787 + struct render *rndr, 788 + char *data, 789 + size_t offset, 790 + size_t size 791 +){ 792 + size_t end = 1; 793 + struct Blob work = BLOB_INITIALIZER; 794 + if( end<size && data[end]=='#' ) end++; 795 + while( end<size 796 + && ((data[end]>='0' && data[end]<='9') 797 + || (data[end]>='a' && data[end]<='z') 798 + || (data[end]>='A' && data[end]<='Z')) 799 + ){ 800 + end++; 801 + } 802 + if( end<size && data[end]==';' ){ 803 + /* real entity */ 804 + end++; 805 + }else{ 806 + /* lone '&' */ 807 + return 0; 808 + } 809 + if( rndr->make.entity ){ 810 + blob_init(&work, data, end); 811 + rndr->make.entity(ob, &work, rndr->make.opaque); 812 + }else{ 813 + blob_append(ob, data, end); 814 + } 815 + return end; 816 +} 817 + 818 + 819 +/* char_langle_tag -- '<' when tags or autolinks are allowed */ 820 +static size_t char_langle_tag( 821 + struct Blob *ob, 822 + struct render *rndr, 823 + char *data, 824 + size_t offset, 825 + size_t size 826 +){ 827 + enum mkd_autolink altype = MKDA_NOT_AUTOLINK; 828 + size_t end = tag_length(data, size, &altype); 829 + struct Blob work = BLOB_INITIALIZER; 830 + int ret = 0; 831 + if( end ){ 832 + if( rndr->make.autolink && altype!=MKDA_NOT_AUTOLINK ){ 833 + blob_init(&work, data+1, end-2); 834 + ret = rndr->make.autolink(ob, &work, altype, rndr->make.opaque); 835 + }else if( rndr->make.raw_html_tag ){ 836 + blob_init(&work, data, end); 837 + ret = rndr->make.raw_html_tag(ob, &work, rndr->make.opaque); 838 + } 839 + } 840 + 841 + if( !ret ){ 842 + return 0; 843 + }else{ 844 + return end; 845 + } 846 +} 847 + 848 + 849 +/* get_link_inline -- extract inline-style link and title from parenthesed data*/ 850 +static int get_link_inline( 851 + struct Blob *link, 852 + struct Blob *title, 853 + char *data, 854 + size_t size 855 +){ 856 + size_t i = 0, mark; 857 + size_t link_b, link_e; 858 + size_t title_b = 0, title_e = 0; 859 + 860 + /* skipping initial whitespace */ 861 + while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } 862 + link_b = i; 863 + 864 + /* looking for link end: ' " */ 865 + while( i<size && data[i]!='\'' && data[i]!='"' ){ i++; } 866 + link_e = i; 867 + 868 + /* looking for title end if present */ 869 + if( data[i]=='\'' || data[i]=='"' ){ 870 + i++; 871 + title_b = i; 872 + 873 + /* skipping whitespaces after title */ 874 + title_e = size-1; 875 + while( title_e>title_b 876 + && (data[title_e]==' ' 877 + || data[title_e]=='\t' 878 + || data[title_e]=='\n') 879 + ){ 880 + title_e--; 881 + } 882 + 883 + /* checking for closing quote presence */ 884 + if (data[title_e] != '\'' && data[title_e] != '"') { 885 + title_b = title_e = 0; 886 + link_e = i; 887 + } 888 + } 889 + 890 + /* remove whitespace at the end of the link */ 891 + while( link_e>link_b 892 + && (data[link_e-1]==' ' 893 + || data[link_e-1]=='\t' 894 + || data[link_e-1]=='\n') 895 + ){ 896 + link_e--; 897 + } 898 + 899 + /* remove optional angle brackets around the link */ 900 + if( data[link_b]=='<' ) link_b += 1; 901 + if( data[link_e-1]=='>' ) link_e -= 1; 902 + 903 + /* escape backslashed character from link */ 904 + blob_reset(link); 905 + i = link_b; 906 + while( i<link_e ){ 907 + mark = i; 908 + while( i<link_e && data[i]!='\\' ){ i++; } 909 + blob_append(link, data+mark, i-mark); 910 + while( i<link_e && data[i]=='\\' ){ i++; } 911 + } 912 + 913 + /* handing back title */ 914 + blob_reset(title); 915 + if( title_e>title_b ) blob_append(title, data+title_b, title_e-title_b); 916 + 917 + /* this function always succeed */ 918 + return 0; 919 +} 920 + 921 + 922 +/* get_link_ref -- extract referenced link and title from id */ 923 +static int get_link_ref( 924 + struct render *rndr, 925 + struct Blob *link, 926 + struct Blob *title, 927 + char *data, 928 + size_t size 929 +){ 930 + struct link_ref *lr; 931 + 932 + /* find the link from its id (stored temporarily in link) */ 933 + blob_reset(link); 934 + if( build_ref_id(link, data, size)<0 ) return -1; 935 + lr = bsearch(link, 936 + blob_buffer(&rndr->refs), 937 + blob_size(&rndr->refs)/sizeof(struct link_ref), 938 + sizeof (struct link_ref), 939 + cmp_link_ref); 940 + if( !lr ) return -1; 941 + 942 + /* fill the output buffers */ 943 + blob_reset(link); 944 + blob_reset(title); 945 + blob_append(link, blob_buffer(&lr->link), blob_size(&lr->link)); 946 + blob_append(title, blob_buffer(&lr->title), blob_size(&lr->title)); 947 + return 0; 948 +} 949 + 950 + 951 +/* char_link -- '[': parsing a link or an image */ 952 +static size_t char_link( 953 + struct Blob *ob, 954 + struct render *rndr, 955 + char *data, 956 + size_t offset, 957 + size_t size 958 +){ 959 + int is_img = (offset && data[-1] == '!'), level; 960 + size_t i = 1, txt_e; 961 + struct Blob *content = 0; 962 + struct Blob *link = 0; 963 + struct Blob *title = 0; 964 + int text_has_nl = 0, ret; 965 + 966 + /* checking whether the correct renderer exists */ 967 + if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){ 968 + return 0; 969 + } 970 + 971 + /* looking for the matching closing bracket */ 972 + for(level=1; i<size; i++){ 973 + if( data[i]=='\n' ) text_has_nl = 1; 974 + else if( data[i-1]=='\\' ) continue; 975 + else if( data[i]=='[' ) level += 1; 976 + else if( data[i]==']' ){ 977 + level--; 978 + if( level<=0 ) break; 979 + } 980 + } 981 + if( i>=size ) return 0; 982 + txt_e = i; 983 + i++; 984 + 985 + /* skip any amount of whitespace or newline */ 986 + /* (this is much more laxist than original markdown syntax) */ 987 + while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } 988 + 989 + /* allocate temporary buffers to store content, link and title */ 990 + content = new_work_buffer(rndr); 991 + link = new_work_buffer(rndr); 992 + title = new_work_buffer(rndr); 993 + if( !title ) return 0; 994 + ret = 0; /* error if we don't get to the callback */ 995 + 996 + /* inline style link */ 997 + if( i<size && data[i]=='(' ){ 998 + size_t span_end = i; 999 + while( span_end<size 1000 + && !(data[span_end]==')' && (span_end==i || data[span_end-1]!='\\')) 1001 + ){ 1002 + span_end++; 1003 + } 1004 + 1005 + if( span_end>=size 1006 + || get_link_inline(link, title, data+i+1, span_end-(i+1))<0 1007 + ){ 1008 + goto char_link_cleanup; 1009 + } 1010 + 1011 + i = span_end+1; 1012 + 1013 + /* reference style link */ 1014 + }else if( i<size && data[i]=='[' ){ 1015 + char *id_data; 1016 + size_t id_size, id_end = i; 1017 + 1018 + while( id_end<size && data[id_end]!=']' ){ id_end++; } 1019 + 1020 + if( id_end>=size ) goto char_link_cleanup; 1021 + 1022 + if( i+1==id_end ){ 1023 + /* implicit id - use the contents */ 1024 + id_data = data+1; 1025 + id_size = txt_e-1; 1026 + }else{ 1027 + /* explici id - between brackets */ 1028 + id_data = data+i+1; 1029 + id_size = id_end-(i+1); 1030 + } 1031 + 1032 + if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){ 1033 + goto char_link_cleanup; 1034 + } 1035 + 1036 + i = id_end+1; 1037 + 1038 + /* shortcut reference style link */ 1039 + }else{ 1040 + if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){ 1041 + goto char_link_cleanup; 1042 + } 1043 + 1044 + /* rewinding the whitespace */ 1045 + i = txt_e+1; 1046 + } 1047 + 1048 + /* building content: img alt is escaped, link content is parsed */ 1049 + if( txt_e>1 ){ 1050 + if( is_img ) blob_append(content, data+1, txt_e-1); 1051 + else parse_inline(content, rndr, data+1, txt_e-1); 1052 + } 1053 + 1054 + /* calling the relevant rendering function */ 1055 + if( is_img ){ 1056 + if( blob_size(ob)>0 && blob_buffer(ob)[blob_size(ob)-1]=='!' ) ob->nUsed--; 1057 + ret = rndr->make.image(ob, link, title, content, rndr->make.opaque); 1058 + }else{ 1059 + ret = rndr->make.link(ob, link, title, content, rndr->make.opaque); 1060 + } 1061 + 1062 + /* cleanup */ 1063 +char_link_cleanup: 1064 + release_work_buffer(rndr, title); 1065 + release_work_buffer(rndr, link); 1066 + release_work_buffer(rndr, content); 1067 + return ret ? i : 0; 1068 +} 1069 + 1070 + 1071 + 1072 +/********************************* 1073 + * BLOCK-LEVEL PARSING FUNCTIONS * 1074 + *********************************/ 1075 + 1076 +/* is_empty -- returns the line length when it is empty, 0 otherwise */ 1077 +static size_t is_empty(char *data, size_t size){ 1078 + size_t i; 1079 + for(i=0; i<size && data[i]!='\n'; i++){ 1080 + if( data[i]!=' ' && data[i]!='\t' ) return 0; 1081 + } 1082 + return i+1; 1083 +} 1084 + 1085 + 1086 +/* is_hrule -- returns whether a line is a horizontal rule */ 1087 +static int is_hrule(char *data, size_t size){ 1088 + size_t i = 0, n = 0; 1089 + char c; 1090 + 1091 + /* skipping initial spaces */ 1092 + if( size<3 ) return 0; 1093 + if( data[0]==' ' ){ 1094 + i++; 1095 + if( data[1]==' ' ){ 1096 + i++; 1097 + if( data[2]==' ' ){ 1098 + i++; 1099 + } 1100 + } 1101 + } 1102 + 1103 + /* looking at the hrule char */ 1104 + if( i+2>=size || (data[i]!='*' && data[i]!='-' && data[i]!='_') ) return 0; 1105 + c = data[i]; 1106 + 1107 + /* the whole line must be the char or whitespace */ 1108 + while (i < size && data[i] != '\n') { 1109 + if( data[i]==c ){ 1110 + n += 1; 1111 + }else if( data[i]!=' ' && data[i]!='\t' ){ 1112 + return 0; 1113 + } 1114 + i++; 1115 + } 1116 + 1117 + return n>=3; 1118 +} 1119 + 1120 + 1121 +/* is_headerline -- returns whether the line is a setext-style hdr underline */ 1122 +static int is_headerline(char *data, size_t size){ 1123 + size_t i = 0; 1124 + 1125 + /* test of level 1 header */ 1126 + if( data[i]=='=' ){ 1127 + for(i=1; i<size && data[i]=='='; i++); 1128 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1129 + return (i>=size || data[i]=='\n') ? 1 : 0; 1130 + } 1131 + 1132 + /* test of level 2 header */ 1133 + if( data[i]=='-' ){ 1134 + for(i=1; i<size && data[i]=='-'; i++); 1135 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1136 + return (i>=size || data[i]=='\n') ? 2 : 0; 1137 + } 1138 + 1139 + return 0; 1140 +} 1141 + 1142 + 1143 +/* is_table_sep -- returns wether there is a table separator at the given pos */ 1144 +static int is_table_sep(char *data, size_t pos){ 1145 + return data[pos]=='|' && (pos==0 || data[pos-1]!='\\'); 1146 +} 1147 + 1148 + 1149 +/* is_tableline -- returns the number of column tables in the given line */ 1150 +static int is_tableline(char *data, size_t size){ 1151 + size_t i = 0; 1152 + int n_sep = 0, outer_sep = 0; 1153 + 1154 + /* skip initial blanks */ 1155 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1156 + 1157 + /* check for initial '|' */ 1158 + if( i<size && data[i]=='|') outer_sep++; 1159 + 1160 + /* count the number of pipes in the line */ 1161 + for(n_sep=0; i<size && data[i]!='\n'; i++){ 1162 + if( is_table_sep(data, i) ) n_sep++; 1163 + } 1164 + 1165 + /* march back to check for optional last '|' before blanks and EOL */ 1166 + while( i && (data[i-1]==' ' || data[i-1]=='\t' || data[i-1]=='\n') ){ i--; } 1167 + if( i && is_table_sep(data, i-1) ) outer_sep += 1; 1168 + 1169 + /* return the number of column or 0 if it's not a table line */ 1170 + return (n_sep>0) ? (n_sep-outer_sep+1) : 0; 1171 +} 1172 + 1173 + 1174 +/* prefix_quote -- returns blockquote prefix length */ 1175 +static size_t prefix_quote(char *data, size_t size){ 1176 + size_t i = 0; 1177 + if( i<size && data[i]==' ' ) i++; 1178 + if( i<size && data[i]==' ' ) i++; 1179 + if( i<size && data[i]==' ' ) i++; 1180 + if( i<size && data[i]=='>' ){ 1181 + if( i+1<size && (data[i+1]==' ' || data[i+1]=='\t') ){ 1182 + return i + 2; 1183 + }else{ 1184 + return i + 1; 1185 + } 1186 + }else{ 1187 + return 0; 1188 + } 1189 +} 1190 + 1191 + 1192 +/* prefix_code -- returns prefix length for block code*/ 1193 +static size_t prefix_code(char *data, size_t size){ 1194 + if( size>0 && data[0]=='\t' ) return 1; 1195 + if( size>3 && data[0]==' ' && data[1]==' ' && data[2]==' ' && data[3]==' ' ){ 1196 + return 4; 1197 + } 1198 + return 0; 1199 +} 1200 + 1201 +/* prefix_oli -- returns ordered list item prefix */ 1202 +static size_t prefix_oli(char *data, size_t size){ 1203 + size_t i = 0; 1204 + if( i<size && data[i]==' ') i++; 1205 + if( i<size && data[i]==' ') i++; 1206 + if( i<size && data[i]==' ') i++; 1207 + 1208 + if( i>=size || data[i]<'0' || data[i]>'9' ) return 0; 1209 + while( i<size && data[i]>='0' && data[i]<='9' ){ i++; } 1210 + 1211 + if( i+1>=size 1212 + || data[i]!='.' 1213 + || (data[i+1]!=' ' && data[i+1]!='\t') 1214 + ){ 1215 + return 0; 1216 + } 1217 + i = i+2; 1218 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1219 + return i; 1220 +} 1221 + 1222 + 1223 +/* prefix_uli -- returns ordered list item prefix */ 1224 +static size_t prefix_uli(char *data, size_t size){ 1225 + size_t i = 0; 1226 + if( i<size && data[i]==' ') i++; 1227 + if( i<size && data[i]==' ') i++; 1228 + if( i<size && data[i]==' ') i++; 1229 + if( i+1>=size 1230 + || (data[i]!='*' && data[i]!='+' && data[i]!='-') 1231 + || (data[i+1]!=' ' && data[i+1]!='\t') 1232 + ){ 1233 + return 0; 1234 + } 1235 + i = i+2; 1236 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1237 + return i; 1238 +} 1239 + 1240 + 1241 +/* parse_block predeclaration */ 1242 +static void parse_block( 1243 + struct Blob *ob, 1244 + struct render *rndr, 1245 + char *data, 1246 + size_t size); 1247 + 1248 + 1249 +/* parse_blockquote -- hanldes parsing of a blockquote fragment */ 1250 +static size_t parse_blockquote( 1251 + struct Blob *ob, 1252 + struct render *rndr, 1253 + char *data, 1254 + size_t size 1255 +){ 1256 + size_t beg, end = 0, pre, work_size = 0; 1257 + char *work_data = 0; 1258 + struct Blob *out = new_work_buffer(rndr); 1259 + 1260 + beg = 0; 1261 + while( beg<size ){ 1262 + for(end=beg+1; end<size && data[end-1]!='\n'; end++); 1263 + pre = prefix_quote(data+beg, end-beg); 1264 + if( pre ){ 1265 + beg += pre; /* skipping prefix */ 1266 + }else if( is_empty(data+beg, end-beg) 1267 + && (end>=size 1268 + || (prefix_quote(data+end, size-end)==0 1269 + && !is_empty(data+end, size-end))) 1270 + ){ 1271 + /* empty line followed by non-quote line */ 1272 + break; 1273 + } 1274 + if( beg<end ){ /* copy into the in-place working buffer */ 1275 + if( !work_data ){ 1276 + work_data = data+beg; 1277 + }else if( (data+beg)!=(work_data+work_size) ){ 1278 + memmove(work_data+work_size, data+beg, end-beg); 1279 + } 1280 + work_size += end-beg; 1281 + } 1282 + beg = end; 1283 + } 1284 + 1285 + if( rndr->make.blockquote ){ 1286 + struct Blob fallback = BLOB_INITIALIZER; 1287 + if( out ){ 1288 + parse_block(out, rndr, work_data, work_size); 1289 + }else{ 1290 + blob_init(&fallback, work_data, work_size); 1291 + } 1292 + rndr->make.blockquote(ob, out ? out : &fallback, rndr->make.opaque); 1293 + } 1294 + release_work_buffer(rndr, out); 1295 + return end; 1296 +} 1297 + 1298 + 1299 +/* parse_blockquote -- hanldes parsing of a regular paragraph */ 1300 +static size_t parse_paragraph( 1301 + struct Blob *ob, 1302 + struct render *rndr, 1303 + char *data, 1304 + size_t size 1305 +){ 1306 + size_t i = 0, end = 0; 1307 + int level = 0; 1308 + char *work_data = data; 1309 + size_t work_size = 0; 1310 + struct Blob fallback = BLOB_INITIALIZER; 1311 + 1312 + while( i<size ){ 1313 + for(end=i+1; end<size && data[end-1]!='\n'; end++); 1314 + if( is_empty(data+i, size-i) 1315 + || (level = is_headerline(data+i, size-i))!= 0 1316 + ){ 1317 + break; 1318 + } 1319 + if( (i && data[i]=='#') || is_hrule(data+i, size-i) ){ 1320 + end = i; 1321 + break; 1322 + } 1323 + i = end; 1324 + } 1325 + 1326 + work_size = i; 1327 + while( work_size && data[work_size-1]=='\n' ){ work_size--; } 1328 + 1329 + if( !level ){ 1330 + if( rndr->make.paragraph ){ 1331 + struct Blob *tmp = new_work_buffer(rndr); 1332 + if( tmp ){ 1333 + parse_inline(tmp, rndr, work_data, work_size); 1334 + }else{ 1335 + blob_init(&fallback, work_data, work_size); 1336 + } 1337 + rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); 1338 + release_work_buffer(rndr, tmp); 1339 + } 1340 + }else{ 1341 + if( work_size ){ 1342 + size_t beg; 1343 + i = work_size; 1344 + work_size -= 1; 1345 + while( work_size && data[work_size]!='\n' ){ work_size--; } 1346 + beg = work_size+1; 1347 + while( work_size && data[work_size-1]=='\n'){ work_size--; } 1348 + if( work_size ){ 1349 + struct Blob *tmp = new_work_buffer(rndr); 1350 + if( tmp ){ 1351 + parse_inline(tmp, rndr, work_data, work_size); 1352 + }else{ 1353 + blob_init (&fallback, work_data, work_size); 1354 + } 1355 + if( rndr->make.paragraph ){ 1356 + rndr->make.paragraph(ob, tmp ? tmp : &fallback, rndr->make.opaque); 1357 + } 1358 + release_work_buffer(rndr, tmp); 1359 + work_data += beg; 1360 + work_size = i - beg; 1361 + }else{ 1362 + work_size = i; 1363 + } 1364 + } 1365 + 1366 + if( rndr->make.header ){ 1367 + struct Blob *span = new_work_buffer(rndr); 1368 + if( span ){ 1369 + parse_inline(span, rndr, work_data, work_size); 1370 + rndr->make.header(ob, span, level, rndr->make.opaque); 1371 + }else{ 1372 + blob_init(&fallback, work_data, work_size); 1373 + rndr->make.header(ob, &fallback, level, rndr->make.opaque); 1374 + } 1375 + release_work_buffer(rndr, span); 1376 + } 1377 + } 1378 + return end; 1379 +} 1380 + 1381 + 1382 +/* parse_blockquote -- hanldes parsing of a block-level code fragment */ 1383 +static size_t parse_blockcode( 1384 + struct Blob *ob, 1385 + struct render *rndr, 1386 + char *data, 1387 + size_t size 1388 +){ 1389 + size_t beg, end, pre; 1390 + struct Blob *work = new_work_buffer(rndr); 1391 + if( !work ) work = ob; 1392 + 1393 + beg = 0; 1394 + while( beg<size ){ 1395 + for(end=beg+1; end<size && data[end-1]!='\n'; end++); 1396 + pre = prefix_code(data+beg, end-beg); 1397 + if( pre ){ 1398 + beg += pre; /* skipping prefix */ 1399 + }else if( !is_empty(data+beg, end-beg) ){ 1400 + /* non-empty non-prefixed line breaks the pre */ 1401 + break; 1402 + } 1403 + if( beg<end ){ 1404 + /* verbatim copy to the working buffer, escaping entities */ 1405 + if( is_empty(data + beg, end - beg) ){ 1406 + blob_append(work, "\n", 1); 1407 + }else{ 1408 + blob_append(work, data+beg, end-beg); 1409 + } 1410 + } 1411 + beg = end; 1412 + } 1413 + 1414 + end = blob_size(work); 1415 + while( end>0 && blob_buffer(work)[end-1]=='\n' ){ end--; } 1416 + work->nUsed = end; 1417 + blob_append(work, "\n", 1); 1418 + 1419 + if( work!=ob ){ 1420 + if( rndr->make.blockcode ){ 1421 + rndr->make.blockcode(ob, work, rndr->make.opaque); 1422 + } 1423 + release_work_buffer(rndr, work); 1424 + } 1425 + return beg; 1426 +} 1427 + 1428 + 1429 +/* parse_listitem -- parsing of a single list item */ 1430 +/* assuming initial prefix is already removed */ 1431 +static size_t parse_listitem( 1432 + struct Blob *ob, 1433 + struct render *rndr, 1434 + char *data, 1435 + size_t size, 1436 + int *flags 1437 +){ 1438 + struct Blob fallback = BLOB_INITIALIZER; 1439 + struct Blob *work = 0, *inter = 0; 1440 + size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; 1441 + int in_empty = 0, has_inside_empty = 0; 1442 + 1443 + /* keeping track of the first indentation prefix */ 1444 + if( size>1 && data[0]==' ' ){ 1445 + orgpre = 1; 1446 + if( size>2 && data[1]==' ' ){ 1447 + orgpre = 2; 1448 + if( size>3 && data[2]==' ' ){ 1449 + orgpre = 3; 1450 + } 1451 + } 1452 + } 1453 + beg = prefix_uli(data, size); 1454 + if( !beg ) beg = prefix_oli(data, size); 1455 + if( !beg ) return 0; 1456 + /* skipping to the beginning of the following line */ 1457 + end = beg; 1458 + while( end<size && data[end-1]!='\n' ){ end++; } 1459 + 1460 + /* getting working buffers */ 1461 + work = new_work_buffer(rndr); 1462 + inter = new_work_buffer(rndr); 1463 + if( !work ) work = &fallback; 1464 + 1465 + /* putting the first line into the working buffer */ 1466 + blob_append(work, data+beg, end-beg); 1467 + beg = end; 1468 + 1469 + /* process the following lines */ 1470 + while( beg<size ){ 1471 + end++; 1472 + while( end<size && data[end-1]!='\n' ){ end++; } 1473 + 1474 + /* process an empty line */ 1475 + if( is_empty(data+beg, end-beg) ){ 1476 + in_empty = 1; 1477 + beg = end; 1478 + continue; 1479 + } 1480 + 1481 + /* computing the indentation */ 1482 + i = 0; 1483 + if( end-beg>1 && data[beg]==' ' ){ 1484 + i = 1; 1485 + if( end-beg>2 && data[beg+1]==' ' ){ 1486 + i = 2; 1487 + if( end-beg>3 && data[beg+2]==' ' ){ 1488 + i = 3; 1489 + if( end-beg>3 && data[beg+3]==' ' ){ 1490 + i = 4; 1491 + } 1492 + } 1493 + } 1494 + } 1495 + pre = i; 1496 + if( data[beg]=='\t' ){ i = 1; pre = 8; } 1497 + 1498 + /* checking for a new item */ 1499 + if( (prefix_uli(data+beg+i, end-beg-i) && !is_hrule(data+beg+i, end-beg-i)) 1500 + || prefix_oli(data+beg+i, end-beg-i) 1501 + ){ 1502 + if( in_empty ) has_inside_empty = 1; 1503 + if( pre == orgpre ){ /* the following item must have */ 1504 + break; /* the same indentation */ 1505 + } 1506 + if( !sublist ) sublist = blob_size(work); 1507 + 1508 + /* joining only indented stuff after empty lines */ 1509 + }else if( in_empty && i<4 && data[beg]!='\t' ){ 1510 + *flags |= MKD_LI_END; 1511 + break; 1512 + }else if( in_empty ){ 1513 + blob_append(work, "\n", 1); 1514 + has_inside_empty = 1; 1515 + } 1516 + in_empty = 0; 1517 + 1518 + /* adding the line without prefix into the working buffer */ 1519 + blob_append(work, data+beg+i, end-beg-i); 1520 + beg = end; 1521 + } 1522 + 1523 + /* non-recursive fallback when working buffer stack is full */ 1524 + if( !inter ){ 1525 + if( rndr->make.listitem ){ 1526 + rndr->make.listitem(ob, work, *flags, rndr->make.opaque); 1527 + } 1528 + if( work!=&fallback ) release_work_buffer(rndr, work); 1529 + blob_zero(&fallback); 1530 + return beg; 1531 + } 1532 + 1533 + /* render of li contents */ 1534 + if( has_inside_empty ) *flags |= MKD_LI_BLOCK; 1535 + if( *flags & MKD_LI_BLOCK ){ 1536 + /* intermediate render of block li */ 1537 + if( sublist && sublist<blob_size(work) ){ 1538 + parse_block(inter, rndr, blob_buffer(work), sublist); 1539 + parse_block(inter, 1540 + rndr, 1541 + blob_buffer(work)+sublist, 1542 + blob_size(work)-sublist); 1543 + }else{ 1544 + parse_block(inter, rndr, blob_buffer(work), blob_size(work)); 1545 + } 1546 + }else{ 1547 + /* intermediate render of inline li */ 1548 + if( sublist && sublist<blob_size(work) ){ 1549 + parse_inline(inter, rndr, blob_buffer(work), sublist); 1550 + parse_block(inter, 1551 + rndr, 1552 + blob_buffer(work)+sublist, 1553 + blob_size(work)-sublist); 1554 + }else{ 1555 + parse_inline(inter, rndr, blob_buffer(work), blob_size(work)); 1556 + } 1557 + } 1558 + 1559 + /* render of li itself */ 1560 + if( rndr->make.listitem ){ 1561 + rndr->make.listitem(ob, inter, *flags, rndr->make.opaque); 1562 + } 1563 + release_work_buffer(rndr, inter); 1564 + if( work!=&fallback ) release_work_buffer(rndr, work); 1565 + blob_zero(&fallback); 1566 + return beg; 1567 +} 1568 + 1569 + 1570 +/* parse_list -- parsing ordered or unordered list block */ 1571 +static size_t parse_list( 1572 + struct Blob *ob, 1573 + struct render *rndr, 1574 + char *data, 1575 + size_t size, 1576 + int flags 1577 +){ 1578 + struct Blob fallback = BLOB_INITIALIZER; 1579 + struct Blob *work = new_work_buffer(rndr); 1580 + size_t i = 0, j; 1581 + if( !work ) work = &fallback; 1582 + 1583 + while( i<size ){ 1584 + j = parse_listitem(work, rndr, data+i, size-i, &flags); 1585 + i += j; 1586 + if( !j || (flags & MKD_LI_END) ) break; 1587 + } 1588 + 1589 + if( rndr->make.list ) rndr->make.list(ob, work, flags, rndr->make.opaque); 1590 + if( work!=&fallback ) release_work_buffer(rndr, work); 1591 + blob_zero(&fallback); 1592 + return i; 1593 +} 1594 + 1595 + 1596 +/* parse_atxheader -- parsing of atx-style headers */ 1597 +static size_t parse_atxheader( 1598 + struct Blob *ob, 1599 + struct render *rndr, 1600 + char *data, 1601 + size_t size 1602 +){ 1603 + int level = 0; 1604 + size_t i, end, skip, span_beg, span_size; 1605 + 1606 + if( !size || data[0]!='#' ) return 0; 1607 + 1608 + while( level<size && level<6 && data[level]=='#' ){ level++; } 1609 + for(i=level; i<size && (data[i]==' ' || data[i]=='\t'); i++); 1610 + span_beg = i; 1611 + 1612 + for(end=i; end<size && data[end]!='\n'; end++); 1613 + skip = end; 1614 + if( end<=i ) return parse_paragraph(ob, rndr, data, size); 1615 + while( end && data[end-1]=='#' ){ end--; } 1616 + while( end && (data[end-1]==' ' || data[end-1]=='\t') ){ end--; } 1617 + if( end<=i ) return parse_paragraph(ob, rndr, data, size); 1618 + 1619 + span_size = end-span_beg; 1620 + if( rndr->make.header ){ 1621 + struct Blob fallback = BLOB_INITIALIZER; 1622 + struct Blob *span = new_work_buffer(rndr); 1623 + 1624 + if( span ){ 1625 + parse_inline(span, rndr, data+span_beg, span_size); 1626 + }else{ 1627 + blob_init(&fallback, data+span_beg, span_size); 1628 + } 1629 + rndr->make.header(ob, span ? span : &fallback, level, rndr->make.opaque); 1630 + release_work_buffer(rndr, span); 1631 + } 1632 + return skip; 1633 +} 1634 + 1635 + 1636 +/* htmlblock_end -- checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */ 1637 +/* returns the length on match, 0 otherwise */ 1638 +static size_t htmlblock_end(struct html_tag *tag, char *data, size_t size){ 1639 + size_t i, w; 1640 + 1641 + /* assuming data[0]=='<' && data[1]=='/' already tested */ 1642 + 1643 + /* checking tag is a match */ 1644 + if( (tag->size+3)>=size 1645 + || strncasecmp(data+2, tag->text, tag->size) 1646 + || data[tag->size+2]!='>' 1647 + ){ 1648 + return 0; 1649 + } 1650 + 1651 + /* checking white lines */ 1652 + i = tag->size + 3; 1653 + w = 0; 1654 + if( i<size && (w = is_empty(data+i, size-i))==0 ){ 1655 + return 0; /* non-blank after tag */ 1656 + } 1657 + i += w; 1658 + w = 0; 1659 + 1660 + if( i<size && (w = is_empty(data + i, size - i))==0 ){ 1661 + return 0; /* non-blank line after tag line */ 1662 + } 1663 + return i+w; 1664 +} 1665 + 1666 + 1667 +/* parse_htmlblock -- parsing of inline HTML block */ 1668 +static size_t parse_htmlblock( 1669 + struct Blob *ob, 1670 + struct render *rndr, 1671 + char *data, 1672 + size_t size 1673 +){ 1674 + size_t i, j = 0; 1675 + struct html_tag *curtag; 1676 + int found; 1677 + size_t work_size = 0; 1678 + struct Blob work = BLOB_INITIALIZER; 1679 + 1680 + /* identification of the opening tag */ 1681 + if( size<2 || data[0]!='<' ) return 0; 1682 + curtag = find_block_tag(data+1, size-1); 1683 + 1684 + /* handling of special cases */ 1685 + if( !curtag ){ 1686 + 1687 + /* HTML comment, laxist form */ 1688 + if( size>5 && data[1]=='!' && data[2]=='-' && data[3]=='-' ){ 1689 + i = 5; 1690 + while( i<size && !(data[i-2]=='-' && data[i-1]=='-' && data[i]=='>') ){ 1691 + i++; 1692 + } 1693 + i++; 1694 + if( i<size ){ 1695 + j = is_empty(data+i, size-i); 1696 + if( j ){ 1697 + work_size = i+j; 1698 + if( !rndr->make.blockhtml ) return work_size; 1699 + blob_init(&work, data, work_size); 1700 + rndr->make.blockhtml(ob, &work, rndr->make.opaque); 1701 + return work_size; 1702 + } 1703 + } 1704 + } 1705 + 1706 + /* HR, which is the only self-closing block tag considered */ 1707 + if( size>4 1708 + && (data[1]=='h' || data[1]=='H') 1709 + && (data[2]=='r' || data[2]=='R') 1710 + ){ 1711 + i = 3; 1712 + while( i<size && data[i]!='>' ){ i++; } 1713 + if( i+1<size ){ 1714 + i += 1; 1715 + j = is_empty(data+i, size-i); 1716 + if( j ){ 1717 + work_size = i+j; 1718 + if( !rndr->make.blockhtml ) return work_size; 1719 + blob_init(&work, data, work_size); 1720 + rndr->make.blockhtml(ob, &work, rndr->make.opaque); 1721 + return work_size; 1722 + } 1723 + } 1724 + } 1725 + 1726 + /* no special case recognised */ 1727 + return 0; 1728 + } 1729 + 1730 + /* looking for an unindented matching closing tag */ 1731 + /* followed by a blank line */ 1732 + i = 1; 1733 + found = 0; 1734 +#if 0 1735 + while( i<size ){ 1736 + i++; 1737 + while( i<size && !(data[i-2]=='\n' && data[i-1]=='<' && data[i]=='/') ){ 1738 + i++; 1739 + } 1740 + if( (i+2+curtag->size)>=size ) break; 1741 + j = htmlblock_end(curtag, data+i-1, size-i+1); 1742 + if (j) { 1743 + i += j-1; 1744 + found = 1; 1745 + break; 1746 + } 1747 + } 1748 +#endif 1749 + 1750 + /* if not found, trying a second pass looking for indented match */ 1751 + /* but not if tag is "ins" or "del" (following original Markdown.pl) */ 1752 + if( !found && curtag!=INS_TAG && curtag!=DEL_TAG ){ 1753 + i = 1; 1754 + while( i<size ){ 1755 + i++; 1756 + while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; } 1757 + if( (i+2+curtag->size)>=size ) break; 1758 + j = htmlblock_end(curtag, data+i-1, size-i+1); 1759 + if (j) { 1760 + i += j-1; 1761 + found = 1; 1762 + break; 1763 + } 1764 + } 1765 + } 1766 + 1767 + if( !found ) return 0; 1768 + 1769 + /* the end of the block has been found */ 1770 + blob_init(&work, data, i); 1771 + if( rndr->make.blockhtml ){ 1772 + rndr->make.blockhtml(ob, &work, rndr->make.opaque); 1773 + } 1774 + return i; 1775 +} 1776 + 1777 + 1778 +/* parse_table_cell -- parse a cell inside a table */ 1779 +static void parse_table_cell( 1780 + struct Blob *ob, /* output blob */ 1781 + struct render *rndr, /* renderer description */ 1782 + char *data, /* input text */ 1783 + size_t size, /* input text size */ 1784 + int flags /* table flags */ 1785 +){ 1786 + struct Blob fallback = BLOB_INITIALIZER; 1787 + struct Blob *span = new_work_buffer(rndr); 1788 + 1789 + if( span ){ 1790 + parse_inline(span, rndr, data, size); 1791 + }else{ 1792 + blob_init(&fallback, data, size); 1793 + } 1794 + rndr->make.table_cell(ob, span ? span : &fallback, flags, rndr->make.opaque); 1795 + release_work_buffer(rndr, span); 1796 +} 1797 + 1798 + 1799 +/* parse_table_row -- parse an input line into a table row */ 1800 +static size_t parse_table_row( 1801 + struct Blob *ob, /* output blob for rendering */ 1802 + struct render *rndr, /* renderer description */ 1803 + char *data, /* input text */ 1804 + size_t size, /* input text size */ 1805 + int *aligns, /* array of default alignment for columns */ 1806 + size_t align_size, /* number of columns with default alignment */ 1807 + int flags /* table flags */ 1808 +){ 1809 + size_t i = 0, col = 0; 1810 + size_t beg, end, total = 0; 1811 + struct Blob *cells = new_work_buffer(rndr); 1812 + int align; 1813 + 1814 + /* skip leading blanks and sperator */ 1815 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1816 + if( i<size && data[i]=='|' ) i++; 1817 + 1818 + /* go over all the cells */ 1819 + while( i<size && total==0 ){ 1820 + /* check optional left/center align marker */ 1821 + align = 0; 1822 + if( data[i]==':' ){ 1823 + align |= MKD_CELL_ALIGN_LEFT; 1824 + i++; 1825 + } 1826 + 1827 + /* skip blanks */ 1828 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1829 + beg = i; 1830 + 1831 + /* forward to the next separator or EOL */ 1832 + while( i<size && !is_table_sep(data, i) && data[i]!='\n' ){ i++; } 1833 + end = i; 1834 + if( i<size ){ 1835 + i++; 1836 + if( data[i-1]=='\n' ) total = i; 1837 + } 1838 + 1839 + /* check optional right/center align marker */ 1840 + if( i>beg && data[end-1]==':' ){ 1841 + align |= MKD_CELL_ALIGN_RIGHT; 1842 + end--; 1843 + } 1844 + 1845 + /* remove trailing blanks */ 1846 + while( end>beg && (data[end-1]==' ' || data[end-1]=='\t') ){ end--; } 1847 + 1848 + /* skip the last cell if it was only blanks */ 1849 + /* (because it is only the optional end separator) */ 1850 + if( total && end<=beg ) continue; 1851 + 1852 + /* fallback on default alignment if not explicit */ 1853 + if( align==0 && aligns && col<align_size ) align = aligns[col]; 1854 + 1855 + /* render cells */ 1856 + if( cells ) parse_table_cell(cells, rndr, data+beg, end-beg, align|flags); 1857 + 1858 + col++; 1859 + } 1860 + 1861 + /* render the whole row and clean up */ 1862 + if( cells ){ 1863 + rndr->make.table_row(ob, cells, flags, rndr->make.opaque); 1864 + }else{ 1865 + struct Blob fallback = BLOB_INITIALIZER; 1866 + blob_init(&fallback, data, total ? total : size); 1867 + rndr->make.table_row(ob, &fallback, flags, rndr->make.opaque); 1868 + } 1869 + release_work_buffer(rndr, cells); 1870 + return total ? total : size; 1871 +} 1872 + 1873 + 1874 +/* parse_table -- parsing of a whole table */ 1875 +static size_t parse_table( 1876 + struct Blob *ob, 1877 + struct render *rndr, 1878 + char *data, 1879 + size_t size 1880 +){ 1881 + size_t i = 0, head_end, col; 1882 + size_t align_size = 0; 1883 + int *aligns = 0; 1884 + struct Blob fallback = BLOB_INITIALIZER; 1885 + struct Blob *head = 0; 1886 + struct Blob *rows = new_work_buffer(rndr); 1887 + if( !rows ) rows = &fallback; 1888 + 1889 + /* skip the first (presumably header) line */ 1890 + while( i<size && data[i]!='\n' ){ i++; } 1891 + head_end = i; 1892 + 1893 + /* fallback on end of input */ 1894 + if( i>=size ){ 1895 + parse_table_row(rows, rndr, data, size, 0, 0, 0); 1896 + rndr->make.table(ob, 0, rows, rndr->make.opaque); 1897 + if( rows!=&fallback ) release_work_buffer(rndr, rows); 1898 + return i; 1899 + } 1900 + 1901 + /* attempt to parse a table rule, i.e. blanks, dash, colons and sep */ 1902 + i++; 1903 + col = 0; 1904 + while( i<size 1905 + && (data[i]==' ' 1906 + || data[i]=='\t' 1907 + || data[i]=='-' 1908 + || data[i] == ':' 1909 + || data[i] =='|') 1910 + ){ 1911 + if( data[i] == '|' ) align_size++; 1912 + if( data[i] == ':' ) col = 1; 1913 + i += 1; 1914 + } 1915 + 1916 + if( i<size && data[i]=='\n' ){ 1917 + align_size++; 1918 + 1919 + /* render the header row */ 1920 + head = new_work_buffer(rndr); 1921 + if( head ){ 1922 + parse_table_row(head, rndr, data, head_end, 0, 0, MKD_CELL_HEAD); 1923 + } 1924 + 1925 + /* parse alignments if provided */ 1926 + if( col && (aligns=malloc(align_size * sizeof *aligns))!=0 ){ 1927 + for(i=0; i<align_size; i++) aligns[i] = 0; 1928 + col = 0; 1929 + i = head_end+1; 1930 + 1931 + /* skip initial white space and optional separator */ 1932 + while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; } 1933 + if( data[i]=='|' ) i++; 1934 + 1935 + /* compute default alignment for each column */ 1936 + while (i < size && data[i] != '\n') { 1937 + if (data[i] == ':') 1938 + aligns[col] |= MKD_CELL_ALIGN_LEFT; 1939 + while (i < size 1940 + && data[i] != '|' && data[i] != '\n') 1941 + i += 1; 1942 + if (data[i - 1] == ':') 1943 + aligns[col] |= MKD_CELL_ALIGN_RIGHT; 1944 + if (i < size && data[i] == '|') 1945 + i += 1; 1946 + col += 1; } 1947 + } 1948 + 1949 + /* point i to the beginning of next line/row */ 1950 + i++; 1951 + 1952 + }else{ 1953 + /* there is no valid ruler, continuing without header */ 1954 + i = 0; 1955 + } 1956 + 1957 + /* render the table body lines */ 1958 + while( i<size && is_tableline(data + i, size - i) ){ 1959 + i += parse_table_row(rows, rndr, data+i, size-i, aligns, align_size, 0); 1960 + } 1961 + 1962 + /* render the full table */ 1963 + rndr->make.table(ob, head, rows, rndr->make.opaque); 1964 + 1965 + /* cleanup */ 1966 + if( head ) release_work_buffer(rndr, head); 1967 + if( rows!=&fallback ) release_work_buffer(rndr, rows); 1968 + free(aligns); 1969 + return i; 1970 +} 1971 + 1972 + 1973 +/* parse_block -- parsing of one block, returning next char to parse */ 1974 +static void parse_block( 1975 + struct Blob *ob, /* output blob */ 1976 + struct render *rndr, /* renderer internal state */ 1977 + char *data, /* input text */ 1978 + size_t size /* input text size */ 1979 +){ 1980 + size_t beg, end, i; 1981 + char *txt_data; 1982 + int has_table = (rndr->make.table 1983 + && rndr->make.table_row 1984 + && rndr->make.table_cell); 1985 + 1986 + beg = 0; 1987 + while( beg<size ){ 1988 + txt_data = data+beg; 1989 + end = size-beg; 1990 + if( data[beg]=='#' ){ 1991 + beg += parse_atxheader(ob, rndr, txt_data, end); 1992 + }else if( data[beg]=='<' 1993 + && rndr->make.blockhtml 1994 + && (i = parse_htmlblock(ob, rndr, txt_data, end))!=0 1995 + ){ 1996 + beg += i; 1997 + }else if( (i=is_empty(txt_data, end))!=0 ){ 1998 + beg += i; 1999 + }else if( is_hrule(txt_data, end) ){ 2000 + if( rndr->make.hrule ) rndr->make.hrule(ob, rndr->make.opaque); 2001 + while( beg<size && data[beg]!='\n' ){ beg++; } 2002 + beg++; 2003 + }else if( prefix_quote(txt_data, end) ){ 2004 + beg += parse_blockquote(ob, rndr, txt_data, end); 2005 + }else if( prefix_code(txt_data, end) ){ 2006 + beg += parse_blockcode(ob, rndr, txt_data, end); 2007 + }else if( prefix_uli(txt_data, end) ){ 2008 + beg += parse_list(ob, rndr, txt_data, end, 0); 2009 + }else if( prefix_oli(txt_data, end) ){ 2010 + beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED); 2011 + }else if( has_table && is_tableline(txt_data, end) ){ 2012 + beg += parse_table(ob, rndr, txt_data, end); 2013 + }else{ 2014 + beg += parse_paragraph(ob, rndr, txt_data, end); 2015 + } 2016 + } 2017 +} 2018 + 2019 + 2020 + 2021 +/********************* 2022 + * REFERENCE PARSING * 2023 + *********************/ 2024 + 2025 +/* is_ref -- returns whether a line is a reference or not */ 2026 +static int is_ref( 2027 + char *data, /* input text */ 2028 + size_t beg, /* offset of the beginning of the line */ 2029 + size_t end, /* offset of the end of the text */ 2030 + size_t *last, /* last character of the link */ 2031 + struct Blob *refs /* arry of link references */ 2032 +){ 2033 + size_t i = 0; 2034 + size_t id_offset, id_end; 2035 + size_t link_offset, link_end; 2036 + size_t title_offset, title_end; 2037 + size_t line_end; 2038 + struct link_ref lr = { 2039 + BLOB_INITIALIZER, 2040 + BLOB_INITIALIZER, 2041 + BLOB_INITIALIZER 2042 + }; 2043 + 2044 + /* up to 3 optional leading spaces */ 2045 + if( beg+3>=end ) return 0; 2046 + if( data[beg]==' ' ){ 2047 + i = 1; 2048 + if( data[beg+1]==' ' ){ 2049 + i = 2; 2050 + if( data[beg+2]==' ' ){ 2051 + i = 3; 2052 + if( data[beg+3]==' ' ) return 0; 2053 + } 2054 + } 2055 + } 2056 + i += beg; 2057 + 2058 + /* id part: anything but a newline between brackets */ 2059 + if( data[i]!='[' ) return 0; 2060 + i++; 2061 + id_offset = i; 2062 + while( i<end && data[i]!='\n' && data[i]!='\r' && data[i]!=']' ){ i++; } 2063 + if( i>=end || data[i]!=']' ) return 0; 2064 + id_end = i; 2065 + 2066 + /* spacer: colon (space | tab)* newline? (space | tab)* */ 2067 + i++; 2068 + if( i>=end || data[i]!=':' ) return 0; 2069 + i++; 2070 + while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; } 2071 + if( i<end && (data[i]=='\n' || data[i]=='\r') ){ 2072 + i++; 2073 + if( i<end && data[i]=='\r' && data[i-1] == '\n' ) i++; 2074 + } 2075 + while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; } 2076 + if( i>=end ) return 0; 2077 + 2078 + /* link: whitespace-free sequence, optionally between angle brackets */ 2079 + if( data[i]=='<' ) i++; 2080 + link_offset = i; 2081 + while( i<end 2082 + && data[i]!=' ' 2083 + && data[i]!='\t' 2084 + && data[i]!='\n' 2085 + && data[i]!='\r' 2086 + ){ 2087 + i += 1; 2088 + } 2089 + if( data[i-1]=='>' ) link_end = i-1; else link_end = i; 2090 + 2091 + /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */ 2092 + while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; } 2093 + if( i<end 2094 + && data[i]!='\n' 2095 + && data[i]!='\r' 2096 + && data[i]!='\'' 2097 + && data[i]!='"' 2098 + && data[i]!='(' 2099 + ){ 2100 + return 0; 2101 + } 2102 + line_end = 0; 2103 + /* computing end-of-line */ 2104 + if( i>=end || data[i]=='\r' || data[i]=='\n' ) line_end = i; 2105 + if( i+1<end && data[i]=='\n' && data[i+1]=='\r' ) line_end = i+1; 2106 + 2107 + /* optional (space|tab)* spacer after a newline */ 2108 + if( line_end ){ 2109 + i = line_end+1; 2110 + while( i<end && (data[i]==' ' || data[i]=='\t') ){ i++; } 2111 + } 2112 + 2113 + /* optional title: any non-newline sequence enclosed in '"() 2114 + alone on its line */ 2115 + title_offset = title_end = 0; 2116 + if( i+1<end && (data[i]=='\'' || data[i]=='"' || data[i]=='(') ){ 2117 + i += 1; 2118 + title_offset = i; 2119 + /* looking for EOL */ 2120 + while( i<end && data[i]!='\n' && data[i]!='\r' ){ i++; } 2121 + if( i+1<end && data[i]=='\n' && data[i+1]=='\r' ){ 2122 + title_end = i + 1; 2123 + }else{ 2124 + title_end = i; 2125 + } 2126 + /* stepping back */ 2127 + i--; 2128 + while( i>title_offset && (data[i]==' ' || data[i]=='\t') ){ i--; } 2129 + if( i>title_offset && (data[i]=='\'' || data[i]=='"' || data[i]==')') ){ 2130 + line_end = title_end; 2131 + title_end = i; 2132 + } 2133 + } 2134 + if( !line_end ) return 0; /* garbage after the link */ 2135 + 2136 + /* a valid ref has been found, filling-in return structures */ 2137 + if( last ) *last = line_end; 2138 + if( !refs ) return 1; 2139 + if( build_ref_id(&lr.id, data+id_offset, id_end-id_offset)<0 ) return 0; 2140 + blob_append(&lr.link, data+link_offset, link_end-link_offset); 2141 + if( title_end>title_offset ){ 2142 + blob_append(&lr.title, data+title_offset, title_end-title_offset); 2143 + } 2144 + blob_append(refs, (char *)&lr, sizeof lr); 2145 + return 1; 2146 +} 2147 + 2148 + 2149 + 2150 +/********************** 2151 + * EXPORTED FUNCTIONS * 2152 + **********************/ 2153 + 2154 +/* markdown -- parses the input buffer and renders it into the output buffer */ 2155 +void markdown( 2156 + struct Blob *ob, /* output blob for rendered text */ 2157 + struct Blob *ib, /* input blob in markdown */ 2158 + const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ 2159 +){ 2160 + struct link_ref *lr; 2161 + struct Blob text = BLOB_INITIALIZER; 2162 + size_t i, beg, end; 2163 + struct render rndr; 2164 + char *ib_data; 2165 + 2166 + /* filling the render structure */ 2167 + if( !rndrer ) return; 2168 + rndr.make = *rndrer; 2169 + if( rndr.make.max_work_stack<1 ) rndr.make.max_work_stack = 1; 2170 + rndr.work_active = 0; 2171 + rndr.work = fossil_malloc(rndr.make.max_work_stack * sizeof *rndr.work); 2172 + for(i=0; i<rndr.make.max_work_stack; i++) rndr.work[i] = text; 2173 + rndr.refs = text; 2174 + for(i=0; i<256; i++) rndr.active_char[i] = 0; 2175 + if( (rndr.make.emphasis 2176 + || rndr.make.double_emphasis 2177 + || rndr.make.triple_emphasis) 2178 + && rndr.make.emph_chars 2179 + ){ 2180 + for(i=0; rndr.make.emph_chars[i]; i++){ 2181 + rndr.active_char[(unsigned char)rndr.make.emph_chars[i]] = char_emphasis; 2182 + } 2183 + } 2184 + if( rndr.make.codespan ) rndr.active_char['`'] = char_codespan; 2185 + if( rndr.make.linebreak ) rndr.active_char['\n'] = char_linebreak; 2186 + if( rndr.make.image || rndr.make.link ) rndr.active_char['['] = char_link; 2187 + rndr.active_char['<'] = char_langle_tag; 2188 + rndr.active_char['\\'] = char_escape; 2189 + rndr.active_char['&'] = char_entity; 2190 + 2191 + /* first pass: looking for references, copying everything else */ 2192 + beg = 0; 2193 + ib_data = blob_buffer(ib); 2194 + while( beg<blob_size(ib) ){ /* iterating over lines */ 2195 + if( is_ref(ib_data, beg, blob_size(ib), &end, &rndr.refs) ){ 2196 + beg = end; 2197 + }else{ /* skipping to the next line */ 2198 + end = beg; 2199 + while( end<blob_size(ib) && ib_data[end]!='\n' && ib_data[end]!='\r' ){ 2200 + end += 1; 2201 + } 2202 + /* adding the line body if present */ 2203 + if( end>beg ) blob_append(&text, ib_data + beg, end - beg); 2204 + while( end<blob_size(ib) && (ib_data[end]=='\n' || ib_data[end]=='\r') ){ 2205 + /* add one \n per newline */ 2206 + if( ib_data[end]=='\n' 2207 + || (end+1<blob_size(ib) && ib_data[end+1]!='\n') 2208 + ){ 2209 + blob_append(&text, "\n", 1); 2210 + } 2211 + end += 1; 2212 + } 2213 + beg = end; 2214 + } 2215 + } 2216 + 2217 + /* sorting the reference array */ 2218 + if( blob_size(&rndr.refs) ){ 2219 + qsort(blob_buffer(&rndr.refs), 2220 + blob_size(&rndr.refs)/sizeof(struct link_ref), 2221 + sizeof(struct link_ref), 2222 + cmp_link_ref_sort); 2223 + } 2224 + 2225 + /* second pass: actual rendering */ 2226 + if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque); 2227 + parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text)); 2228 + if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque); 2229 + 2230 + /* clean-up */ 2231 + blob_zero(&text); 2232 + lr = (struct link_ref *)blob_buffer(&rndr.refs); 2233 + end = blob_size(&rndr.refs)/sizeof(struct link_ref); 2234 + for(i=0; i<end; i++){ 2235 + blob_zero(&lr[i].id); 2236 + blob_zero(&lr[i].link); 2237 + blob_zero(&lr[i].title); 2238 + } 2239 + blob_zero(&rndr.refs); 2240 + blobarray_zero(rndr.work, rndr.make.max_work_stack); 2241 + fossil_free(rndr.work); 2242 +} 2243 + 2244 +#endif /* def FOSSIL_ENABLE_MARKDOWN */
Added src/markdown_html.c.
1 +/* 2 +** Copyright (c) 2012 D. Richard Hipp 3 +** 4 +** This program is free software; you can redistribute it and/or 5 +** modify it under the terms of the Simplified BSD License (also 6 +** known as the "2-Clause License" or "FreeBSD License".) 7 + 8 +** This program is distributed in the hope that it will be useful, 9 +** but without any warranty; without even the implied warranty of 10 +** merchantability or fitness for a particular purpose. 11 +** 12 +** Author contact information: 13 +** drh@hwaci.com 14 +** http://www.hwaci.com/drh/ 15 +** 16 +******************************************************************************* 17 +** 18 +** This file contains callbacks for the markdown parser that generate 19 +** XHTML output. 20 +*/ 21 + 22 +#ifdef FOSSIL_ENABLE_MARKDOWN 23 + 24 +#include "config.h" 25 +#include "markdown_html.h" 26 + 27 +#if INTERFACE 28 + 29 +void markdown_to_html( 30 + struct Blob *input_markdown, 31 + struct Blob *output_title, 32 + struct Blob *output_body); 33 + 34 +#endif /* INTERFACE */ 35 + 36 + 37 +/* INTER_BLOCK -- skip a line between block level elements */ 38 +#define INTER_BLOCK(ob) \ 39 + do { if( blob_size(ob)>0 ) blob_append(ob, "\n", 1); } while (0) 40 + 41 +/* BLOB_APPEND_LITTERAL -- append a string litteral to a blob */ 42 +#define BLOB_APPEND_LITTERAL(blob, litteral) \ 43 + blob_append((blob), "" litteral, (sizeof litteral)-1) 44 + /* 45 + * The empty string in the second argument leads to a syntax error 46 + * when the macro is not used with a string litteral. Unfortunately 47 + * the error is not overly explicit. 48 + */ 49 + 50 +/* BLOB_APPEND_BLOB -- append blob contents to another */ 51 +#define BLOB_APPEND_BLOB(dest, src) \ 52 + blob_append((dest), blob_buffer(src), blob_size(src)) 53 + 54 + 55 +/* HTML escape */ 56 + 57 +static void html_escape(struct Blob *ob, const char *data, size_t size){ 58 + size_t beg = 0, i = 0; 59 + while( i<size ){ 60 + beg = i; 61 + while( i<size 62 + && data[i]!='<' 63 + && data[i]!='>' 64 + && data[i]!='"' 65 + && data[i]!='&' 66 + ){ 67 + i++; 68 + } 69 + blob_append(ob, data+beg, i-beg); 70 + while( i<size ){ 71 + if( data[i]=='<' ){ 72 + BLOB_APPEND_LITTERAL(ob, "<"); 73 + }else if( data[i]=='>' ){ 74 + BLOB_APPEND_LITTERAL(ob, ">"); 75 + }else if( data[i]=='&' ){ 76 + BLOB_APPEND_LITTERAL(ob, "&"); 77 + }else if( data[i]=='"' ){ 78 + BLOB_APPEND_LITTERAL(ob, """); 79 + }else{ 80 + break; 81 + } 82 + i++; 83 + } 84 + } 85 +} 86 + 87 + 88 +/* HTML block tags */ 89 + 90 +static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ 91 + char *data = blob_buffer(text); 92 + size_t first = 0, size = blob_size(text); 93 + INTER_BLOCK(ob); 94 + while( first<size && data[first]=='\n' ) first++; 95 + while( size>first && data[size-1]=='\n' ) size--; 96 + blob_append(ob, data+first, size-first); 97 + BLOB_APPEND_LITTERAL(ob, "\n"); 98 +} 99 + 100 +static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ 101 + INTER_BLOCK(ob); 102 + BLOB_APPEND_LITTERAL(ob, "<pre><code>"); 103 + html_escape(ob, blob_buffer(text), blob_size(text)); 104 + BLOB_APPEND_LITTERAL(ob, "</code></pre>\n"); 105 +} 106 + 107 +static void html_blockquote(struct Blob *ob, struct Blob *text, void *opaque){ 108 + INTER_BLOCK(ob); 109 + BLOB_APPEND_LITTERAL(ob, "<blockquote>\n"); 110 + BLOB_APPEND_BLOB(ob, text); 111 + BLOB_APPEND_LITTERAL(ob, "</blockquote>\n"); 112 +} 113 + 114 +static void html_header( 115 + struct Blob *ob, 116 + struct Blob *text, 117 + int level, 118 + void *opaque 119 +){ 120 + struct Blob *title = opaque; 121 + /* The first header at the beginning of a text is considered as 122 + * a title and not output. */ 123 + if( blob_size(ob)==0 && blob_size(title)==0 ){ 124 + BLOB_APPEND_BLOB(title, text); 125 + return; 126 + } 127 + INTER_BLOCK(ob); 128 + blob_appendf(ob, "<h%d>", level); 129 + BLOB_APPEND_BLOB(ob, text); 130 + blob_appendf(ob, "</h%d>", level); 131 +} 132 + 133 +static void html_hrule(struct Blob *ob, void *opaque){ 134 + INTER_BLOCK(ob); 135 + BLOB_APPEND_LITTERAL(ob, "<hr />\n"); 136 +} 137 + 138 + 139 +static void html_list( 140 + struct Blob *ob, 141 + struct Blob *text, 142 + int flags, 143 + void *opaque 144 +){ 145 + char ol[] = "ol"; 146 + char ul[] = "ul"; 147 + char *tag = (flags & MKD_LIST_ORDERED) ? ol : ul; 148 + INTER_BLOCK(ob); 149 + blob_appendf(ob, "<%s>\n", tag); 150 + BLOB_APPEND_BLOB(ob, text); 151 + blob_appendf(ob, "</%s>\n", tag); 152 +} 153 + 154 +static void html_list_item( 155 + struct Blob *ob, 156 + struct Blob *text, 157 + int flags, 158 + void *opaque 159 +){ 160 + char *text_data = blob_buffer(text); 161 + size_t text_size = blob_size(text); 162 + while( text_size>0 && text_data[text_size-1]=='\n' ) text_size--; 163 + BLOB_APPEND_LITTERAL(ob, "<li>"); 164 + blob_append(ob, text_data, text_size); 165 + BLOB_APPEND_LITTERAL(ob, "</li>\n"); 166 +} 167 + 168 +static void html_paragraph(struct Blob *ob, struct Blob *text, void *opaque){ 169 + INTER_BLOCK(ob); 170 + BLOB_APPEND_LITTERAL(ob, "<p>"); 171 + BLOB_APPEND_BLOB(ob, text); 172 + BLOB_APPEND_LITTERAL(ob, "</p>\n"); 173 +} 174 + 175 + 176 +static void html_table( 177 + struct Blob *ob, 178 + struct Blob *head_row, 179 + struct Blob *rows, 180 + void *opaque 181 +){ 182 + INTER_BLOCK(ob); 183 + BLOB_APPEND_LITTERAL(ob, "<table>\n"); 184 + if( head_row && blob_size(head_row)>0 ){ 185 + BLOB_APPEND_LITTERAL(ob, "<thead>\n"); 186 + BLOB_APPEND_BLOB(ob, head_row); 187 + BLOB_APPEND_LITTERAL(ob, "</thead>\n<tbody>\n"); 188 + } 189 + if( rows ){ 190 + BLOB_APPEND_BLOB(ob, rows); 191 + } 192 + if( head_row && blob_size(head_row)>0 ){ 193 + BLOB_APPEND_LITTERAL(ob, "</tbody>\n"); 194 + } 195 + BLOB_APPEND_LITTERAL(ob, "</table>\n"); 196 +} 197 + 198 +static void html_table_cell( 199 + struct Blob *ob, 200 + struct Blob *text, 201 + int flags, 202 + void *opaque 203 +){ 204 + if( flags & MKD_CELL_HEAD ){ 205 + BLOB_APPEND_LITTERAL(ob, " <th"); 206 + }else{ 207 + BLOB_APPEND_LITTERAL(ob, " <td"); 208 + } 209 + switch( flags & MKD_CELL_ALIGN_MASK ){ 210 + case MKD_CELL_ALIGN_LEFT: { 211 + BLOB_APPEND_LITTERAL(ob, " align=\"left\""); 212 + break; 213 + } 214 + case MKD_CELL_ALIGN_RIGHT: { 215 + BLOB_APPEND_LITTERAL(ob, " align=\"right\""); 216 + break; 217 + } 218 + case MKD_CELL_ALIGN_CENTER: { 219 + BLOB_APPEND_LITTERAL(ob, " align=\"center\""); 220 + break; 221 + } 222 + } 223 + BLOB_APPEND_LITTERAL(ob, ">"); 224 + BLOB_APPEND_BLOB(ob, text); 225 + if( flags & MKD_CELL_HEAD ){ 226 + BLOB_APPEND_LITTERAL(ob, "</th>\n"); 227 + }else{ 228 + BLOB_APPEND_LITTERAL(ob, "</td>\n"); 229 + } 230 +} 231 + 232 +static void html_table_row( 233 + struct Blob *ob, 234 + struct Blob *cells, 235 + int flags, 236 + void *opaque 237 +){ 238 + BLOB_APPEND_LITTERAL(ob, " <tr>\n"); 239 + BLOB_APPEND_BLOB(ob, cells); 240 + BLOB_APPEND_LITTERAL(ob, " </tr>\n"); 241 +} 242 + 243 + 244 + 245 +/* HTML span tags */ 246 + 247 +static int html_raw_span(struct Blob *ob, struct Blob *text, void *opaque){ 248 + BLOB_APPEND_BLOB(ob, text); 249 + return 1; 250 +} 251 + 252 +static int html_autolink( 253 + struct Blob *ob, 254 + struct Blob *link, 255 + enum mkd_autolink type, 256 + void *opaque 257 +){ 258 + if( !link || blob_size(link)<=0 ) return 0; 259 + BLOB_APPEND_LITTERAL(ob, "<a href=\""); 260 + if( type==MKDA_IMPLICIT_EMAIL ) BLOB_APPEND_LITTERAL(ob, "mailto:"); 261 + html_escape(ob, blob_buffer(link), blob_size(link)); 262 + BLOB_APPEND_LITTERAL(ob, "\">"); 263 + if( type==MKDA_EXPLICIT_EMAIL && blob_size(link)>7 ){ 264 + /* remove "mailto:" from displayed text */ 265 + html_escape(ob, blob_buffer(link)+7, blob_size(link)-7); 266 + }else{ 267 + html_escape(ob, blob_buffer(link), blob_size(link)); 268 + } 269 + BLOB_APPEND_LITTERAL(ob, "</a>"); 270 + return 1; 271 +} 272 + 273 +static int html_code_span(struct Blob *ob, struct Blob *text, void *opaque){ 274 + BLOB_APPEND_LITTERAL(ob, "<code>"); 275 + html_escape(ob, blob_buffer(text), blob_size(text)); 276 + BLOB_APPEND_LITTERAL(ob, "</code>"); 277 + return 1; 278 +} 279 + 280 +static int html_double_emphasis( 281 + struct Blob *ob, 282 + struct Blob *text, 283 + char c, 284 + void *opaque 285 +){ 286 + BLOB_APPEND_LITTERAL(ob, "<strong>"); 287 + BLOB_APPEND_BLOB(ob, text); 288 + BLOB_APPEND_LITTERAL(ob, "</strong>"); 289 + return 1; 290 +} 291 + 292 +static int html_emphasis( 293 + struct Blob *ob, 294 + struct Blob *text, 295 + char c, 296 + void *opaque 297 +){ 298 + BLOB_APPEND_LITTERAL(ob, "<em>"); 299 + BLOB_APPEND_BLOB(ob, text); 300 + BLOB_APPEND_LITTERAL(ob, "</em>"); 301 + return 1; 302 +} 303 + 304 +static int html_image( 305 + struct Blob *ob, 306 + struct Blob *link, 307 + struct Blob *title, 308 + struct Blob *alt, 309 + void *opaque 310 +){ 311 + BLOB_APPEND_LITTERAL(ob, "<img src=\""); 312 + html_escape(ob, blob_buffer(link), blob_size(link)); 313 + BLOB_APPEND_LITTERAL(ob, "\" alt=\""); 314 + html_escape(ob, blob_buffer(alt), blob_size(alt)); 315 + if( title && blob_size(title)>0 ){ 316 + BLOB_APPEND_LITTERAL(ob, "\" title=\""); 317 + html_escape(ob, blob_buffer(title), blob_size(title)); 318 + } 319 + BLOB_APPEND_LITTERAL(ob, "\" />"); 320 + return 1; 321 +} 322 + 323 +static int html_line_break(struct Blob *ob, void *opaque){ 324 + BLOB_APPEND_LITTERAL(ob, "<br />\n"); 325 + return 1; 326 +} 327 + 328 +static int html_link( 329 + struct Blob *ob, 330 + struct Blob *link, 331 + struct Blob *title, 332 + struct Blob *content, 333 + void *opaque 334 +){ 335 + BLOB_APPEND_LITTERAL(ob, "<a href=\""); 336 + html_escape(ob, blob_buffer(link), blob_size(link)); 337 + if( title && blob_size(title)>0 ){ 338 + BLOB_APPEND_LITTERAL(ob, "\" title=\""); 339 + html_escape(ob, blob_buffer(title), blob_size(title)); 340 + } 341 + BLOB_APPEND_LITTERAL(ob, "\">"); 342 + BLOB_APPEND_BLOB(ob, content); 343 + BLOB_APPEND_LITTERAL(ob, "</a>"); 344 + return 1; 345 +} 346 + 347 +static int html_triple_emphasis( 348 + struct Blob *ob, 349 + struct Blob *text, 350 + char c, 351 + void *opaque 352 +){ 353 + BLOB_APPEND_LITTERAL(ob, "<strong><em>"); 354 + BLOB_APPEND_BLOB(ob, text); 355 + BLOB_APPEND_LITTERAL(ob, "</em></strong>"); 356 + return 1; 357 +} 358 + 359 + 360 +static void html_normal_text(struct Blob *ob, struct Blob *text, void *opaque){ 361 + html_escape(ob, blob_buffer(text), blob_size(text)); 362 +} 363 + 364 + 365 +void markdown_to_html( 366 + struct Blob *input_markdown, 367 + struct Blob *output_title, 368 + struct Blob *output_body 369 +){ 370 + struct mkd_renderer html_renderer = { 371 + 0, 0, /* no prolog or epilog */ 372 + 373 + /* block level elements */ 374 + html_blockcode, 375 + html_blockquote, 376 + html_raw_block, 377 + html_header, 378 + html_hrule, 379 + html_list, 380 + html_list_item, 381 + html_paragraph, 382 + html_table, 383 + html_table_cell, 384 + html_table_row, 385 + 386 + /* span level elements */ 387 + html_autolink, 388 + html_code_span, 389 + html_double_emphasis, 390 + html_emphasis, 391 + html_image, 392 + html_line_break, 393 + html_link, 394 + html_raw_span, 395 + html_triple_emphasis, 396 + 397 + /* low level elements */ 398 + 0, /* entities are copied verbatim */ 399 + html_normal_text, 400 + 401 + /* misc. parameters */ 402 + 64, /* maximum stack */ 403 + "*_", /* emphasis characters */ 404 + output_title /* opaque data */ 405 + }; 406 + blob_reset(output_title); 407 + blob_reset(output_body); 408 + markdown(output_body, input_markdown, &html_renderer); 409 +} 410 + 411 +#endif /* def FOSSIL_ENABLE_MARKDOWN */
Changes to src/th_main.c.
263 263 ** Return true if the fossil binary has the given compile-time feature 264 264 ** enabled. The set of features includes: 265 265 ** 266 266 ** "json" = FOSSIL_ENABLE_JSON 267 267 ** "ssl" = FOSSIL_ENABLE_SSL 268 268 ** "tcl" = FOSSIL_ENABLE_TCL 269 269 ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS 270 +** "markdown" = FOSSIL_ENABLE_MARKDOWN 270 271 ** 271 272 */ 272 273 static int hasfeatureCmd( 273 274 Th_Interp *interp, 274 275 void *p, 275 276 int argc, 276 277 const char **argv, ................................................................................ 300 301 rc = 1; 301 302 } 302 303 #endif 303 304 #if defined(FOSSIL_ENABLE_TCL_STUBS) 304 305 else if( 0 == fossil_strnicmp( zArg, "tclStubs", 8 ) ){ 305 306 rc = 1; 306 307 } 308 +#endif 309 +#if defined(FOSSIL_ENABLE_MARKDOWN) 310 + else if( 0 == fossil_strnicmp( zArg, "markdown", 8 ) ){ 311 + rc = 1; 312 + } 307 313 #endif 308 314 if( g.thTrace ){ 309 315 Th_Trace("[hasfeature %#h] => %d<br />\n", argl[1], zArg, rc); 310 316 } 311 317 Th_SetResultInt(interp, rc); 312 318 return TH_OK; 313 319 }
Changes to win/Makefile.dmc.
24 24 CFLAGS = -o 25 25 BCC = $(DMDIR)\bin\dmc $(CFLAGS) 26 26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) 27 27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 28 28 29 29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 30 30 31 -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c 31 +SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c 32 32 33 -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 33 +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 34 34 35 35 36 36 RC=$(DMDIR)\bin\rcc 37 37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ 38 38 39 39 APPNAME = $(OBJDIR)\fossil$(E) 40 40 ................................................................................ 44 44 cd $(OBJDIR) 45 45 $(DMDIR)\bin\link @link 46 46 47 47 $(OBJDIR)\fossil.res: $B\win\fossil.rc 48 48 $(RC) $(RCFLAGS) -o$@ $** 49 49 50 50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res 51 - +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 moderate name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ 51 + +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ 52 52 +echo fossil >> $@ 53 53 +echo fossil >> $@ 54 54 +echo $(LIBS) >> $@ 55 55 +echo. >> $@ 56 56 +echo fossil >> $@ 57 57 58 58 translate$E: $(SRCDIR)\translate.c ................................................................................ 443 443 +translate$E $** > $@ 444 444 445 445 $(OBJDIR)\manifest$O : manifest_.c manifest.h 446 446 $(TCC) -o$@ -c manifest_.c 447 447 448 448 manifest_.c : $(SRCDIR)\manifest.c 449 449 +translate$E $** > $@ 450 + 451 +$(OBJDIR)\markdown$O : markdown_.c markdown.h 452 + $(TCC) -o$@ -c markdown_.c 453 + 454 +markdown_.c : $(SRCDIR)\markdown.c 455 + +translate$E $** > $@ 456 + 457 +$(OBJDIR)\markdown_html$O : markdown_html_.c markdown_html.h 458 + $(TCC) -o$@ -c markdown_html_.c 459 + 460 +markdown_html_.c : $(SRCDIR)\markdown_html.c 461 + +translate$E $** > $@ 450 462 451 463 $(OBJDIR)\md5$O : md5_.c md5.h 452 464 $(TCC) -o$@ -c md5_.c 453 465 454 466 md5_.c : $(SRCDIR)\md5.c 455 467 +translate$E $** > $@ 456 468 ................................................................................ 709 721 $(OBJDIR)\zip$O : zip_.c zip.h 710 722 $(TCC) -o$@ -c zip_.c 711 723 712 724 zip_.c : $(SRCDIR)\zip.c 713 725 +translate$E $** > $@ 714 726 715 727 headers: makeheaders$E page_index.h VERSION.h 716 - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h 728 + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h 717 729 @copy /Y nul: headers
Changes to win/Makefile.mingw.
41 41 #### Enable compiling with debug symbols (much larger binary) 42 42 # 43 43 # FOSSIL_ENABLE_SYMBOLS = 1 44 44 45 45 #### Enable JSON (http://www.json.org) support using "cson" 46 46 # 47 47 # FOSSIL_ENABLE_JSON = 1 48 + 49 +#### Enable markdown support 50 +# 51 +# FOSSIL_ENABLE_MARKDOWN = 1 48 52 49 53 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) 50 54 # 51 55 # FOSSIL_ENABLE_SSL = 1 52 56 53 57 #### Enable scripting support via Tcl/Tk 54 58 # ................................................................................ 182 186 endif 183 187 184 188 # With JSON support 185 189 ifdef FOSSIL_ENABLE_JSON 186 190 TCC += -DFOSSIL_ENABLE_JSON=1 187 191 RCC += -DFOSSIL_ENABLE_JSON=1 188 192 endif 193 + 194 +# With markdown support 195 +ifdef FOSSIL_ENABLE_MARKDOWN 196 +TCC += -DFOSSIL_ENABLE_MARKDOWN=1 197 +RCC += -DFOSSIL_ENABLE_MARKDOWN=1 198 +endif 189 199 190 200 #### We add the -static option here so that we can build a static 191 201 # executable that will run in a chroot jail. 192 202 # 193 203 LIB = -static 194 204 195 205 # MinGW: If available, use the Unicode capable runtime startup code. ................................................................................ 297 307 $(SRCDIR)/json_timeline.c \ 298 308 $(SRCDIR)/json_user.c \ 299 309 $(SRCDIR)/json_wiki.c \ 300 310 $(SRCDIR)/leaf.c \ 301 311 $(SRCDIR)/login.c \ 302 312 $(SRCDIR)/main.c \ 303 313 $(SRCDIR)/manifest.c \ 314 + $(SRCDIR)/markdown.c \ 315 + $(SRCDIR)/markdown_html.c \ 304 316 $(SRCDIR)/md5.c \ 305 317 $(SRCDIR)/merge.c \ 306 318 $(SRCDIR)/merge3.c \ 307 319 $(SRCDIR)/moderate.c \ 308 320 $(SRCDIR)/name.c \ 309 321 $(SRCDIR)/path.c \ 310 322 $(SRCDIR)/pivot.c \ ................................................................................ 399 411 $(OBJDIR)/json_timeline_.c \ 400 412 $(OBJDIR)/json_user_.c \ 401 413 $(OBJDIR)/json_wiki_.c \ 402 414 $(OBJDIR)/leaf_.c \ 403 415 $(OBJDIR)/login_.c \ 404 416 $(OBJDIR)/main_.c \ 405 417 $(OBJDIR)/manifest_.c \ 418 + $(OBJDIR)/markdown_.c \ 419 + $(OBJDIR)/markdown_html_.c \ 406 420 $(OBJDIR)/md5_.c \ 407 421 $(OBJDIR)/merge_.c \ 408 422 $(OBJDIR)/merge3_.c \ 409 423 $(OBJDIR)/moderate_.c \ 410 424 $(OBJDIR)/name_.c \ 411 425 $(OBJDIR)/path_.c \ 412 426 $(OBJDIR)/pivot_.c \ ................................................................................ 501 515 $(OBJDIR)/json_timeline.o \ 502 516 $(OBJDIR)/json_user.o \ 503 517 $(OBJDIR)/json_wiki.o \ 504 518 $(OBJDIR)/leaf.o \ 505 519 $(OBJDIR)/login.o \ 506 520 $(OBJDIR)/main.o \ 507 521 $(OBJDIR)/manifest.o \ 522 + $(OBJDIR)/markdown.o \ 523 + $(OBJDIR)/markdown_html.o \ 508 524 $(OBJDIR)/md5.o \ 509 525 $(OBJDIR)/merge.o \ 510 526 $(OBJDIR)/merge3.o \ 511 527 $(OBJDIR)/moderate.o \ 512 528 $(OBJDIR)/name.o \ 513 529 $(OBJDIR)/path.o \ 514 530 $(OBJDIR)/pivot.o \ ................................................................................ 660 676 setup: $(OBJDIR) $(APPNAME) 661 677 $(MAKENSIS) ./fossil.nsi 662 678 663 679 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 664 680 $(MKINDEX) $(TRANS_SRC) >$@ 665 681 666 682 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 667 - $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 683 + $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 668 684 echo Done >$(OBJDIR)/headers 669 685 670 686 $(OBJDIR)/headers: Makefile 671 687 672 688 Makefile: 673 689 674 690 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate ................................................................................ 1114 1130 $(OBJDIR)/manifest_.c: $(SRCDIR)/manifest.c $(OBJDIR)/translate 1115 1131 $(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c 1116 1132 1117 1133 $(OBJDIR)/manifest.o: $(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h 1118 1134 $(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c 1119 1135 1120 1136 $(OBJDIR)/manifest.h: $(OBJDIR)/headers 1137 + 1138 +$(OBJDIR)/markdown_.c: $(SRCDIR)/markdown.c $(OBJDIR)/translate 1139 + $(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c 1140 + 1141 +$(OBJDIR)/markdown.o: $(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h 1142 + $(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c 1143 + 1144 +$(OBJDIR)/markdown.h: $(OBJDIR)/headers 1145 + 1146 +$(OBJDIR)/markdown_html_.c: $(SRCDIR)/markdown_html.c $(OBJDIR)/translate 1147 + $(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c 1148 + 1149 +$(OBJDIR)/markdown_html.o: $(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h 1150 + $(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c 1151 + 1152 +$(OBJDIR)/markdown_html.h: $(OBJDIR)/headers 1121 1153 1122 1154 $(OBJDIR)/md5_.c: $(SRCDIR)/md5.c $(OBJDIR)/translate 1123 1155 $(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c 1124 1156 1125 1157 $(OBJDIR)/md5.o: $(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h 1126 1158 $(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c 1127 1159
Changes to win/Makefile.mingw.mistachkin.
36 36 # to compile code-generator programs as part of the build process. 37 37 # See TCC below for the C compiler for building the finished binary. 38 38 # 39 39 BCC = gcc 40 40 41 41 #### Enable compiling with debug symbols (much larger binary) 42 42 # 43 -# FOSSIL_ENABLE_SYMBOLS = 1 43 +FOSSIL_ENABLE_SYMBOLS = 1 44 44 45 45 #### Enable JSON (http://www.json.org) support using "cson" 46 46 # 47 47 FOSSIL_ENABLE_JSON = 1 48 + 49 +#### Enable markdown support 50 +# 51 +FOSSIL_ENABLE_MARKDOWN = 1 48 52 49 53 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) 50 54 # 51 55 FOSSIL_ENABLE_SSL = 1 52 56 53 57 #### Enable scripting support via Tcl/Tk 54 58 # ................................................................................ 182 186 endif 183 187 184 188 # With JSON support 185 189 ifdef FOSSIL_ENABLE_JSON 186 190 TCC += -DFOSSIL_ENABLE_JSON=1 187 191 RCC += -DFOSSIL_ENABLE_JSON=1 188 192 endif 193 + 194 +# With markdown support 195 +ifdef FOSSIL_ENABLE_MARKDOWN 196 +TCC += -DFOSSIL_ENABLE_MARKDOWN=1 197 +RCC += -DFOSSIL_ENABLE_MARKDOWN=1 198 +endif 189 199 190 200 #### We add the -static option here so that we can build a static 191 201 # executable that will run in a chroot jail. 192 202 # 193 203 LIB = -static 194 204 195 205 # MinGW: If available, use the Unicode capable runtime startup code. ................................................................................ 297 307 $(SRCDIR)/json_timeline.c \ 298 308 $(SRCDIR)/json_user.c \ 299 309 $(SRCDIR)/json_wiki.c \ 300 310 $(SRCDIR)/leaf.c \ 301 311 $(SRCDIR)/login.c \ 302 312 $(SRCDIR)/main.c \ 303 313 $(SRCDIR)/manifest.c \ 314 + $(SRCDIR)/markdown.c \ 315 + $(SRCDIR)/markdown_html.c \ 304 316 $(SRCDIR)/md5.c \ 305 317 $(SRCDIR)/merge.c \ 306 318 $(SRCDIR)/merge3.c \ 307 319 $(SRCDIR)/moderate.c \ 308 320 $(SRCDIR)/name.c \ 309 321 $(SRCDIR)/path.c \ 310 322 $(SRCDIR)/pivot.c \ ................................................................................ 399 411 $(OBJDIR)/json_timeline_.c \ 400 412 $(OBJDIR)/json_user_.c \ 401 413 $(OBJDIR)/json_wiki_.c \ 402 414 $(OBJDIR)/leaf_.c \ 403 415 $(OBJDIR)/login_.c \ 404 416 $(OBJDIR)/main_.c \ 405 417 $(OBJDIR)/manifest_.c \ 418 + $(OBJDIR)/markdown_.c \ 419 + $(OBJDIR)/markdown_html_.c \ 406 420 $(OBJDIR)/md5_.c \ 407 421 $(OBJDIR)/merge_.c \ 408 422 $(OBJDIR)/merge3_.c \ 409 423 $(OBJDIR)/moderate_.c \ 410 424 $(OBJDIR)/name_.c \ 411 425 $(OBJDIR)/path_.c \ 412 426 $(OBJDIR)/pivot_.c \ ................................................................................ 501 515 $(OBJDIR)/json_timeline.o \ 502 516 $(OBJDIR)/json_user.o \ 503 517 $(OBJDIR)/json_wiki.o \ 504 518 $(OBJDIR)/leaf.o \ 505 519 $(OBJDIR)/login.o \ 506 520 $(OBJDIR)/main.o \ 507 521 $(OBJDIR)/manifest.o \ 522 + $(OBJDIR)/markdown.o \ 523 + $(OBJDIR)/markdown_html.o \ 508 524 $(OBJDIR)/md5.o \ 509 525 $(OBJDIR)/merge.o \ 510 526 $(OBJDIR)/merge3.o \ 511 527 $(OBJDIR)/moderate.o \ 512 528 $(OBJDIR)/name.o \ 513 529 $(OBJDIR)/path.o \ 514 530 $(OBJDIR)/pivot.o \ ................................................................................ 660 676 setup: $(OBJDIR) $(APPNAME) 661 677 $(MAKENSIS) ./fossil.nsi 662 678 663 679 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex 664 680 $(MKINDEX) $(TRANS_SRC) >$@ 665 681 666 682 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h 667 - $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 683 + $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h 668 684 echo Done >$(OBJDIR)/headers 669 685 670 686 $(OBJDIR)/headers: Makefile 671 687 672 688 Makefile: 673 689 674 690 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate ................................................................................ 1114 1130 $(OBJDIR)/manifest_.c: $(SRCDIR)/manifest.c $(OBJDIR)/translate 1115 1131 $(TRANSLATE) $(SRCDIR)/manifest.c >$(OBJDIR)/manifest_.c 1116 1132 1117 1133 $(OBJDIR)/manifest.o: $(OBJDIR)/manifest_.c $(OBJDIR)/manifest.h $(SRCDIR)/config.h 1118 1134 $(XTCC) -o $(OBJDIR)/manifest.o -c $(OBJDIR)/manifest_.c 1119 1135 1120 1136 $(OBJDIR)/manifest.h: $(OBJDIR)/headers 1137 + 1138 +$(OBJDIR)/markdown_.c: $(SRCDIR)/markdown.c $(OBJDIR)/translate 1139 + $(TRANSLATE) $(SRCDIR)/markdown.c >$(OBJDIR)/markdown_.c 1140 + 1141 +$(OBJDIR)/markdown.o: $(OBJDIR)/markdown_.c $(OBJDIR)/markdown.h $(SRCDIR)/config.h 1142 + $(XTCC) -o $(OBJDIR)/markdown.o -c $(OBJDIR)/markdown_.c 1143 + 1144 +$(OBJDIR)/markdown.h: $(OBJDIR)/headers 1145 + 1146 +$(OBJDIR)/markdown_html_.c: $(SRCDIR)/markdown_html.c $(OBJDIR)/translate 1147 + $(TRANSLATE) $(SRCDIR)/markdown_html.c >$(OBJDIR)/markdown_html_.c 1148 + 1149 +$(OBJDIR)/markdown_html.o: $(OBJDIR)/markdown_html_.c $(OBJDIR)/markdown_html.h $(SRCDIR)/config.h 1150 + $(XTCC) -o $(OBJDIR)/markdown_html.o -c $(OBJDIR)/markdown_html_.c 1151 + 1152 +$(OBJDIR)/markdown_html.h: $(OBJDIR)/headers 1121 1153 1122 1154 $(OBJDIR)/md5_.c: $(SRCDIR)/md5.c $(OBJDIR)/translate 1123 1155 $(TRANSLATE) $(SRCDIR)/md5.c >$(OBJDIR)/md5_.c 1124 1156 1125 1157 $(OBJDIR)/md5.o: $(OBJDIR)/md5_.c $(OBJDIR)/md5.h $(SRCDIR)/config.h 1126 1158 $(XTCC) -o $(OBJDIR)/md5.o -c $(OBJDIR)/md5_.c 1127 1159
Changes to win/Makefile.msc.
92 92 json_timeline_.c \ 93 93 json_user_.c \ 94 94 json_wiki_.c \ 95 95 leaf_.c \ 96 96 login_.c \ 97 97 main_.c \ 98 98 manifest_.c \ 99 + markdown_.c \ 100 + markdown_html_.c \ 99 101 md5_.c \ 100 102 merge_.c \ 101 103 merge3_.c \ 102 104 moderate_.c \ 103 105 name_.c \ 104 106 path_.c \ 105 107 pivot_.c \ ................................................................................ 193 195 $(OX)\json_timeline$O \ 194 196 $(OX)\json_user$O \ 195 197 $(OX)\json_wiki$O \ 196 198 $(OX)\leaf$O \ 197 199 $(OX)\login$O \ 198 200 $(OX)\main$O \ 199 201 $(OX)\manifest$O \ 202 + $(OX)\markdown$O \ 203 + $(OX)\markdown_html$O \ 200 204 $(OX)\md5$O \ 201 205 $(OX)\merge$O \ 202 206 $(OX)\merge3$O \ 203 207 $(OX)\moderate$O \ 204 208 $(OX)\name$O \ 205 209 $(OX)\path$O \ 206 210 $(OX)\pivot$O \ ................................................................................ 311 315 echo $(OX)\json_timeline.obj >> $@ 312 316 echo $(OX)\json_user.obj >> $@ 313 317 echo $(OX)\json_wiki.obj >> $@ 314 318 echo $(OX)\leaf.obj >> $@ 315 319 echo $(OX)\login.obj >> $@ 316 320 echo $(OX)\main.obj >> $@ 317 321 echo $(OX)\manifest.obj >> $@ 322 + echo $(OX)\markdown.obj >> $@ 323 + echo $(OX)\markdown_html.obj >> $@ 318 324 echo $(OX)\md5.obj >> $@ 319 325 echo $(OX)\merge.obj >> $@ 320 326 echo $(OX)\merge3.obj >> $@ 321 327 echo $(OX)\moderate.obj >> $@ 322 328 echo $(OX)\name.obj >> $@ 323 329 echo $(OX)\path.obj >> $@ 324 330 echo $(OX)\pivot.obj >> $@ ................................................................................ 767 773 translate$E $** > $@ 768 774 769 775 $(OX)\manifest$O : manifest_.c manifest.h 770 776 $(TCC) /Fo$@ -c manifest_.c 771 777 772 778 manifest_.c : $(SRCDIR)\manifest.c 773 779 translate$E $** > $@ 780 + 781 +$(OX)\markdown$O : markdown_.c markdown.h 782 + $(TCC) /Fo$@ -c markdown_.c 783 + 784 +markdown_.c : $(SRCDIR)\markdown.c 785 + translate$E $** > $@ 786 + 787 +$(OX)\markdown_html$O : markdown_html_.c markdown_html.h 788 + $(TCC) /Fo$@ -c markdown_html_.c 789 + 790 +markdown_html_.c : $(SRCDIR)\markdown_html.c 791 + translate$E $** > $@ 774 792 775 793 $(OX)\md5$O : md5_.c md5.h 776 794 $(TCC) /Fo$@ -c md5_.c 777 795 778 796 md5_.c : $(SRCDIR)\md5.c 779 797 translate$E $** > $@ 780 798 ................................................................................ 1089 1107 json_timeline_.c:json_timeline.h \ 1090 1108 json_user_.c:json_user.h \ 1091 1109 json_wiki_.c:json_wiki.h \ 1092 1110 leaf_.c:leaf.h \ 1093 1111 login_.c:login.h \ 1094 1112 main_.c:main.h \ 1095 1113 manifest_.c:manifest.h \ 1114 + markdown_.c:markdown.h \ 1115 + markdown_html_.c:markdown_html.h \ 1096 1116 md5_.c:md5.h \ 1097 1117 merge_.c:merge.h \ 1098 1118 merge3_.c:merge3.h \ 1099 1119 moderate_.c:moderate.h \ 1100 1120 name_.c:name.h \ 1101 1121 path_.c:path.h \ 1102 1122 pivot_.c:pivot.h \