summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--LICENSE25
-rw-r--r--Makefile34
-rw-r--r--README.md30
-rw-r--r--TODO1
-rw-r--r--js/bench.js6
-rwxr-xr-xjs/bin/markdown (renamed from js/markdown)6
-rw-r--r--js/index.html23
-rw-r--r--js/lib/blocks.js696
-rw-r--r--js/lib/from-code-point.js49
-rw-r--r--js/lib/html-renderer.js164
-rw-r--r--js/lib/html5-entities.js2147
-rwxr-xr-xjs/lib/index.js20
-rw-r--r--js/lib/inlines.js714
-rwxr-xr-xjs/stmd.js1547
-rwxr-xr-xjs/test.js6
-rw-r--r--leakcheck.md1561
-rw-r--r--license.bstrlib.txt29
-rw-r--r--license.uthash.txt21
-rw-r--r--man/Makefile2
-rw-r--r--man/cmark.1.md (renamed from man/stmd.1.md)14
-rw-r--r--man/man1/cmark.1 (renamed from man/man1/stmd.1)10
-rw-r--r--narrative.md17
-rw-r--r--oldtests/Blockquotes/Indents.html12
-rw-r--r--oldtests/Blockquotes/Indents.markdown5
-rw-r--r--oldtests/Blockquotes/Nesting.html32
-rw-r--r--oldtests/Blockquotes/Nesting.markdown22
-rw-r--r--oldtests/Blockquotes/Separation.html39
-rw-r--r--oldtests/Blockquotes/Separation.markdown29
-rw-r--r--oldtests/Code/BlankLines.html33
-rw-r--r--oldtests/Code/BlankLines.markdown28
-rw-r--r--oldtests/Code/BlankLinesAtEnd.html14
-rw-r--r--oldtests/Code/BlankLinesAtEnd.markdown14
-rw-r--r--oldtests/Code/FenceMatching.html8
-rw-r--r--oldtests/Code/FenceMatching.markdown10
-rw-r--r--oldtests/Code/FencedCodeBlocks.html24
-rw-r--r--oldtests/Code/FencedCodeBlocks.markdown35
-rw-r--r--oldtests/Code/IndentedCodeBlocks.html22
-rw-r--r--oldtests/Code/IndentedCodeBlocks.markdown22
-rw-r--r--oldtests/Code/IndentedFences.html20
-rw-r--r--oldtests/Code/IndentedFences.markdown26
-rw-r--r--oldtests/Code/IndentedInLists.html22
-rw-r--r--oldtests/Code/IndentedInLists.markdown17
-rw-r--r--oldtests/Code/Inline.html13
-rw-r--r--oldtests/Code/Inline.markdown13
-rw-r--r--oldtests/Code/ListBreakAfter.html30
-rw-r--r--oldtests/Code/ListBreakAfter.markdown26
-rw-r--r--oldtests/Code/WhiteLines.html7
-rw-r--r--oldtests/Code/WhiteLines.markdown9
-rw-r--r--oldtests/Emphasis/Escapes.html1
-rw-r--r--oldtests/Emphasis/Escapes.markdown1
-rw-r--r--oldtests/Emphasis/NestedEmphAndStrong.html66
-rw-r--r--oldtests/Emphasis/NestedEmphAndStrong.markdown69
-rw-r--r--oldtests/Emphasis/Pathological.html24
-rw-r--r--oldtests/Emphasis/Pathological.markdown26
-rw-r--r--oldtests/Emphasis/Punctuation.html10
-rw-r--r--oldtests/Emphasis/Punctuation.markdown19
-rw-r--r--oldtests/HTML/Blocks.html18
-rw-r--r--oldtests/HTML/Blocks.markdown26
-rw-r--r--oldtests/HTML/Inline.html8
-rw-r--r--oldtests/HTML/Inline.markdown8
-rw-r--r--oldtests/HTML/UppercaseTags.html4
-rw-r--r--oldtests/HTML/UppercaseTags.markdown5
-rw-r--r--oldtests/Headers/ATX.html14
-rw-r--r--oldtests/Headers/ATX.markdown20
-rw-r--r--oldtests/Headers/Setext.html9
-rw-r--r--oldtests/Headers/Setext.markdown17
-rw-r--r--oldtests/Links/AngleBrackets.html3
-rw-r--r--oldtests/Links/AngleBrackets.markdown7
-rw-r--r--oldtests/Links/AutoLinks.html7
-rw-r--r--oldtests/Links/AutoLinks.markdown7
-rw-r--r--oldtests/Links/BackticksInLinks.html1
-rw-r--r--oldtests/Links/BackticksInLinks.markdown1
-rw-r--r--oldtests/Links/CaseInsensitiveReferences.html1
-rw-r--r--oldtests/Links/CaseInsensitiveReferences.markdown3
-rw-r--r--oldtests/Links/Entities.html2
-rw-r--r--oldtests/Links/Entities.markdown3
-rw-r--r--oldtests/Links/InlineLinks.html10
-rw-r--r--oldtests/Links/InlineLinks.markdown9
-rw-r--r--oldtests/Links/ParensInURLs.html6
-rw-r--r--oldtests/Links/ParensInURLs.markdown14
-rw-r--r--oldtests/Links/ReferenceLinks.html7
-rw-r--r--oldtests/Links/ReferenceLinks.markdown10
-rw-r--r--oldtests/Lists/CodeBlocksInLists.html14
-rw-r--r--oldtests/Lists/CodeBlocksInLists.markdown18
-rw-r--r--oldtests/Lists/ConsecutiveLists.html20
-rw-r--r--oldtests/Lists/ConsecutiveLists.markdown10
-rw-r--r--oldtests/Lists/EmptyListItem.html10
-rw-r--r--oldtests/Lists/EmptyListItem.markdown7
-rw-r--r--oldtests/Lists/InBlockquote.html22
-rw-r--r--oldtests/Lists/InBlockquote.markdown12
-rw-r--r--oldtests/Lists/Indents.html22
-rw-r--r--oldtests/Lists/Indents.markdown17
-rw-r--r--oldtests/Lists/ListsAndHRs.html7
-rw-r--r--oldtests/Lists/ListsAndHRs.markdown3
-rw-r--r--oldtests/Lists/ListsAndSetextHeaders.html6
-rw-r--r--oldtests/Lists/ListsAndSetextHeaders.markdown4
-rw-r--r--oldtests/Lists/MultipleBlankLines.html56
-rw-r--r--oldtests/Lists/MultipleBlankLines.markdown37
-rw-r--r--oldtests/Lists/Start.html11
-rw-r--r--oldtests/Lists/Start.markdown7
-rw-r--r--oldtests/Lists/Sublists.html49
-rw-r--r--oldtests/Lists/Sublists.markdown24
-rw-r--r--oldtests/Lists/TightAndLoose.html49
-rw-r--r--oldtests/Lists/TightAndLoose.markdown45
-rw-r--r--oldtests/Lists/TightLooseBlockquote.html32
-rw-r--r--oldtests/Lists/TightLooseBlockquote.markdown25
-rw-r--r--oldtests/Lists/TightLooseMore.html7
-rw-r--r--oldtests/Lists/TightLooseMore.markdown4
-rw-r--r--oldtests/Lists/TwoBlankLinesEndList.html21
-rw-r--r--oldtests/Lists/TwoBlankLinesEndList.markdown20
-rw-r--r--oldtests/Makefile55
-rw-r--r--oldtests/Misc/BackslashEscapes.html14
-rw-r--r--oldtests/Misc/BackslashEscapes.markdown19
-rw-r--r--oldtests/Misc/Laziness.html22
-rw-r--r--oldtests/Misc/Laziness.markdown14
-rw-r--r--oldtests/Misc/LineBreaks.html11
-rw-r--r--oldtests/Misc/LineBreaks.markdown18
-rw-r--r--oldtests/Misc/Transitions.html26
-rw-r--r--oldtests/Misc/Transitions.markdown20
-rw-r--r--oldtests/Original/Amps_and_angle_encoding.html9
-rw-r--r--oldtests/Original/Amps_and_angle_encoding.markdown21
-rw-r--r--oldtests/Original/Auto_links.html13
-rw-r--r--oldtests/Original/Auto_links.markdown13
-rw-r--r--oldtests/Original/Backslash_escapes.html75
-rw-r--r--oldtests/Original/Backslash_escapes.markdown120
-rw-r--r--oldtests/Original/Blockquotes_with_code_blocks.html12
-rw-r--r--oldtests/Original/Blockquotes_with_code_blocks.markdown11
-rw-r--r--oldtests/Original/Code_Blocks.html12
-rw-r--r--oldtests/Original/Code_Blocks.markdown14
-rw-r--r--oldtests/Original/Code_Spans.html3
-rw-r--r--oldtests/Original/Code_Spans.markdown5
-rw-r--r--oldtests/Original/Horizontal_rules.html39
-rw-r--r--oldtests/Original/Horizontal_rules.markdown67
-rw-r--r--oldtests/Original/Images.html11
-rw-r--r--oldtests/Original/Images.markdown26
-rw-r--r--oldtests/Original/Inline_HTML_Advanced.html23
-rw-r--r--oldtests/Original/Inline_HTML_Advanced.markdown30
-rw-r--r--oldtests/Original/Inline_HTML_Simple.html45
-rw-r--r--oldtests/Original/Inline_HTML_Simple.markdown69
-rw-r--r--oldtests/Original/Inline_HTML_comments.html8
-rw-r--r--oldtests/Original/Inline_HTML_comments.markdown13
-rw-r--r--oldtests/Original/Links_inline_style.html12
-rw-r--r--oldtests/Original/Links_inline_style.markdown24
-rw-r--r--oldtests/Original/Links_reference_style.html28
-rw-r--r--oldtests/Original/Links_reference_style.markdown71
-rw-r--r--oldtests/Original/Links_shortcut_references.html6
-rw-r--r--oldtests/Original/Links_shortcut_references.markdown20
-rw-r--r--oldtests/Original/Literal_quotes_in_titles.html2
-rw-r--r--oldtests/Original/Literal_quotes_in_titles.markdown7
-rw-r--r--oldtests/Original/Markdown_Documentation_Basics.html242
-rw-r--r--oldtests/Original/Markdown_Documentation_Basics.markdown306
-rw-r--r--oldtests/Original/Markdown_Documentation_Syntax.html708
-rw-r--r--oldtests/Original/Markdown_Documentation_Syntax.markdown888
-rw-r--r--oldtests/Original/Nested_blockquotes.html7
-rw-r--r--oldtests/Original/Nested_blockquotes.markdown5
-rw-r--r--oldtests/Original/Ordered_and_unordered_lists.html112
-rw-r--r--oldtests/Original/Ordered_and_unordered_lists.markdown131
-rw-r--r--oldtests/Original/README15
-rw-r--r--oldtests/Original/Strong_and_em_together.html4
-rw-r--r--oldtests/Original/Strong_and_em_together.markdown7
-rw-r--r--oldtests/Original/Tabs.html19
-rw-r--r--oldtests/Original/Tabs.markdown21
-rw-r--r--oldtests/Original/Tidyness.html8
-rw-r--r--oldtests/Original/Tidyness.markdown5
-rw-r--r--oldtests/Tabs/TabConversionUnicode.html1
-rw-r--r--oldtests/Tabs/TabConversionUnicode.markdown1
-rw-r--r--spec.txt310
-rw-r--r--src/blocks.c270
-rw-r--r--src/buffer.c15
-rw-r--r--src/chunk.h9
-rw-r--r--src/cmark.h (renamed from src/stmd.h)12
-rw-r--r--src/html/html.c4
-rw-r--r--src/inlines.c518
-rw-r--r--src/main.c23
-rw-r--r--src/print.c38
-rw-r--r--src/references.c47
-rw-r--r--src/scanners.h2
-rw-r--r--src/scanners.re2
-rw-r--r--src/utf8.c39
-rw-r--r--src/utf8.h4
-rw-r--r--template.html3
182 files changed, 6218 insertions, 7219 deletions
diff --git a/.gitignore b/.gitignore
index 9cfb3a6..a59b625 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,5 +29,5 @@
scanners.c
*.zip
bstrlib.txt
-stmd.dSYM/*
-stmd
+commonmark.dSYM/*
+commonmark
diff --git a/LICENSE b/LICENSE
index bb8c36f..e514d05 100644
--- a/LICENSE
+++ b/LICENSE
@@ -28,3 +28,28 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-----
+
+The polyfill for String.fromCodePoint included in commonmark.js is
+Copyright Mathias Bynens <http://mathiasbynens.be/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/Makefile b/Makefile
index 671d30d..a19d48b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,11 @@ CFLAGS?=-g -O3 -Wall -Wextra -std=c99 -Isrc -Wno-missing-field-initializers $(OP
LDFLAGS?=-g -O3 -Wall -Werror
SRCDIR?=src
DATADIR?=data
+BENCHINP?=narrative.md
+PROG?=./cmark
+JSMODULES=$(wildcard js/lib/*.js)
-PROG?=./stmd
-
-.PHONY: all oldtests test spec benchjs testjs
+.PHONY: all test spec benchjs testjs
all: $(SRCDIR)/case_fold_switch.inc $(PROG)
README.html: README.md template.html
@@ -28,25 +29,27 @@ spec.pdf: spec.md template.tex specfilter.hs
--number-sections -V documentclass=report -V tocdepth=2 \
-V classoption=twosides
-oldtests:
- make -C oldtests --quiet clean all
-
test: spec.txt
perl runtests.pl $< $(PROG)
+js/commonmark.js: js/lib/index.js ${JSMODULES}
+ browserify --standalone commonmark $< -o $@
+
testjs: spec.txt
node js/test.js
-# perl runtests.pl js/markdown $<
+
+jshint:
+ jshint ${JSMODULES}
benchjs:
node js/bench.js ${BENCHINP}
HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o $(SRCDIR)/html/houdini_html_u.o
-STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o $(SRCDIR)/references.c
+CMARK_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o $(SRCDIR)/references.c
-$(PROG): $(SRCDIR)/html/html_unescape.h $(SRCDIR)/case_fold_switch.inc $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c
- $(CC) $(LDFLAGS) -o $@ $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c
+$(PROG): $(SRCDIR)/html/html_unescape.h $(SRCDIR)/case_fold_switch.inc $(HTML_OBJ) $(CMARK_OBJ) $(SRCDIR)/main.c
+ $(CC) $(LDFLAGS) -o $@ $(HTML_OBJ) $(CMARK_OBJ) $(SRCDIR)/main.c
$(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re
re2c --case-insensitive -bis $< > $@ || (rm $@ && false)
@@ -57,22 +60,22 @@ $(SRCDIR)/case_fold_switch.inc: $(DATADIR)/CaseFolding-3.2.0.txt
$(SRCDIR)/html/html_unescape.h: $(SRCDIR)/html/html_unescape.gperf
gperf -I -t -N find_entity -H hash_entity -K entity -C -l --null-strings -m5 $< > $@
-.PHONY: leakcheck clean fuzztest dingus upload
+.PHONY: leakcheck clean fuzztest dingus upload jshint test testjs benchjs
-dingus:
+dingus: js/commonmark.js
cd js && echo "Starting dingus server at http://localhost:9000" && python -m SimpleHTTPServer 9000
leakcheck: $(PROG)
- cat oldtests/*/*.markdown | valgrind --leak-check=full --dsymutil=yes $(PROG)
+ cat leakcheck.md | valgrind --leak-check=full --dsymutil=yes $(PROG)
operf: $(PROG)
- operf $(PROG) <bench.md >/dev/null
+ operf $(PROG) <$(BENCHINP) >/dev/null
fuzztest:
for i in `seq 1 10`; do \
time cat /dev/urandom | head -c 100000 | iconv -f latin1 -t utf-8 | $(PROG) >/dev/null; done
-update-site: spec.html narrative.html
+update-site: spec.html narrative.html js/commonmark.js
cp spec.html _site/
cp narrative.html _site/index.html
cp -r js/* _site/js/
@@ -80,6 +83,7 @@ update-site: spec.html narrative.html
clean:
-rm -f test $(SRCDIR)/*.o $(SRCDIR)/scanners.c $(SRCDIR)/html/*.o
+ -rm js/commonmark.js
-rm -rf *.dSYM
-rm -f README.html
-rm -f spec.md fuzz.txt spec.html
diff --git a/README.md b/README.md
index 78fc837..c618ad8 100644
--- a/README.md
+++ b/README.md
@@ -2,36 +2,44 @@ CommonMark
==========
CommonMark is a [specification of Markdown syntax][the spec],
-together with BSD3-licensed implementations (`stmd`) in C and javascript.
+together with BSD3-licensed implementations in C and JavaScript.
The implementations
-------------------
The C implementation provides both a library and a standalone program
-`stmd` that converts Markdown to HTML. It is written in standard C99
+`cmark` that converts Markdown to HTML. It is written in standard C99
and has no library dependencies. (However, if you check it out from the
repository, you'll need [`re2c`](http://re2c.org) to generate
`scanners.c` from `scanners.re`. This is only a build dependency for
developers, since `scanners.c` can be provided in a released source
tarball.)
- Usage: stmd [FILE*]
+ Usage: cmark [FILE*]
Options: --help, -h Print usage information
--ast Print AST instead of HTML
--version Print version
-The javascript implementation is a single javascript file, with
-no dependencies, that can be linked to in an HTML page. A standalone
-version (using `node.js`) is also provided (`js/markdown`), and there is
-a "dingus" for playing with it interactively. (`make dingus` will start
-this.)
+The JavaScript implementation is a single JavaScript file, with
+no dependencies, that can be linked to in an HTML page. (To build,
+it, do `make js/commonmark.js`---this requires `browserify`, which you
+can get using `npm install -g browserify`.) A command-line
+version (using `node.js`) is also provided (`js/bin/markdown`), and
+there is a "dingus" for playing with it interactively. (`make dingus`
+will start this.)
[Try it now!](http://jgm.github.io/stmd/js/)
-[The spec] contains over 400 embedded examples which serve as conformance
-tests. To run the tests for `stmd`, do `make test`. To run them for
+Note that neither implementation attempts to sanitize link attributes or
+raw HTML. If you use these libraries in applications that accept
+untrusted user input, you must run the output through an HTML
+sanitizer to protect against
+[XSS attacks](http://en.wikipedia.org/wiki/Cross-site_scripting).
+
+[The spec] contains over 450 embedded examples which serve as conformance
+tests. To run the tests for `cmark`, do `make test`. To run them for
another Markdown program, say `myprog`, do `make test PROG=myprog`. To
-run the tests for `stmd.js`, do `make testjs`.
+run the tests for `commonmark.js`, do `make testjs`.
[The spec]: http://jgm.github.io/stmd/spec.html
diff --git a/TODO b/TODO
index 8b13789..e69de29 100644
--- a/TODO
+++ b/TODO
@@ -1 +0,0 @@
-
diff --git a/js/bench.js b/js/bench.js
index 3c486b1..d068a7e 100644
--- a/js/bench.js
+++ b/js/bench.js
@@ -1,19 +1,19 @@
var Benchmark = require('benchmark').Benchmark;
var suite = new Benchmark.Suite;
var fs = require('fs');
-var sm = require('./stmd');
+var sm = require('./lib/index.js');
// https://github.com/coreyti/showdown
var showdown = require('../../showdown/src/showdown');
// https://github.com/chjj/marked
var marked = require('../../marked/marked.min.js');
-var benchfile = process.argv[2] || 'oldtests/Original/Markdown_Documentation_Syntax.markdown';
+var benchfile = process.argv[2];
var contents = fs.readFileSync(benchfile, 'utf8');
// var converter = new showdown.converter();
-suite.add('stmd markdown->html', function() {
+suite.add('commonmark.js markdown->html', function() {
var doc = new sm.DocParser().parse(contents);
var renderer = new sm.HtmlRenderer();
renderer.renderBlock(doc);
diff --git a/js/markdown b/js/bin/markdown
index 2b23d54..37b0e52 100755
--- a/js/markdown
+++ b/js/bin/markdown
@@ -1,7 +1,7 @@
#!/usr/bin/env node
var fs = require('fs');
var util = require('util');
-var stmd = require('./stmd');
+var commonmark = require('../lib/index.js');
file = process.argv[2] || '/dev/stdin';
@@ -9,7 +9,7 @@ fs.readFile(file, 'utf8', function(err, data) {
if (err) {
return console.log(err);
}
- var parser = new stmd.DocParser();
- var renderer = new stmd.HtmlRenderer();
+ var parser = new commonmark.DocParser();
+ var renderer = new commonmark.HtmlRenderer();
process.stdout.write(renderer.render(parser.parse(data)));
});
diff --git a/js/index.html b/js/index.html
index 05fc216..01afef2 100644
--- a/js/index.html
+++ b/js/index.html
@@ -2,15 +2,15 @@
<html lang="en">
<head>
<meta charset="utf-8">
- <title>stmd.js demo</title>
+ <title>commonmark.js demo</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
- <script src="stmd.js"></script>
+ <script src="commonmark.js"></script>
<script type="text/javascript">
-var writer = new stmd.HtmlRenderer();
-var reader = new stmd.DocParser();
+var writer = new commonmark.HtmlRenderer();
+var reader = new commonmark.DocParser();
$(document).ready(function() {
$(".timing").hide();
@@ -28,6 +28,7 @@ $(document).ready(function() {
// $("#html").text(result);
$("#preview").html(result);
$("#html").text(result);
+ $("#ast").text(commonmark.ASTRenderer(parsed));
$("#rendertime").text(renderTime);
};
var parseAndRender = function () {
@@ -76,17 +77,18 @@ $(document).ready(function() {
<div class="container">
<div class="row">
<div class="col-md-6">
- <h1>stmd.js dingus</h1>
+ <h1>commonmark.js dingus</h1>
</div>
- <div class="col-md-3">
+ <div class="col-md-4">
<ul class="nav nav-tabs" role="tablist">
<li class="active"><a href="#preview" role="tab" data-toggle="tab">Preview</a></li>
<li><a href="#result" role="tab" data-toggle="tab">HTML</a></li>
+ <li><a href="#result-ast" role="tab" data-toggle="tab">AST</a></li>
</ul>
</div>
- <div class="col-md-3">
- <p class="timing">Parsed in <span class="timing" id="parsetime"></span> milliseconds.<br/>
- Rendered in <span class="timing" id="rendertime"></span> milliseconds.</p>
+ <div class="col-md-2">
+ <p class="timing">Parsed in <span class="timing" id="parsetime"></span> ms.<br>
+ Rendered in <span class="timing" id="rendertime"></span> ms.</p>
</div>
</div>
<div class="row">
@@ -101,6 +103,9 @@ $(document).ready(function() {
<div id="result" class="tab-pane">
<pre id="htmlpre"><code id="html"></code></pre>
</div>
+ <div id="result-ast" class="tab-pane">
+ <pre id="astpre"><code id="ast"></code></pre>
+ </div>
</div>
</div>
</div>
diff --git a/js/lib/blocks.js b/js/lib/blocks.js
new file mode 100644
index 0000000..109661f
--- /dev/null
+++ b/js/lib/blocks.js
@@ -0,0 +1,696 @@
+var C_GREATERTHAN = 62;
+var C_SPACE = 32;
+var C_OPEN_BRACKET = 91;
+
+var InlineParser = require('./inlines');
+var unescapeString = new InlineParser().unescapeString;
+
+// Returns true if string contains only space characters.
+var isBlank = function(s) {
+ return /^\s*$/.test(s);
+};
+
+// Convert tabs to spaces on each line using a 4-space tab stop.
+var detabLine = function(text) {
+ if (text.indexOf('\t') == -1) {
+ return text;
+ } else {
+ var lastStop = 0;
+ return text.replace(/\t/g, function(match, offset) {
+ var result = ' '.slice((offset - lastStop) % 4);
+ lastStop = offset + 1;
+ return result;
+ });
+ }
+};
+
+// Attempt to match a regex in string s at offset offset.
+// Return index of match or null.
+var matchAt = function(re, s, offset) {
+ var res = s.slice(offset).match(re);
+ if (res) {
+ return offset + res.index;
+ } else {
+ return null;
+ }
+};
+
+var BLOCKTAGNAME = '(?:article|header|aside|hgroup|iframe|blockquote|hr|body|li|map|button|object|canvas|ol|caption|output|col|p|colgroup|pre|dd|progress|div|section|dl|table|td|dt|tbody|embed|textarea|fieldset|tfoot|figcaption|th|figure|thead|footer|footer|tr|form|ul|h1|h2|h3|h4|h5|h6|video|script|style)';
+var HTMLBLOCKOPEN = "<(?:" + BLOCKTAGNAME + "[\\s/>]" + "|" +
+ "/" + BLOCKTAGNAME + "[\\s>]" + "|" + "[?!])";
+var reHtmlBlockOpen = new RegExp('^' + HTMLBLOCKOPEN, 'i');
+
+var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/;
+
+
+// DOC PARSER
+
+// These are methods of a DocParser object, defined below.
+
+var makeBlock = function(tag, start_line, start_column) {
+ return { t: tag,
+ open: true,
+ last_line_blank: false,
+ start_line: start_line,
+ start_column: start_column,
+ end_line: start_line,
+ children: [],
+ parent: null,
+ // string_content is formed by concatenating strings, in finalize:
+ string_content: "",
+ strings: [],
+ inline_content: []
+ };
+};
+
+// Returns true if parent block can contain child block.
+var canContain = function(parent_type, child_type) {
+ return ( parent_type == 'Document' ||
+ parent_type == 'BlockQuote' ||
+ parent_type == 'ListItem' ||
+ (parent_type == 'List' && child_type == 'ListItem') );
+};
+
+// Returns true if block type can accept lines of text.
+var acceptsLines = function(block_type) {
+ return ( block_type == 'Paragraph' ||
+ block_type == 'IndentedCode' ||
+ block_type == 'FencedCode' );
+};
+
+// Returns true if block ends with a blank line, descending if needed
+// into lists and sublists.
+var endsWithBlankLine = function(block) {
+ if (block.last_line_blank) {
+ return true;
+ }
+ if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) {
+ return endsWithBlankLine(block.children[block.children.length - 1]);
+ } else {
+ return false;
+ }
+};
+
+// Break out of all containing lists, resetting the tip of the
+// document to the parent of the highest list, and finalizing
+// all the lists. (This is used to implement the "two blank lines
+// break of of all lists" feature.)
+var breakOutOfLists = function(block, line_number) {
+ var b = block;
+ var last_list = null;
+ do {
+ if (b.t === 'List') {
+ last_list = b;
+ }
+ b = b.parent;
+ } while (b);
+
+ if (last_list) {
+ while (block != last_list) {
+ this.finalize(block, line_number);
+ block = block.parent;
+ }
+ this.finalize(last_list, line_number);
+ this.tip = last_list.parent;
+ }
+};
+
+// Add a line to the block at the tip. We assume the tip
+// can accept lines -- that check should be done before calling this.
+var addLine = function(ln, offset) {
+ var s = ln.slice(offset);
+ if (!(this.tip.open)) {
+ throw({ msg: "Attempted to add line (" + ln + ") to closed container." });
+ }
+ this.tip.strings.push(s);
+};
+
+// Add block of type tag as a child of the tip. If the tip can't
+// accept children, close and finalize it and try its parent,
+// and so on til we find a block that can accept children.
+var addChild = function(tag, line_number, offset) {
+ while (!canContain(this.tip.t, tag)) {
+ this.finalize(this.tip, line_number);
+ }
+
+ var column_number = offset + 1; // offset 0 = column 1
+ var newBlock = makeBlock(tag, line_number, column_number);
+ this.tip.children.push(newBlock);
+ newBlock.parent = this.tip;
+ this.tip = newBlock;
+ return newBlock;
+};
+
+// Parse a list marker and return data on the marker (type,
+// start, delimiter, bullet character, padding) or null.
+var parseListMarker = function(ln, offset) {
+ var rest = ln.slice(offset);
+ var match;
+ var spaces_after_marker;
+ var data = {};
+ if (rest.match(reHrule)) {
+ return null;
+ }
+ if ((match = rest.match(/^[*+-]( +|$)/))) {
+ spaces_after_marker = match[1].length;
+ data.type = 'Bullet';
+ data.bullet_char = match[0][0];
+
+ } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) {
+ spaces_after_marker = match[3].length;
+ data.type = 'Ordered';
+ data.start = parseInt(match[1]);
+ data.delimiter = match[2];
+ } else {
+ return null;
+ }
+ var blank_item = match[0].length === rest.length;
+ if (spaces_after_marker >= 5 ||
+ spaces_after_marker < 1 ||
+ blank_item) {
+ data.padding = match[0].length - spaces_after_marker + 1;
+ } else {
+ data.padding = match[0].length;
+ }
+ return data;
+};
+
+// Returns true if the two list items are of the same type,
+// with the same delimiter and bullet character. This is used
+// in agglomerating list items into lists.
+var listsMatch = function(list_data, item_data) {
+ return (list_data.type === item_data.type &&
+ list_data.delimiter === item_data.delimiter &&
+ list_data.bullet_char === item_data.bullet_char);
+};
+
+// Analyze a line of text and update the document appropriately.
+// We parse markdown text by calling this on each line of input,
+// then finalizing the document.
+var incorporateLine = function(ln, line_number) {
+
+ var all_matched = true;
+ var last_child;
+ var first_nonspace;
+ var offset = 0;
+ var match;
+ var data;
+ var blank;
+ var indent;
+ var last_matched_container;
+ var i;
+ var CODE_INDENT = 4;
+
+ var container = this.doc;
+ var oldtip = this.tip;
+
+ // Convert tabs to spaces:
+ ln = detabLine(ln);
+
+ // For each containing block, try to parse the associated line start.
+ // Bail out on failure: container will point to the last matching block.
+ // Set all_matched to false if not all containers match.
+ while (container.children.length > 0) {
+ last_child = container.children[container.children.length - 1];
+ if (!last_child.open) {
+ break;
+ }
+ container = last_child;
+
+ match = matchAt(/[^ ]/, ln, offset);
+ if (match === null) {
+ first_nonspace = ln.length;
+ blank = true;
+ } else {
+ first_nonspace = match;
+ blank = false;
+ }
+ indent = first_nonspace - offset;
+
+ switch (container.t) {
+ case 'BlockQuote':
+ if (indent <= 3 && ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
+ offset = first_nonspace + 1;
+ if (ln.charCodeAt(offset) === C_SPACE) {
+ offset++;
+ }
+ } else {
+ all_matched = false;
+ }
+ break;
+
+ case 'ListItem':
+ if (indent >= container.list_data.marker_offset +
+ container.list_data.padding) {
+ offset += container.list_data.marker_offset +
+ container.list_data.padding;
+ } else if (blank) {
+ offset = first_nonspace;
+ } else {
+ all_matched = false;
+ }
+ break;
+
+ case 'IndentedCode':
+ if (indent >= CODE_INDENT) {
+ offset += CODE_INDENT;
+ } else if (blank) {
+ offset = first_nonspace;
+ } else {
+ all_matched = false;
+ }
+ break;
+
+ case 'ATXHeader':
+ case 'SetextHeader':
+ case 'HorizontalRule':
+ // a header can never container > 1 line, so fail to match:
+ all_matched = false;
+ break;
+
+ case 'FencedCode':
+ // skip optional spaces of fence offset
+ i = container.fence_offset;
+ while (i > 0 && ln.charCodeAt(offset) === C_SPACE) {
+ offset++;
+ i--;
+ }
+ break;
+
+ case 'HtmlBlock':
+ if (blank) {
+ all_matched = false;
+ }
+ break;
+
+ case 'Paragraph':
+ if (blank) {
+ container.last_line_blank = true;
+ all_matched = false;
+ }
+ break;
+
+ default:
+ }
+
+ if (!all_matched) {
+ container = container.parent; // back up to last matching block
+ break;
+ }
+ }
+
+ last_matched_container = container;
+
+ // This function is used to finalize and close any unmatched
+ // blocks. We aren't ready to do this now, because we might
+ // have a lazy paragraph continuation, in which case we don't
+ // want to close unmatched blocks. So we store this closure for
+ // use later, when we have more information.
+ var closeUnmatchedBlocks = function(mythis) {
+ // finalize any blocks not matched
+ while (!already_done && oldtip != last_matched_container) {
+ mythis.finalize(oldtip, line_number);
+ oldtip = oldtip.parent;
+ }
+ var already_done = true;
+ };
+
+ // Check to see if we've hit 2nd blank line; if so break out of list:
+ if (blank && container.last_line_blank) {
+ this.breakOutOfLists(container, line_number);
+ }
+
+ // Unless last matched container is a code block, try new container starts,
+ // adding children to the last matched container:
+ while (container.t != 'FencedCode' &&
+ container.t != 'IndentedCode' &&
+ container.t != 'HtmlBlock' &&
+ // this is a little performance optimization:
+ matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) {
+
+ match = matchAt(/[^ ]/, ln, offset);
+ if (match === null) {
+ first_nonspace = ln.length;
+ blank = true;
+ } else {
+ first_nonspace = match;
+ blank = false;
+ }
+ indent = first_nonspace - offset;
+
+ if (indent >= CODE_INDENT) {
+ // indented code
+ if (this.tip.t != 'Paragraph' && !blank) {
+ offset += CODE_INDENT;
+ closeUnmatchedBlocks(this);
+ container = this.addChild('IndentedCode', line_number, offset);
+ } else { // indent > 4 in a lazy paragraph continuation
+ break;
+ }
+
+ } else if (ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
+ // blockquote
+ offset = first_nonspace + 1;
+ // optional following space
+ if (ln.charCodeAt(offset) === C_SPACE) {
+ offset++;
+ }
+ closeUnmatchedBlocks(this);
+ container = this.addChild('BlockQuote', line_number, offset);
+
+ } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) {
+ // ATX header
+ offset = first_nonspace + match[0].length;
+ closeUnmatchedBlocks(this);
+ container = this.addChild('ATXHeader', line_number, first_nonspace);
+ container.level = match[0].trim().length; // number of #s
+ // remove trailing ###s:
+ container.strings =
+ [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')];
+ break;
+
+ } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) {
+ // fenced code block
+ var fence_length = match[0].length;
+ closeUnmatchedBlocks(this);
+ container = this.addChild('FencedCode', line_number, first_nonspace);
+ container.fence_length = fence_length;
+ container.fence_char = match[0][0];
+ container.fence_offset = first_nonspace - offset;
+ offset = first_nonspace + fence_length;
+ break;
+
+ } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) {
+ // html block
+ closeUnmatchedBlocks(this);
+ container = this.addChild('HtmlBlock', line_number, first_nonspace);
+ // note, we don't adjust offset because the tag is part of the text
+ break;
+
+ } else if (container.t == 'Paragraph' &&
+ container.strings.length === 1 &&
+ ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) {
+ // setext header line
+ closeUnmatchedBlocks(this);
+ container.t = 'SetextHeader'; // convert Paragraph to SetextHeader
+ container.level = match[0][0] === '=' ? 1 : 2;
+ offset = ln.length;
+
+ } else if (matchAt(reHrule, ln, first_nonspace) !== null) {
+ // hrule
+ closeUnmatchedBlocks(this);
+ container = this.addChild('HorizontalRule', line_number, first_nonspace);
+ offset = ln.length - 1;
+ break;
+
+ } else if ((data = parseListMarker(ln, first_nonspace))) {
+ // list item
+ closeUnmatchedBlocks(this);
+ data.marker_offset = indent;
+ offset = first_nonspace + data.padding;
+
+ // add the list if needed
+ if (container.t !== 'List' ||
+ !(listsMatch(container.list_data, data))) {
+ container = this.addChild('List', line_number, first_nonspace);
+ container.list_data = data;
+ }
+
+ // add the list item
+ container = this.addChild('ListItem', line_number, first_nonspace);
+ container.list_data = data;
+
+ } else {
+ break;
+
+ }
+
+ if (acceptsLines(container.t)) {
+ // if it's a line container, it can't contain other containers
+ break;
+ }
+ }
+
+ // What remains at the offset is a text line. Add the text to the
+ // appropriate container.
+
+ match = matchAt(/[^ ]/, ln, offset);
+ if (match === null) {
+ first_nonspace = ln.length;
+ blank = true;
+ } else {
+ first_nonspace = match;
+ blank = false;
+ }
+ indent = first_nonspace - offset;
+
+ // First check for a lazy paragraph continuation:
+ if (this.tip !== last_matched_container &&
+ !blank &&
+ this.tip.t == 'Paragraph' &&
+ this.tip.strings.length > 0) {
+ // lazy paragraph continuation
+
+ this.last_line_blank = false;
+ this.addLine(ln, offset);
+
+ } else { // not a lazy continuation
+
+ // finalize any blocks not matched
+ closeUnmatchedBlocks(this);
+
+ // Block quote lines are never blank as they start with >
+ // and we don't count blanks in fenced code for purposes of tight/loose
+ // lists or breaking out of lists. We also don't set last_line_blank
+ // on an empty list item.
+ container.last_line_blank = blank &&
+ !(container.t == 'BlockQuote' ||
+ container.t == 'FencedCode' ||
+ (container.t == 'ListItem' &&
+ container.children.length === 0 &&
+ container.start_line == line_number));
+
+ var cont = container;
+ while (cont.parent) {
+ cont.parent.last_line_blank = false;
+ cont = cont.parent;
+ }
+
+ switch (container.t) {
+ case 'IndentedCode':
+ case 'HtmlBlock':
+ this.addLine(ln, offset);
+ break;
+
+ case 'FencedCode':
+ // check for closing code fence:
+ match = (indent <= 3 &&
+ ln.charAt(first_nonspace) == container.fence_char &&
+ ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/));
+ if (match && match[0].length >= container.fence_length) {
+ // don't add closing fence to container; instead, close it:
+ this.finalize(container, line_number);
+ } else {
+ this.addLine(ln, offset);
+ }
+ break;
+
+ case 'ATXHeader':
+ case 'SetextHeader':
+ case 'HorizontalRule':
+ // nothing to do; we already added the contents.
+ break;
+
+ default:
+ if (acceptsLines(container.t)) {
+ this.addLine(ln, first_nonspace);
+ } else if (blank) {
+ // do nothing
+ } else if (container.t != 'HorizontalRule' &&
+ container.t != 'SetextHeader') {
+ // create paragraph container for line
+ container = this.addChild('Paragraph', line_number, first_nonspace);
+ this.addLine(ln, first_nonspace);
+ } else {
+ console.log("Line " + line_number.toString() +
+ " with container type " + container.t +
+ " did not match any condition.");
+
+ }
+ }
+ }
+};
+
+// Finalize a block. Close it and do any necessary postprocessing,
+// e.g. creating string_content from strings, setting the 'tight'
+// or 'loose' status of a list, and parsing the beginnings
+// of paragraphs for reference definitions. Reset the tip to the
+// parent of the closed block.
+var finalize = function(block, line_number) {
+ var pos;
+ // don't do anything if the block is already closed
+ if (!block.open) {
+ return 0;
+ }
+ block.open = false;
+ if (line_number > block.start_line) {
+ block.end_line = line_number - 1;
+ } else {
+ block.end_line = line_number;
+ }
+
+ switch (block.t) {
+ case 'Paragraph':
+ block.string_content = block.strings.join('\n').replace(/^ */m,'');
+ // delete block.strings;
+
+ // try parsing the beginning as link reference definitions:
+ while (block.string_content.charCodeAt(0) === C_OPEN_BRACKET &&
+ (pos = this.inlineParser.parseReference(block.string_content,
+ this.refmap))) {
+ block.string_content = block.string_content.slice(pos);
+ if (isBlank(block.string_content)) {
+ block.t = 'ReferenceDef';
+ break;
+ }
+ }
+ break;
+
+ case 'ATXHeader':
+ case 'SetextHeader':
+ case 'HtmlBlock':
+ block.string_content = block.strings.join('\n');
+ break;
+
+ case 'IndentedCode':
+ block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n');
+ break;
+
+ case 'FencedCode':
+ // first line becomes info string
+ block.info = unescapeString(block.strings[0].trim());
+ if (block.strings.length == 1) {
+ block.string_content = '';
+ } else {
+ block.string_content = block.strings.slice(1).join('\n') + '\n';
+ }
+ break;
+
+ case 'List':
+ block.tight = true; // tight by default
+
+ var numitems = block.children.length;
+ var i = 0;
+ while (i < numitems) {
+ var item = block.children[i];
+ // check for non-final list item ending with blank line:
+ var last_item = i == numitems - 1;
+ if (endsWithBlankLine(item) && !last_item) {
+ block.tight = false;
+ break;
+ }
+ // recurse into children of list item, to see if there are
+ // spaces between any of them:
+ var numsubitems = item.children.length;
+ var j = 0;
+ while (j < numsubitems) {
+ var subitem = item.children[j];
+ var last_subitem = j == numsubitems - 1;
+ if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) {
+ block.tight = false;
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ this.tip = block.parent || this.top;
+};
+
+// Walk through a block & children recursively, parsing string content
+// into inline content where appropriate. Returns new object.
+var processInlines = function(block) {
+ var newblock = {};
+ newblock.t = block.t;
+ newblock.start_line = block.start_line;
+ newblock.start_column = block.start_column;
+ newblock.end_line = block.end_line;
+
+ switch(block.t) {
+ case 'Paragraph':
+ newblock.inline_content =
+ this.inlineParser.parse(block.string_content.trim(), this.refmap);
+ break;
+ case 'SetextHeader':
+ case 'ATXHeader':
+ newblock.inline_content =
+ this.inlineParser.parse(block.string_content.trim(), this.refmap);
+ newblock.level = block.level;
+ break;
+ case 'List':
+ newblock.list_data = block.list_data;
+ newblock.tight = block.tight;
+ break;
+ case 'FencedCode':
+ newblock.string_content = block.string_content;
+ newblock.info = block.info;
+ break;
+ case 'IndentedCode':
+ case 'HtmlBlock':
+ newblock.string_content = block.string_content;
+ break;
+ default:
+ break;
+ }
+
+ if (block.children) {
+ var newchildren = [];
+ for (var i = 0; i < block.children.length; i++) {
+ newchildren.push(this.processInlines(block.children[i]));
+ }
+ newblock.children = newchildren;
+ }
+ return newblock;
+};
+
+// The main parsing function. Returns a parsed document AST.
+var parse = function(input) {
+ this.doc = makeBlock('Document', 1, 1);
+ this.tip = this.doc;
+ this.refmap = {};
+ var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/);
+ var len = lines.length;
+ for (var i = 0; i < len; i++) {
+ this.incorporateLine(lines[i], i+1);
+ }
+ while (this.tip) {
+ this.finalize(this.tip, len - 1);
+ }
+ return this.processInlines(this.doc);
+};
+
+
+// The DocParser object.
+function DocParser(){
+ return {
+ doc: makeBlock('Document', 1, 1),
+ tip: this.doc,
+ refmap: {},
+ inlineParser: new InlineParser(),
+ breakOutOfLists: breakOutOfLists,
+ addLine: addLine,
+ addChild: addChild,
+ incorporateLine: incorporateLine,
+ finalize: finalize,
+ processInlines: processInlines,
+ parse: parse
+ };
+}
+
+module.exports = DocParser;
diff --git a/js/lib/from-code-point.js b/js/lib/from-code-point.js
new file mode 100644
index 0000000..94eca65
--- /dev/null
+++ b/js/lib/from-code-point.js
@@ -0,0 +1,49 @@
+// derived from https://github.com/mathiasbynens/String.fromCodePoint
+/*! http://mths.be/fromcodepoint v0.2.1 by @mathias */
+if (String.fromCodePoint) {
+
+ module.exports = String.fromCodePoint;
+
+} else {
+
+ var stringFromCharCode = String.fromCharCode;
+ var floor = Math.floor;
+ var fromCodePoint = function(_) {
+ var MAX_SIZE = 0x4000;
+ var codeUnits = [];
+ var highSurrogate;
+ var lowSurrogate;
+ var index = -1;
+ var length = arguments.length;
+ if (!length) {
+ return '';
+ }
+ var result = '';
+ while (++index < length) {
+ var codePoint = Number(arguments[index]);
+ if (
+ !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
+ codePoint < 0 || // not a valid Unicode code point
+ codePoint > 0x10FFFF || // not a valid Unicode code point
+ floor(codePoint) != codePoint // not an integer
+ ) {
+ return String.fromCharCode(0xFFFD);
+ }
+ if (codePoint <= 0xFFFF) { // BMP code point
+ codeUnits.push(codePoint);
+ } else { // Astral code point; split in surrogate halves
+ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+ codePoint -= 0x10000;
+ highSurrogate = (codePoint >> 10) + 0xD800;
+ lowSurrogate = (codePoint % 0x400) + 0xDC00;
+ codeUnits.push(highSurrogate, lowSurrogate);
+ }
+ if (index + 1 == length || codeUnits.length > MAX_SIZE) {
+ result += stringFromCharCode.apply(null, codeUnits);
+ codeUnits.length = 0;
+ }
+ }
+ return result;
+ };
+ module.exports = fromCodePoint;
+}
diff --git a/js/lib/html-renderer.js b/js/lib/html-renderer.js
new file mode 100644
index 0000000..e1a6063
--- /dev/null
+++ b/js/lib/html-renderer.js
@@ -0,0 +1,164 @@
+// Helper function to produce content in a pair of HTML tags.
+var inTags = function(tag, attribs, contents, selfclosing) {
+ var result = '<' + tag;
+ if (attribs) {
+ var i = 0;
+ var attrib;
+ while ((attrib = attribs[i]) !== undefined) {
+ result = result.concat(' ', attrib[0], '="', attrib[1], '"');
+ i++;
+ }
+ }
+ if (contents) {
+ result = result.concat('>', contents, '</', tag, '>');
+ } else if (selfclosing) {
+ result = result + ' />';
+ } else {
+ result = result.concat('></', tag, '>');
+ }
+ return result;
+};
+
+// Render an inline element as HTML.
+var renderInline = function(inline) {
+ var attrs;
+ switch (inline.t) {
+ case 'Str':
+ return this.escape(inline.c);
+ case 'Softbreak':
+ return this.softbreak;
+ case 'Hardbreak':
+ return inTags('br',[],"",true) + '\n';
+ case 'Emph':
+ return inTags('em', [], this.renderInlines(inline.c));
+ case 'Strong':
+ return inTags('strong', [], this.renderInlines(inline.c));
+ case 'Html':
+ return inline.c;
+ case 'Link':
+ attrs = [['href', this.escape(inline.destination, true)]];
+ if (inline.title) {
+ attrs.push(['title', this.escape(inline.title, true)]);
+ }
+ return inTags('a', attrs, this.renderInlines(inline.label));
+ case 'Image':
+ attrs = [['src', this.escape(inline.destination, true)],
+ ['alt', this.escape(this.renderInlines(inline.label))]];
+ if (inline.title) {
+ attrs.push(['title', this.escape(inline.title, true)]);
+ }
+ return inTags('img', attrs, "", true);
+ case 'Code':
+ return inTags('code', [], this.escape(inline.c));
+ default:
+ console.log("Unknown inline type " + inline.t);
+ return "";
+ }
+};
+
+// Render a list of inlines.
+var renderInlines = function(inlines) {
+ var result = '';
+ for (var i=0; i < inlines.length; i++) {
+ result = result + this.renderInline(inlines[i]);
+ }
+ return result;
+};
+
+// Render a single block element.
+var renderBlock = function(block, in_tight_list) {
+ var tag;
+ var attr;
+ var info_words;
+ switch (block.t) {
+ case 'Document':
+ var whole_doc = this.renderBlocks(block.children);
+ return (whole_doc === '' ? '' : whole_doc + '\n');
+ case 'Paragraph':
+ if (in_tight_list) {
+ return this.renderInlines(block.inline_content);
+ } else {
+ return inTags('p', [], this.renderInlines(block.inline_content));
+ }
+ break;
+ case 'BlockQuote':
+ var filling = this.renderBlocks(block.children);
+ return inTags('blockquote', [], filling === '' ? this.innersep :
+ this.innersep + filling + this.innersep);
+ case 'ListItem':
+ return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim());
+ case 'List':
+ tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol';
+ attr = (!block.list_data.start || block.list_data.start == 1) ?
+ [] : [['start', block.list_data.start.toString()]];
+ return inTags(tag, attr, this.innersep +
+ this.renderBlocks(block.children, block.tight) +
+ this.innersep);
+ case 'ATXHeader':
+ case 'SetextHeader':
+ tag = 'h' + block.level;
+ return inTags(tag, [], this.renderInlines(block.inline_content));
+ case 'IndentedCode':
+ return inTags('pre', [],
+ inTags('code', [], this.escape(block.string_content)));
+ case 'FencedCode':
+ info_words = block.info.split(/ +/);
+ attr = info_words.length === 0 || info_words[0].length === 0 ?
+ [] : [['class','language-' +
+ this.escape(info_words[0],true)]];
+ return inTags('pre', [],
+ inTags('code', attr, this.escape(block.string_content)));
+ case 'HtmlBlock':
+ return block.string_content;
+ case 'ReferenceDef':
+ return "";
+ case 'HorizontalRule':
+ return inTags('hr',[],"",true);
+ default:
+ console.log("Unknown block type " + block.t);
+ return "";
+ }
+};
+
+// Render a list of block elements, separated by this.blocksep.
+var renderBlocks = function(blocks, in_tight_list) {
+ var result = [];
+ for (var i=0; i < blocks.length; i++) {
+ if (blocks[i].t !== 'ReferenceDef') {
+ result.push(this.renderBlock(blocks[i], in_tight_list));
+ }
+ }
+ return result.join(this.blocksep);
+};
+
+// The HtmlRenderer object.
+function HtmlRenderer(){
+ return {
+ // default options:
+ blocksep: '\n', // space between blocks
+ innersep: '\n', // space between block container tag and contents
+ softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML
+ // set to "<br />" to make them hard breaks
+ // set to " " if you want to ignore line wrapping in source
+ escape: function(s, preserve_entities) {
+ if (preserve_entities) {
+ return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&amp;')
+ .replace(/[<]/g,'&lt;')
+ .replace(/[>]/g,'&gt;')
+ .replace(/["]/g,'&quot;');
+ } else {
+ return s.replace(/[&]/g,'&amp;')
+ .replace(/[<]/g,'&lt;')
+ .replace(/[>]/g,'&gt;')
+ .replace(/["]/g,'&quot;');
+ }
+ },
+ renderInline: renderInline,
+ renderInlines: renderInlines,
+ renderBlock: renderBlock,
+ renderBlocks: renderBlocks,
+ render: renderBlock
+ };
+}
+
+module.exports = HtmlRenderer;
diff --git a/js/lib/html5-entities.js b/js/lib/html5-entities.js
new file mode 100644
index 0000000..235fc66
--- /dev/null
+++ b/js/lib/html5-entities.js
@@ -0,0 +1,2147 @@
+var fromCodePoint = require('./from-code-point');
+
+var entities = { AAacute: 'Á',
+ aacute: 'á',
+ Abreve: 'Ă',
+ abreve: 'ă',
+ ac: '∾',
+ acd: '∿',
+ acE: '∾',
+ Acirc: 'Â',
+ acirc: 'â',
+ acute: '´',
+ Acy: 'А',
+ acy: 'а',
+ AElig: 'Æ',
+ aelig: 'æ',
+ af: '⁡',
+ Afr: '𝔄',
+ afr: '𝔞',
+ Agrave: 'À',
+ agrave: 'à',
+ alefsym: 'ℵ',
+ aleph: 'ℵ',
+ Alpha: 'Α',
+ alpha: 'α',
+ Amacr: 'Ā',
+ amacr: 'ā',
+ amalg: '⨿',
+ amp: '&',
+ AMP: '&',
+ andand: '⩕',
+ And: '⩓',
+ and: '∧',
+ andd: '⩜',
+ andslope: '⩘',
+ andv: '⩚',
+ ang: '∠',
+ ange: '⦤',
+ angle: '∠',
+ angmsdaa: '⦨',
+ angmsdab: '⦩',
+ angmsdac: '⦪',
+ angmsdad: '⦫',
+ angmsdae: '⦬',
+ angmsdaf: '⦭',
+ angmsdag: '⦮',
+ angmsdah: '⦯',
+ angmsd: '∡',
+ angrt: '∟',
+ angrtvb: '⊾',
+ angrtvbd: '⦝',
+ angsph: '∢',
+ angst: 'Å',
+ angzarr: '⍼',
+ Aogon: 'Ą',
+ aogon: 'ą',
+ Aopf: '𝔸',
+ aopf: '𝕒',
+ apacir: '⩯',
+ ap: '≈',
+ apE: '⩰',
+ ape: '≊',
+ apid: '≋',
+ apos: '\'',
+ ApplyFunction: '⁡',
+ approx: '≈',
+ approxeq: '≊',
+ Aring: 'Å',
+ aring: 'å',
+ Ascr: '𝒜',
+ ascr: '𝒶',
+ Assign: '≔',
+ ast: '*',
+ asymp: '≈',
+ asympeq: '≍',
+ Atilde: 'Ã',
+ atilde: 'ã',
+ Auml: 'Ä',
+ auml: 'ä',
+ awconint: '∳',
+ awint: '⨑',
+ backcong: '≌',
+ backepsilon: '϶',
+ backprime: '‵',
+ backsim: '∽',
+ backsimeq: '⋍',
+ Backslash: '∖',
+ Barv: '⫧',
+ barvee: '⊽',
+ barwed: '⌅',
+ Barwed: '⌆',
+ barwedge: '⌅',
+ bbrk: '⎵',
+ bbrktbrk: '⎶',
+ bcong: '≌',
+ Bcy: 'Б',
+ bcy: 'б',
+ bdquo: '„',
+ becaus: '∵',
+ because: '∵',
+ Because: '∵',
+ bemptyv: '⦰',
+ bepsi: '϶',
+ bernou: 'ℬ',
+ Bernoullis: 'ℬ',
+ Beta: 'Β',
+ beta: 'β',
+ beth: 'ℶ',
+ between: '≬',
+ Bfr: '𝔅',
+ bfr: '𝔟',
+ bigcap: '⋂',
+ bigcirc: '◯',
+ bigcup: '⋃',
+ bigodot: '⨀',
+ bigoplus: '⨁',
+ bigotimes: '⨂',
+ bigsqcup: '⨆',
+ bigstar: '★',
+ bigtriangledown: '▽',
+ bigtriangleup: '△',
+ biguplus: '⨄',
+ bigvee: '⋁',
+ bigwedge: '⋀',
+ bkarow: '⤍',
+ blacklozenge: '⧫',
+ blacksquare: '▪',
+ blacktriangle: '▴',
+ blacktriangledown: '▾',
+ blacktriangleleft: '◂',
+ blacktriangleright: '▸',
+ blank: '␣',
+ blk12: '▒',
+ blk14: '░',
+ blk34: '▓',
+ block: '█',
+ bne: '=',
+ bnequiv: '≡',
+ bNot: '⫭',
+ bnot: '⌐',
+ Bopf: '𝔹',
+ bopf: '𝕓',
+ bot: '⊥',
+ bottom: '⊥',
+ bowtie: '⋈',
+ boxbox: '⧉',
+ boxdl: '┐',
+ boxdL: '╕',
+ boxDl: '╖',
+ boxDL: '╗',
+ boxdr: '┌',
+ boxdR: '╒',
+ boxDr: '╓',
+ boxDR: '╔',
+ boxh: '─',
+ boxH: '═',
+ boxhd: '┬',
+ boxHd: '╤',
+ boxhD: '╥',
+ boxHD: '╦',
+ boxhu: '┴',
+ boxHu: '╧',
+ boxhU: '╨',
+ boxHU: '╩',
+ boxminus: '⊟',
+ boxplus: '⊞',
+ boxtimes: '⊠',
+ boxul: '┘',
+ boxuL: '╛',
+ boxUl: '╜',
+ boxUL: '╝',
+ boxur: '└',
+ boxuR: '╘',
+ boxUr: '╙',
+ boxUR: '╚',
+ boxv: '│',
+ boxV: '║',
+ boxvh: '┼',
+ boxvH: '╪',
+ boxVh: '╫',
+ boxVH: '╬',
+ boxvl: '┤',
+ boxvL: '╡',
+ boxVl: '╢',
+ boxVL: '╣',
+ boxvr: '├',
+ boxvR: '╞',
+ boxVr: '╟',
+ boxVR: '╠',
+ bprime: '‵',
+ breve: '˘',
+ Breve: '˘',
+ brvbar: '¦',
+ bscr: '𝒷',
+ Bscr: 'ℬ',
+ bsemi: '⁏',
+ bsim: '∽',
+ bsime: '⋍',
+ bsolb: '⧅',
+ bsol: '\\',
+ bsolhsub: '⟈',
+ bull: '•',
+ bullet: '•',
+ bump: '≎',
+ bumpE: '⪮',
+ bumpe: '≏',
+ Bumpeq: '≎',
+ bumpeq: '≏',
+ Cacute: 'Ć',
+ cacute: 'ć',
+ capand: '⩄',
+ capbrcup: '⩉',
+ capcap: '⩋',
+ cap: '∩',
+ Cap: '⋒',
+ capcup: '⩇',
+ capdot: '⩀',
+ CapitalDifferentialD: 'ⅅ',
+ caps: '∩',
+ caret: '⁁',
+ caron: 'ˇ',
+ Cayleys: 'ℭ',
+ ccaps: '⩍',
+ Ccaron: 'Č',
+ ccaron: 'č',
+ Ccedil: 'Ç',
+ ccedil: 'ç',
+ Ccirc: 'Ĉ',
+ ccirc: 'ĉ',
+ Cconint: '∰',
+ ccups: '⩌',
+ ccupssm: '⩐',
+ Cdot: 'Ċ',
+ cdot: 'ċ',
+ cedil: '¸',
+ Cedilla: '¸',
+ cemptyv: '⦲',
+ cent: '¢',
+ centerdot: '·',
+ CenterDot: '·',
+ cfr: '𝔠',
+ Cfr: 'ℭ',
+ CHcy: 'Ч',
+ chcy: 'ч',
+ check: '✓',
+ checkmark: '✓',
+ Chi: 'Χ',
+ chi: 'χ',
+ circ: 'ˆ',
+ circeq: '≗',
+ circlearrowleft: '↺',
+ circlearrowright: '↻',
+ circledast: '⊛',
+ circledcirc: '⊚',
+ circleddash: '⊝',
+ CircleDot: '⊙',
+ circledR: '®',
+ circledS: 'Ⓢ',
+ CircleMinus: '⊖',
+ CirclePlus: '⊕',
+ CircleTimes: '⊗',
+ cir: '○',
+ cirE: '⧃',
+ cire: '≗',
+ cirfnint: '⨐',
+ cirmid: '⫯',
+ cirscir: '⧂',
+ ClockwiseContourIntegral: '∲',
+ CloseCurlyDoubleQuote: '”',
+ CloseCurlyQuote: '’',
+ clubs: '♣',
+ clubsuit: '♣',
+ colon: ':',
+ Colon: '∷',
+ Colone: '⩴',
+ colone: '≔',
+ coloneq: '≔',
+ comma: ',',
+ commat: '@',
+ comp: '∁',
+ compfn: '∘',
+ complement: '∁',
+ complexes: 'ℂ',
+ cong: '≅',
+ congdot: '⩭',
+ Congruent: '≡',
+ conint: '∮',
+ Conint: '∯',
+ ContourIntegral: '∮',
+ copf: '𝕔',
+ Copf: 'ℂ',
+ coprod: '∐',
+ Coproduct: '∐',
+ copy: '©',
+ COPY: '©',
+ copysr: '℗',
+ CounterClockwiseContourIntegral: '∳',
+ crarr: '↵',
+ cross: '✗',
+ Cross: '⨯',
+ Cscr: '𝒞',
+ cscr: '𝒸',
+ csub: '⫏',
+ csube: '⫑',
+ csup: '⫐',
+ csupe: '⫒',
+ ctdot: '⋯',
+ cudarrl: '⤸',
+ cudarrr: '⤵',
+ cuepr: '⋞',
+ cuesc: '⋟',
+ cularr: '↶',
+ cularrp: '⤽',
+ cupbrcap: '⩈',
+ cupcap: '⩆',
+ CupCap: '≍',
+ cup: '∪',
+ Cup: '⋓',
+ cupcup: '⩊',
+ cupdot: '⊍',
+ cupor: '⩅',
+ cups: '∪',
+ curarr: '↷',
+ curarrm: '⤼',
+ curlyeqprec: '⋞',
+ curlyeqsucc: '⋟',
+ curlyvee: '⋎',
+ curlywedge: '⋏',
+ curren: '¤',
+ curvearrowleft: '↶',
+ curvearrowright: '↷',
+ cuvee: '⋎',
+ cuwed: '⋏',
+ cwconint: '∲',
+ cwint: '∱',
+ cylcty: '⌭',
+ dagger: '†',
+ Dagger: '‡',
+ daleth: 'ℸ',
+ darr: '↓',
+ Darr: '↡',
+ dArr: '⇓',
+ dash: '‐',
+ Dashv: '⫤',
+ dashv: '⊣',
+ dbkarow: '⤏',
+ dblac: '˝',
+ Dcaron: 'Ď',
+ dcaron: 'ď',
+ Dcy: 'Д',
+ dcy: 'д',
+ ddagger: '‡',
+ ddarr: '⇊',
+ DD: 'ⅅ',
+ dd: 'ⅆ',
+ DDotrahd: '⤑',
+ ddotseq: '⩷',
+ deg: '°',
+ Del: '∇',
+ Delta: 'Δ',
+ delta: 'δ',
+ demptyv: '⦱',
+ dfisht: '⥿',
+ Dfr: '𝔇',
+ dfr: '𝔡',
+ dHar: '⥥',
+ dharl: '⇃',
+ dharr: '⇂',
+ DiacriticalAcute: '´',
+ DiacriticalDot: '˙',
+ DiacriticalDoubleAcute: '˝',
+ DiacriticalGrave: '`',
+ DiacriticalTilde: '˜',
+ diam: '⋄',
+ diamond: '⋄',
+ Diamond: '⋄',
+ diamondsuit: '♦',
+ diams: '♦',
+ die: '¨',
+ DifferentialD: 'ⅆ',
+ digamma: 'ϝ',
+ disin: '⋲',
+ div: '÷',
+ divide: '÷',
+ divideontimes: '⋇',
+ divonx: '⋇',
+ DJcy: 'Ђ',
+ djcy: 'ђ',
+ dlcorn: '⌞',
+ dlcrop: '⌍',
+ dollar: '$',
+ Dopf: '𝔻',
+ dopf: '𝕕',
+ Dot: '¨',
+ dot: '˙',
+ DotDot: '⃜',
+ doteq: '≐',
+ doteqdot: '≑',
+ DotEqual: '≐',
+ dotminus: '∸',
+ dotplus: '∔',
+ dotsquare: '⊡',
+ doublebarwedge: '⌆',
+ DoubleContourIntegral: '∯',
+ DoubleDot: '¨',
+ DoubleDownArrow: '⇓',
+ DoubleLeftArrow: '⇐',
+ DoubleLeftRightArrow: '⇔',
+ DoubleLeftTee: '⫤',
+ DoubleLongLeftArrow: '⟸',
+ DoubleLongLeftRightArrow: '⟺',
+ DoubleLongRightArrow: '⟹',
+ DoubleRightArrow: '⇒',
+ DoubleRightTee: '⊨',
+ DoubleUpArrow: '⇑',
+ DoubleUpDownArrow: '⇕',
+ DoubleVerticalBar: '∥',
+ DownArrowBar: '⤓',
+ downarrow: '↓',
+ DownArrow: '↓',
+ Downarrow: '⇓',
+ DownArrowUpArrow: '⇵',
+ DownBreve: '̑',
+ downdownarrows: '⇊',
+ downharpoonleft: '⇃',
+ downharpoonright: '⇂',
+ DownLeftRightVector: '⥐',
+ DownLeftTeeVector: '⥞',
+ DownLeftVectorBar: '⥖',
+ DownLeftVector: '↽',
+ DownRightTeeVector: '⥟',
+ DownRightVectorBar: '⥗',
+ DownRightVector: '⇁',
+ DownTeeArrow: '↧',
+ DownTee: '⊤',
+ drbkarow: '⤐',
+ drcorn: '⌟',
+ drcrop: '⌌',
+ Dscr: '𝒟',
+ dscr: '𝒹',
+ DScy: 'Ѕ',
+ dscy: 'ѕ',
+ dsol: '⧶',
+ Dstrok: 'Đ',
+ dstrok: 'đ',
+ dtdot: '⋱',
+ dtri: '▿',
+ dtrif: '▾',
+ duarr: '⇵',
+ duhar: '⥯',
+ dwangle: '⦦',
+ DZcy: 'Џ',
+ dzcy: 'џ',
+ dzigrarr: '⟿',
+ Eacute: 'É',
+ eacute: 'é',
+ easter: '⩮',
+ Ecaron: 'Ě',
+ ecaron: 'ě',
+ Ecirc: 'Ê',
+ ecirc: 'ê',
+ ecir: '≖',
+ ecolon: '≕',
+ Ecy: 'Э',
+ ecy: 'э',
+ eDDot: '⩷',
+ Edot: 'Ė',
+ edot: 'ė',
+ eDot: '≑',
+ ee: 'ⅇ',
+ efDot: '≒',
+ Efr: '𝔈',
+ efr: '𝔢',
+ eg: '⪚',
+ Egrave: 'È',
+ egrave: 'è',
+ egs: '⪖',
+ egsdot: '⪘',
+ el: '⪙',
+ Element: '∈',
+ elinters: '⏧',
+ ell: 'ℓ',
+ els: '⪕',
+ elsdot: '⪗',
+ Emacr: 'Ē',
+ emacr: 'ē',
+ empty: '∅',
+ emptyset: '∅',
+ EmptySmallSquare: '◻',
+ emptyv: '∅',
+ EmptyVerySmallSquare: '▫',
+ emsp13: ' ',
+ emsp14: ' ',
+ emsp: ' ',
+ ENG: 'Ŋ',
+ eng: 'ŋ',
+ ensp: ' ',
+ Eogon: 'Ę',
+ eogon: 'ę',
+ Eopf: '𝔼',
+ eopf: '𝕖',
+ epar: '⋕',
+ eparsl: '⧣',
+ eplus: '⩱',
+ epsi: 'ε',
+ Epsilon: 'Ε',
+ epsilon: 'ε',
+ epsiv: 'ϵ',
+ eqcirc: '≖',
+ eqcolon: '≕',
+ eqsim: '≂',
+ eqslantgtr: '⪖',
+ eqslantless: '⪕',
+ Equal: '⩵',
+ equals: '=',
+ EqualTilde: '≂',
+ equest: '≟',
+ Equilibrium: '⇌',
+ equiv: '≡',
+ equivDD: '⩸',
+ eqvparsl: '⧥',
+ erarr: '⥱',
+ erDot: '≓',
+ escr: 'ℯ',
+ Escr: 'ℰ',
+ esdot: '≐',
+ Esim: '⩳',
+ esim: '≂',
+ Eta: 'Η',
+ eta: 'η',
+ ETH: 'Ð',
+ eth: 'ð',
+ Euml: 'Ë',
+ euml: 'ë',
+ euro: '€',
+ excl: '!',
+ exist: '∃',
+ Exists: '∃',
+ expectation: 'ℰ',
+ exponentiale: 'ⅇ',
+ ExponentialE: 'ⅇ',
+ fallingdotseq: '≒',
+ Fcy: 'Ф',
+ fcy: 'ф',
+ female: '♀',
+ ffilig: 'ffi',
+ fflig: 'ff',
+ ffllig: 'ffl',
+ Ffr: '𝔉',
+ ffr: '𝔣',
+ filig: 'fi',
+ FilledSmallSquare: '◼',
+ FilledVerySmallSquare: '▪',
+ fjlig: 'f',
+ flat: '♭',
+ fllig: 'fl',
+ fltns: '▱',
+ fnof: 'ƒ',
+ Fopf: '𝔽',
+ fopf: '𝕗',
+ forall: '∀',
+ ForAll: '∀',
+ fork: '⋔',
+ forkv: '⫙',
+ Fouriertrf: 'ℱ',
+ fpartint: '⨍',
+ frac12: '½',
+ frac13: '⅓',
+ frac14: '¼',
+ frac15: '⅕',
+ frac16: '⅙',
+ frac18: '⅛',
+ frac23: '⅔',
+ frac25: '⅖',
+ frac34: '¾',
+ frac35: '⅗',
+ frac38: '⅜',
+ frac45: '⅘',
+ frac56: '⅚',
+ frac58: '⅝',
+ frac78: '⅞',
+ frasl: '⁄',
+ frown: '⌢',
+ fscr: '𝒻',
+ Fscr: 'ℱ',
+ gacute: 'ǵ',
+ Gamma: 'Γ',
+ gamma: 'γ',
+ Gammad: 'Ϝ',
+ gammad: 'ϝ',
+ gap: '⪆',
+ Gbreve: 'Ğ',
+ gbreve: 'ğ',
+ Gcedil: 'Ģ',
+ Gcirc: 'Ĝ',
+ gcirc: 'ĝ',
+ Gcy: 'Г',
+ gcy: 'г',
+ Gdot: 'Ġ',
+ gdot: 'ġ',
+ ge: '≥',
+ gE: '≧',
+ gEl: '⪌',
+ gel: '⋛',
+ geq: '≥',
+ geqq: '≧',
+ geqslant: '⩾',
+ gescc: '⪩',
+ ges: '⩾',
+ gesdot: '⪀',
+ gesdoto: '⪂',
+ gesdotol: '⪄',
+ gesl: '⋛',
+ gesles: '⪔',
+ Gfr: '𝔊',
+ gfr: '𝔤',
+ gg: '≫',
+ Gg: '⋙',
+ ggg: '⋙',
+ gimel: 'ℷ',
+ GJcy: 'Ѓ',
+ gjcy: 'ѓ',
+ gla: '⪥',
+ gl: '≷',
+ glE: '⪒',
+ glj: '⪤',
+ gnap: '⪊',
+ gnapprox: '⪊',
+ gne: '⪈',
+ gnE: '≩',
+ gneq: '⪈',
+ gneqq: '≩',
+ gnsim: '⋧',
+ Gopf: '𝔾',
+ gopf: '𝕘',
+ grave: '`',
+ GreaterEqual: '≥',
+ GreaterEqualLess: '⋛',
+ GreaterFullEqual: '≧',
+ GreaterGreater: '⪢',
+ GreaterLess: '≷',
+ GreaterSlantEqual: '⩾',
+ GreaterTilde: '≳',
+ Gscr: '𝒢',
+ gscr: 'ℊ',
+ gsim: '≳',
+ gsime: '⪎',
+ gsiml: '⪐',
+ gtcc: '⪧',
+ gtcir: '⩺',
+ gt: '>',
+ GT: '>',
+ Gt: '≫',
+ gtdot: '⋗',
+ gtlPar: '⦕',
+ gtquest: '⩼',
+ gtrapprox: '⪆',
+ gtrarr: '⥸',
+ gtrdot: '⋗',
+ gtreqless: '⋛',
+ gtreqqless: '⪌',
+ gtrless: '≷',
+ gtrsim: '≳',
+ gvertneqq: '≩',
+ gvnE: '≩',
+ Hacek: 'ˇ',
+ hairsp: ' ',
+ half: '½',
+ hamilt: 'ℋ',
+ HARDcy: 'Ъ',
+ hardcy: 'ъ',
+ harrcir: '⥈',
+ harr: '↔',
+ hArr: '⇔',
+ harrw: '↭',
+ Hat: '^',
+ hbar: 'ℏ',
+ Hcirc: 'Ĥ',
+ hcirc: 'ĥ',
+ hearts: '♥',
+ heartsuit: '♥',
+ hellip: '…',
+ hercon: '⊹',
+ hfr: '𝔥',
+ Hfr: 'ℌ',
+ HilbertSpace: 'ℋ',
+ hksearow: '⤥',
+ hkswarow: '⤦',
+ hoarr: '⇿',
+ homtht: '∻',
+ hookleftarrow: '↩',
+ hookrightarrow: '↪',
+ hopf: '𝕙',
+ Hopf: 'ℍ',
+ horbar: '―',
+ HorizontalLine: '─',
+ hscr: '𝒽',
+ Hscr: 'ℋ',
+ hslash: 'ℏ',
+ Hstrok: 'Ħ',
+ hstrok: 'ħ',
+ HumpDownHump: '≎',
+ HumpEqual: '≏',
+ hybull: '⁃',
+ hyphen: '‐',
+ Iacute: 'Í',
+ iacute: 'í',
+ ic: '⁣',
+ Icirc: 'Î',
+ icirc: 'î',
+ Icy: 'И',
+ icy: 'и',
+ Idot: 'İ',
+ IEcy: 'Е',
+ iecy: 'е',
+ iexcl: '¡',
+ iff: '⇔',
+ ifr: '𝔦',
+ Ifr: 'ℑ',
+ Igrave: 'Ì',
+ igrave: 'ì',
+ ii: 'ⅈ',
+ iiiint: '⨌',
+ iiint: '∭',
+ iinfin: '⧜',
+ iiota: '℩',
+ IJlig: 'IJ',
+ ijlig: 'ij',
+ Imacr: 'Ī',
+ imacr: 'ī',
+ image: 'ℑ',
+ ImaginaryI: 'ⅈ',
+ imagline: 'ℐ',
+ imagpart: 'ℑ',
+ imath: 'ı',
+ Im: 'ℑ',
+ imof: '⊷',
+ imped: 'Ƶ',
+ Implies: '⇒',
+ incare: '℅',
+ in: '∈',
+ infin: '∞',
+ infintie: '⧝',
+ inodot: 'ı',
+ intcal: '⊺',
+ int: '∫',
+ Int: '∬',
+ integers: 'ℤ',
+ Integral: '∫',
+ intercal: '⊺',
+ Intersection: '⋂',
+ intlarhk: '⨗',
+ intprod: '⨼',
+ InvisibleComma: '⁣',
+ InvisibleTimes: '⁢',
+ IOcy: 'Ё',
+ iocy: 'ё',
+ Iogon: 'Į',
+ iogon: 'į',
+ Iopf: '𝕀',
+ iopf: '𝕚',
+ Iota: 'Ι',
+ iota: 'ι',
+ iprod: '⨼',
+ iquest: '¿',
+ iscr: '𝒾',
+ Iscr: 'ℐ',
+ isin: '∈',
+ isindot: '⋵',
+ isinE: '⋹',
+ isins: '⋴',
+ isinsv: '⋳',
+ isinv: '∈',
+ it: '⁢',
+ Itilde: 'Ĩ',
+ itilde: 'ĩ',
+ Iukcy: 'І',
+ iukcy: 'і',
+ Iuml: 'Ï',
+ iuml: 'ï',
+ Jcirc: 'Ĵ',
+ jcirc: 'ĵ',
+ Jcy: 'Й',
+ jcy: 'й',
+ Jfr: '𝔍',
+ jfr: '𝔧',
+ jmath: 'ȷ',
+ Jopf: '𝕁',
+ jopf: '𝕛',
+ Jscr: '𝒥',
+ jscr: '𝒿',
+ Jsercy: 'Ј',
+ jsercy: 'ј',
+ Jukcy: 'Є',
+ jukcy: 'є',
+ Kappa: 'Κ',
+ kappa: 'κ',
+ kappav: 'ϰ',
+ Kcedil: 'Ķ',
+ kcedil: 'ķ',
+ Kcy: 'К',
+ kcy: 'к',
+ Kfr: '𝔎',
+ kfr: '𝔨',
+ kgreen: 'ĸ',
+ KHcy: 'Х',
+ khcy: 'х',
+ KJcy: 'Ќ',
+ kjcy: 'ќ',
+ Kopf: '𝕂',
+ kopf: '𝕜',
+ Kscr: '𝒦',
+ kscr: '𝓀',
+ lAarr: '⇚',
+ Lacute: 'Ĺ',
+ lacute: 'ĺ',
+ laemptyv: '⦴',
+ lagran: 'ℒ',
+ Lambda: 'Λ',
+ lambda: 'λ',
+ lang: '⟨',
+ Lang: '⟪',
+ langd: '⦑',
+ langle: '⟨',
+ lap: '⪅',
+ Laplacetrf: 'ℒ',
+ laquo: '«',
+ larrb: '⇤',
+ larrbfs: '⤟',
+ larr: '←',
+ Larr: '↞',
+ lArr: '⇐',
+ larrfs: '⤝',
+ larrhk: '↩',
+ larrlp: '↫',
+ larrpl: '⤹',
+ larrsim: '⥳',
+ larrtl: '↢',
+ latail: '⤙',
+ lAtail: '⤛',
+ lat: '⪫',
+ late: '⪭',
+ lates: '⪭',
+ lbarr: '⤌',
+ lBarr: '⤎',
+ lbbrk: '❲',
+ lbrace: '{',
+ lbrack: '[',
+ lbrke: '⦋',
+ lbrksld: '⦏',
+ lbrkslu: '⦍',
+ Lcaron: 'Ľ',
+ lcaron: 'ľ',
+ Lcedil: 'Ļ',
+ lcedil: 'ļ',
+ lceil: '⌈',
+ lcub: '{',
+ Lcy: 'Л',
+ lcy: 'л',
+ ldca: '⤶',
+ ldquo: '“',
+ ldquor: '„',
+ ldrdhar: '⥧',
+ ldrushar: '⥋',
+ ldsh: '↲',
+ le: '≤',
+ lE: '≦',
+ LeftAngleBracket: '⟨',
+ LeftArrowBar: '⇤',
+ leftarrow: '←',
+ LeftArrow: '←',
+ Leftarrow: '⇐',
+ LeftArrowRightArrow: '⇆',
+ leftarrowtail: '↢',
+ LeftCeiling: '⌈',
+ LeftDoubleBracket: '⟦',
+ LeftDownTeeVector: '⥡',
+ LeftDownVectorBar: '⥙',
+ LeftDownVector: '⇃',
+ LeftFloor: '⌊',
+ leftharpoondown: '↽',
+ leftharpoonup: '↼',
+ leftleftarrows: '⇇',
+ leftrightarrow: '↔',
+ LeftRightArrow: '↔',
+ Leftrightarrow: '⇔',
+ leftrightarrows: '⇆',
+ leftrightharpoons: '⇋',
+ leftrightsquigarrow: '↭',
+ LeftRightVector: '⥎',
+ LeftTeeArrow: '↤',
+ LeftTee: '⊣',
+ LeftTeeVector: '⥚',
+ leftthreetimes: '⋋',
+ LeftTriangleBar: '⧏',
+ LeftTriangle: '⊲',
+ LeftTriangleEqual: '⊴',
+ LeftUpDownVector: '⥑',
+ LeftUpTeeVector: '⥠',
+ LeftUpVectorBar: '⥘',
+ LeftUpVector: '↿',
+ LeftVectorBar: '⥒',
+ LeftVector: '↼',
+ lEg: '⪋',
+ leg: '⋚',
+ leq: '≤',
+ leqq: '≦',
+ leqslant: '⩽',
+ lescc: '⪨',
+ les: '⩽',
+ lesdot: '⩿',
+ lesdoto: '⪁',
+ lesdotor: '⪃',
+ lesg: '⋚',
+ lesges: '⪓',
+ lessapprox: '⪅',
+ lessdot: '⋖',
+ lesseqgtr: '⋚',
+ lesseqqgtr: '⪋',
+ LessEqualGreater: '⋚',
+ LessFullEqual: '≦',
+ LessGreater: '≶',
+ lessgtr: '≶',
+ LessLess: '⪡',
+ lesssim: '≲',
+ LessSlantEqual: '⩽',
+ LessTilde: '≲',
+ lfisht: '⥼',
+ lfloor: '⌊',
+ Lfr: '𝔏',
+ lfr: '𝔩',
+ lg: '≶',
+ lgE: '⪑',
+ lHar: '⥢',
+ lhard: '↽',
+ lharu: '↼',
+ lharul: '⥪',
+ lhblk: '▄',
+ LJcy: 'Љ',
+ ljcy: 'љ',
+ llarr: '⇇',
+ ll: '≪',
+ Ll: '⋘',
+ llcorner: '⌞',
+ Lleftarrow: '⇚',
+ llhard: '⥫',
+ lltri: '◺',
+ Lmidot: 'Ŀ',
+ lmidot: 'ŀ',
+ lmoustache: '⎰',
+ lmoust: '⎰',
+ lnap: '⪉',
+ lnapprox: '⪉',
+ lne: '⪇',
+ lnE: '≨',
+ lneq: '⪇',
+ lneqq: '≨',
+ lnsim: '⋦',
+ loang: '⟬',
+ loarr: '⇽',
+ lobrk: '⟦',
+ longleftarrow: '⟵',
+ LongLeftArrow: '⟵',
+ Longleftarrow: '⟸',
+ longleftrightarrow: '⟷',
+ LongLeftRightArrow: '⟷',
+ Longleftrightarrow: '⟺',
+ longmapsto: '⟼',
+ longrightarrow: '⟶',
+ LongRightArrow: '⟶',
+ Longrightarrow: '⟹',
+ looparrowleft: '↫',
+ looparrowright: '↬',
+ lopar: '⦅',
+ Lopf: '𝕃',
+ lopf: '𝕝',
+ loplus: '⨭',
+ lotimes: '⨴',
+ lowast: '∗',
+ lowbar: '_',
+ LowerLeftArrow: '↙',
+ LowerRightArrow: '↘',
+ loz: '◊',
+ lozenge: '◊',
+ lozf: '⧫',
+ lpar: '(',
+ lparlt: '⦓',
+ lrarr: '⇆',
+ lrcorner: '⌟',
+ lrhar: '⇋',
+ lrhard: '⥭',
+ lrm: '‎',
+ lrtri: '⊿',
+ lsaquo: '‹',
+ lscr: '𝓁',
+ Lscr: 'ℒ',
+ lsh: '↰',
+ Lsh: '↰',
+ lsim: '≲',
+ lsime: '⪍',
+ lsimg: '⪏',
+ lsqb: '[',
+ lsquo: '‘',
+ lsquor: '‚',
+ Lstrok: 'Ł',
+ lstrok: 'ł',
+ ltcc: '⪦',
+ ltcir: '⩹',
+ lt: '<',
+ LT: '<',
+ Lt: '≪',
+ ltdot: '⋖',
+ lthree: '⋋',
+ ltimes: '⋉',
+ ltlarr: '⥶',
+ ltquest: '⩻',
+ ltri: '◃',
+ ltrie: '⊴',
+ ltrif: '◂',
+ ltrPar: '⦖',
+ lurdshar: '⥊',
+ luruhar: '⥦',
+ lvertneqq: '≨',
+ lvnE: '≨',
+ macr: '¯',
+ male: '♂',
+ malt: '✠',
+ maltese: '✠',
+ Map: '⤅',
+ map: '↦',
+ mapsto: '↦',
+ mapstodown: '↧',
+ mapstoleft: '↤',
+ mapstoup: '↥',
+ marker: '▮',
+ mcomma: '⨩',
+ Mcy: 'М',
+ mcy: 'м',
+ mdash: '—',
+ mDDot: '∺',
+ measuredangle: '∡',
+ MediumSpace: ' ',
+ Mellintrf: 'ℳ',
+ Mfr: '𝔐',
+ mfr: '𝔪',
+ mho: '℧',
+ micro: 'µ',
+ midast: '*',
+ midcir: '⫰',
+ mid: '∣',
+ middot: '·',
+ minusb: '⊟',
+ minus: '−',
+ minusd: '∸',
+ minusdu: '⨪',
+ MinusPlus: '∓',
+ mlcp: '⫛',
+ mldr: '…',
+ mnplus: '∓',
+ models: '⊧',
+ Mopf: '𝕄',
+ mopf: '𝕞',
+ mp: '∓',
+ mscr: '𝓂',
+ Mscr: 'ℳ',
+ mstpos: '∾',
+ Mu: 'Μ',
+ mu: 'μ',
+ multimap: '⊸',
+ mumap: '⊸',
+ nabla: '∇',
+ Nacute: 'Ń',
+ nacute: 'ń',
+ nang: '∠',
+ nap: '≉',
+ napE: '⩰',
+ napid: '≋',
+ napos: 'ʼn',
+ napprox: '≉',
+ natural: '♮',
+ naturals: 'ℕ',
+ natur: '♮',
+ nbsp: ' ',
+ nbump: '≎',
+ nbumpe: '≏',
+ ncap: '⩃',
+ Ncaron: 'Ň',
+ ncaron: 'ň',
+ Ncedil: 'Ņ',
+ ncedil: 'ņ',
+ ncong: '≇',
+ ncongdot: '⩭',
+ ncup: '⩂',
+ Ncy: 'Н',
+ ncy: 'н',
+ ndash: '–',
+ nearhk: '⤤',
+ nearr: '↗',
+ neArr: '⇗',
+ nearrow: '↗',
+ ne: '≠',
+ nedot: '≐',
+ NegativeMediumSpace: '​',
+ NegativeThickSpace: '​',
+ NegativeThinSpace: '​',
+ NegativeVeryThinSpace: '​',
+ nequiv: '≢',
+ nesear: '⤨',
+ nesim: '≂',
+ NestedGreaterGreater: '≫',
+ NestedLessLess: '≪',
+ NewLine: '\n',
+ nexist: '∄',
+ nexists: '∄',
+ Nfr: '𝔑',
+ nfr: '𝔫',
+ ngE: '≧',
+ nge: '≱',
+ ngeq: '≱',
+ ngeqq: '≧',
+ ngeqslant: '⩾',
+ nges: '⩾',
+ nGg: '⋙',
+ ngsim: '≵',
+ nGt: '≫',
+ ngt: '≯',
+ ngtr: '≯',
+ nGtv: '≫',
+ nharr: '↮',
+ nhArr: '⇎',
+ nhpar: '⫲',
+ ni: '∋',
+ nis: '⋼',
+ nisd: '⋺',
+ niv: '∋',
+ NJcy: 'Њ',
+ njcy: 'њ',
+ nlarr: '↚',
+ nlArr: '⇍',
+ nldr: '‥',
+ nlE: '≦',
+ nle: '≰',
+ nleftarrow: '↚',
+ nLeftarrow: '⇍',
+ nleftrightarrow: '↮',
+ nLeftrightarrow: '⇎',
+ nleq: '≰',
+ nleqq: '≦',
+ nleqslant: '⩽',
+ nles: '⩽',
+ nless: '≮',
+ nLl: '⋘',
+ nlsim: '≴',
+ nLt: '≪',
+ nlt: '≮',
+ nltri: '⋪',
+ nltrie: '⋬',
+ nLtv: '≪',
+ nmid: '∤',
+ NoBreak: '⁠',
+ NonBreakingSpace: ' ',
+ nopf: '𝕟',
+ Nopf: 'ℕ',
+ Not: '⫬',
+ not: '¬',
+ NotCongruent: '≢',
+ NotCupCap: '≭',
+ NotDoubleVerticalBar: '∦',
+ NotElement: '∉',
+ NotEqual: '≠',
+ NotEqualTilde: '≂',
+ NotExists: '∄',
+ NotGreater: '≯',
+ NotGreaterEqual: '≱',
+ NotGreaterFullEqual: '≧',
+ NotGreaterGreater: '≫',
+ NotGreaterLess: '≹',
+ NotGreaterSlantEqual: '⩾',
+ NotGreaterTilde: '≵',
+ NotHumpDownHump: '≎',
+ NotHumpEqual: '≏',
+ notin: '∉',
+ notindot: '⋵',
+ notinE: '⋹',
+ notinva: '∉',
+ notinvb: '⋷',
+ notinvc: '⋶',
+ NotLeftTriangleBar: '⧏',
+ NotLeftTriangle: '⋪',
+ NotLeftTriangleEqual: '⋬',
+ NotLess: '≮',
+ NotLessEqual: '≰',
+ NotLessGreater: '≸',
+ NotLessLess: '≪',
+ NotLessSlantEqual: '⩽',
+ NotLessTilde: '≴',
+ NotNestedGreaterGreater: '⪢',
+ NotNestedLessLess: '⪡',
+ notni: '∌',
+ notniva: '∌',
+ notnivb: '⋾',
+ notnivc: '⋽',
+ NotPrecedes: '⊀',
+ NotPrecedesEqual: '⪯',
+ NotPrecedesSlantEqual: '⋠',
+ NotReverseElement: '∌',
+ NotRightTriangleBar: '⧐',
+ NotRightTriangle: '⋫',
+ NotRightTriangleEqual: '⋭',
+ NotSquareSubset: '⊏',
+ NotSquareSubsetEqual: '⋢',
+ NotSquareSuperset: '⊐',
+ NotSquareSupersetEqual: '⋣',
+ NotSubset: '⊂',
+ NotSubsetEqual: '⊈',
+ NotSucceeds: '⊁',
+ NotSucceedsEqual: '⪰',
+ NotSucceedsSlantEqual: '⋡',
+ NotSucceedsTilde: '≿',
+ NotSuperset: '⊃',
+ NotSupersetEqual: '⊉',
+ NotTilde: '≁',
+ NotTildeEqual: '≄',
+ NotTildeFullEqual: '≇',
+ NotTildeTilde: '≉',
+ NotVerticalBar: '∤',
+ nparallel: '∦',
+ npar: '∦',
+ nparsl: '⫽',
+ npart: '∂',
+ npolint: '⨔',
+ npr: '⊀',
+ nprcue: '⋠',
+ nprec: '⊀',
+ npreceq: '⪯',
+ npre: '⪯',
+ nrarrc: '⤳',
+ nrarr: '↛',
+ nrArr: '⇏',
+ nrarrw: '↝',
+ nrightarrow: '↛',
+ nRightarrow: '⇏',
+ nrtri: '⋫',
+ nrtrie: '⋭',
+ nsc: '⊁',
+ nsccue: '⋡',
+ nsce: '⪰',
+ Nscr: '𝒩',
+ nscr: '𝓃',
+ nshortmid: '∤',
+ nshortparallel: '∦',
+ nsim: '≁',
+ nsime: '≄',
+ nsimeq: '≄',
+ nsmid: '∤',
+ nspar: '∦',
+ nsqsube: '⋢',
+ nsqsupe: '⋣',
+ nsub: '⊄',
+ nsubE: '⫅',
+ nsube: '⊈',
+ nsubset: '⊂',
+ nsubseteq: '⊈',
+ nsubseteqq: '⫅',
+ nsucc: '⊁',
+ nsucceq: '⪰',
+ nsup: '⊅',
+ nsupE: '⫆',
+ nsupe: '⊉',
+ nsupset: '⊃',
+ nsupseteq: '⊉',
+ nsupseteqq: '⫆',
+ ntgl: '≹',
+ Ntilde: 'Ñ',
+ ntilde: 'ñ',
+ ntlg: '≸',
+ ntriangleleft: '⋪',
+ ntrianglelefteq: '⋬',
+ ntriangleright: '⋫',
+ ntrianglerighteq: '⋭',
+ Nu: 'Ν',
+ nu: 'ν',
+ num: '#',
+ numero: '№',
+ numsp: ' ',
+ nvap: '≍',
+ nvdash: '⊬',
+ nvDash: '⊭',
+ nVdash: '⊮',
+ nVDash: '⊯',
+ nvge: '≥',
+ nvgt: '>',
+ nvHarr: '⤄',
+ nvinfin: '⧞',
+ nvlArr: '⤂',
+ nvle: '≤',
+ nvlt: '>',
+ nvltrie: '⊴',
+ nvrArr: '⤃',
+ nvrtrie: '⊵',
+ nvsim: '∼',
+ nwarhk: '⤣',
+ nwarr: '↖',
+ nwArr: '⇖',
+ nwarrow: '↖',
+ nwnear: '⤧',
+ Oacute: 'Ó',
+ oacute: 'ó',
+ oast: '⊛',
+ Ocirc: 'Ô',
+ ocirc: 'ô',
+ ocir: '⊚',
+ Ocy: 'О',
+ ocy: 'о',
+ odash: '⊝',
+ Odblac: 'Ő',
+ odblac: 'ő',
+ odiv: '⨸',
+ odot: '⊙',
+ odsold: '⦼',
+ OElig: 'Œ',
+ oelig: 'œ',
+ ofcir: '⦿',
+ Ofr: '𝔒',
+ ofr: '𝔬',
+ ogon: '˛',
+ Ograve: 'Ò',
+ ograve: 'ò',
+ ogt: '⧁',
+ ohbar: '⦵',
+ ohm: 'Ω',
+ oint: '∮',
+ olarr: '↺',
+ olcir: '⦾',
+ olcross: '⦻',
+ oline: '‾',
+ olt: '⧀',
+ Omacr: 'Ō',
+ omacr: 'ō',
+ Omega: 'Ω',
+ omega: 'ω',
+ Omicron: 'Ο',
+ omicron: 'ο',
+ omid: '⦶',
+ ominus: '⊖',
+ Oopf: '𝕆',
+ oopf: '𝕠',
+ opar: '⦷',
+ OpenCurlyDoubleQuote: '“',
+ OpenCurlyQuote: '‘',
+ operp: '⦹',
+ oplus: '⊕',
+ orarr: '↻',
+ Or: '⩔',
+ or: '∨',
+ ord: '⩝',
+ order: 'ℴ',
+ orderof: 'ℴ',
+ ordf: 'ª',
+ ordm: 'º',
+ origof: '⊶',
+ oror: '⩖',
+ orslope: '⩗',
+ orv: '⩛',
+ oS: 'Ⓢ',
+ Oscr: '𝒪',
+ oscr: 'ℴ',
+ Oslash: 'Ø',
+ oslash: 'ø',
+ osol: '⊘',
+ Otilde: 'Õ',
+ otilde: 'õ',
+ otimesas: '⨶',
+ Otimes: '⨷',
+ otimes: '⊗',
+ Ouml: 'Ö',
+ ouml: 'ö',
+ ovbar: '⌽',
+ OverBar: '‾',
+ OverBrace: '⏞',
+ OverBracket: '⎴',
+ OverParenthesis: '⏜',
+ para: '¶',
+ parallel: '∥',
+ par: '∥',
+ parsim: '⫳',
+ parsl: '⫽',
+ part: '∂',
+ PartialD: '∂',
+ Pcy: 'П',
+ pcy: 'п',
+ percnt: '%',
+ period: '.',
+ permil: '‰',
+ perp: '⊥',
+ pertenk: '‱',
+ Pfr: '𝔓',
+ pfr: '𝔭',
+ Phi: 'Φ',
+ phi: 'φ',
+ phiv: 'ϕ',
+ phmmat: 'ℳ',
+ phone: '☎',
+ Pi: 'Π',
+ pi: 'π',
+ pitchfork: '⋔',
+ piv: 'ϖ',
+ planck: 'ℏ',
+ planckh: 'ℎ',
+ plankv: 'ℏ',
+ plusacir: '⨣',
+ plusb: '⊞',
+ pluscir: '⨢',
+ plus: '+',
+ plusdo: '∔',
+ plusdu: '⨥',
+ pluse: '⩲',
+ PlusMinus: '±',
+ plusmn: '±',
+ plussim: '⨦',
+ plustwo: '⨧',
+ pm: '±',
+ Poincareplane: 'ℌ',
+ pointint: '⨕',
+ popf: '𝕡',
+ Popf: 'ℙ',
+ pound: '£',
+ prap: '⪷',
+ Pr: '⪻',
+ pr: '≺',
+ prcue: '≼',
+ precapprox: '⪷',
+ prec: '≺',
+ preccurlyeq: '≼',
+ Precedes: '≺',
+ PrecedesEqual: '⪯',
+ PrecedesSlantEqual: '≼',
+ PrecedesTilde: '≾',
+ preceq: '⪯',
+ precnapprox: '⪹',
+ precneqq: '⪵',
+ precnsim: '⋨',
+ pre: '⪯',
+ prE: '⪳',
+ precsim: '≾',
+ prime: '′',
+ Prime: '″',
+ primes: 'ℙ',
+ prnap: '⪹',
+ prnE: '⪵',
+ prnsim: '⋨',
+ prod: '∏',
+ Product: '∏',
+ profalar: '⌮',
+ profline: '⌒',
+ profsurf: '⌓',
+ prop: '∝',
+ Proportional: '∝',
+ Proportion: '∷',
+ propto: '∝',
+ prsim: '≾',
+ prurel: '⊰',
+ Pscr: '𝒫',
+ pscr: '𝓅',
+ Psi: 'Ψ',
+ psi: 'ψ',
+ puncsp: ' ',
+ Qfr: '𝔔',
+ qfr: '𝔮',
+ qint: '⨌',
+ qopf: '𝕢',
+ Qopf: 'ℚ',
+ qprime: '⁗',
+ Qscr: '𝒬',
+ qscr: '𝓆',
+ quaternions: 'ℍ',
+ quatint: '⨖',
+ quest: '?',
+ questeq: '≟',
+ quot: '"',
+ QUOT: '"',
+ rAarr: '⇛',
+ race: '∽',
+ Racute: 'Ŕ',
+ racute: 'ŕ',
+ radic: '√',
+ raemptyv: '⦳',
+ rang: '⟩',
+ Rang: '⟫',
+ rangd: '⦒',
+ range: '⦥',
+ rangle: '⟩',
+ raquo: '»',
+ rarrap: '⥵',
+ rarrb: '⇥',
+ rarrbfs: '⤠',
+ rarrc: '⤳',
+ rarr: '→',
+ Rarr: '↠',
+ rArr: '⇒',
+ rarrfs: '⤞',
+ rarrhk: '↪',
+ rarrlp: '↬',
+ rarrpl: '⥅',
+ rarrsim: '⥴',
+ Rarrtl: '⤖',
+ rarrtl: '↣',
+ rarrw: '↝',
+ ratail: '⤚',
+ rAtail: '⤜',
+ ratio: '∶',
+ rationals: 'ℚ',
+ rbarr: '⤍',
+ rBarr: '⤏',
+ RBarr: '⤐',
+ rbbrk: '❳',
+ rbrace: '}',
+ rbrack: ']',
+ rbrke: '⦌',
+ rbrksld: '⦎',
+ rbrkslu: '⦐',
+ Rcaron: 'Ř',
+ rcaron: 'ř',
+ Rcedil: 'Ŗ',
+ rcedil: 'ŗ',
+ rceil: '⌉',
+ rcub: '}',
+ Rcy: 'Р',
+ rcy: 'р',
+ rdca: '⤷',
+ rdldhar: '⥩',
+ rdquo: '”',
+ rdquor: '”',
+ rdsh: '↳',
+ real: 'ℜ',
+ realine: 'ℛ',
+ realpart: 'ℜ',
+ reals: 'ℝ',
+ Re: 'ℜ',
+ rect: '▭',
+ reg: '®',
+ REG: '®',
+ ReverseElement: '∋',
+ ReverseEquilibrium: '⇋',
+ ReverseUpEquilibrium: '⥯',
+ rfisht: '⥽',
+ rfloor: '⌋',
+ rfr: '𝔯',
+ Rfr: 'ℜ',
+ rHar: '⥤',
+ rhard: '⇁',
+ rharu: '⇀',
+ rharul: '⥬',
+ Rho: 'Ρ',
+ rho: 'ρ',
+ rhov: 'ϱ',
+ RightAngleBracket: '⟩',
+ RightArrowBar: '⇥',
+ rightarrow: '→',
+ RightArrow: '→',
+ Rightarrow: '⇒',
+ RightArrowLeftArrow: '⇄',
+ rightarrowtail: '↣',
+ RightCeiling: '⌉',
+ RightDoubleBracket: '⟧',
+ RightDownTeeVector: '⥝',
+ RightDownVectorBar: '⥕',
+ RightDownVector: '⇂',
+ RightFloor: '⌋',
+ rightharpoondown: '⇁',
+ rightharpoonup: '⇀',
+ rightleftarrows: '⇄',
+ rightleftharpoons: '⇌',
+ rightrightarrows: '⇉',
+ rightsquigarrow: '↝',
+ RightTeeArrow: '↦',
+ RightTee: '⊢',
+ RightTeeVector: '⥛',
+ rightthreetimes: '⋌',
+ RightTriangleBar: '⧐',
+ RightTriangle: '⊳',
+ RightTriangleEqual: '⊵',
+ RightUpDownVector: '⥏',
+ RightUpTeeVector: '⥜',
+ RightUpVectorBar: '⥔',
+ RightUpVector: '↾',
+ RightVectorBar: '⥓',
+ RightVector: '⇀',
+ ring: '˚',
+ risingdotseq: '≓',
+ rlarr: '⇄',
+ rlhar: '⇌',
+ rlm: '‏',
+ rmoustache: '⎱',
+ rmoust: '⎱',
+ rnmid: '⫮',
+ roang: '⟭',
+ roarr: '⇾',
+ robrk: '⟧',
+ ropar: '⦆',
+ ropf: '𝕣',
+ Ropf: 'ℝ',
+ roplus: '⨮',
+ rotimes: '⨵',
+ RoundImplies: '⥰',
+ rpar: ')',
+ rpargt: '⦔',
+ rppolint: '⨒',
+ rrarr: '⇉',
+ Rrightarrow: '⇛',
+ rsaquo: '›',
+ rscr: '𝓇',
+ Rscr: 'ℛ',
+ rsh: '↱',
+ Rsh: '↱',
+ rsqb: ']',
+ rsquo: '’',
+ rsquor: '’',
+ rthree: '⋌',
+ rtimes: '⋊',
+ rtri: '▹',
+ rtrie: '⊵',
+ rtrif: '▸',
+ rtriltri: '⧎',
+ RuleDelayed: '⧴',
+ ruluhar: '⥨',
+ rx: '℞',
+ Sacute: 'Ś',
+ sacute: 'ś',
+ sbquo: '‚',
+ scap: '⪸',
+ Scaron: 'Š',
+ scaron: 'š',
+ Sc: '⪼',
+ sc: '≻',
+ sccue: '≽',
+ sce: '⪰',
+ scE: '⪴',
+ Scedil: 'Ş',
+ scedil: 'ş',
+ Scirc: 'Ŝ',
+ scirc: 'ŝ',
+ scnap: '⪺',
+ scnE: '⪶',
+ scnsim: '⋩',
+ scpolint: '⨓',
+ scsim: '≿',
+ Scy: 'С',
+ scy: 'с',
+ sdotb: '⊡',
+ sdot: '⋅',
+ sdote: '⩦',
+ searhk: '⤥',
+ searr: '↘',
+ seArr: '⇘',
+ searrow: '↘',
+ sect: '§',
+ semi: ';',
+ seswar: '⤩',
+ setminus: '∖',
+ setmn: '∖',
+ sext: '✶',
+ Sfr: '𝔖',
+ sfr: '𝔰',
+ sfrown: '⌢',
+ sharp: '♯',
+ SHCHcy: 'Щ',
+ shchcy: 'щ',
+ SHcy: 'Ш',
+ shcy: 'ш',
+ ShortDownArrow: '↓',
+ ShortLeftArrow: '←',
+ shortmid: '∣',
+ shortparallel: '∥',
+ ShortRightArrow: '→',
+ ShortUpArrow: '↑',
+ shy: '­',
+ Sigma: 'Σ',
+ sigma: 'σ',
+ sigmaf: 'ς',
+ sigmav: 'ς',
+ sim: '∼',
+ simdot: '⩪',
+ sime: '≃',
+ simeq: '≃',
+ simg: '⪞',
+ simgE: '⪠',
+ siml: '⪝',
+ simlE: '⪟',
+ simne: '≆',
+ simplus: '⨤',
+ simrarr: '⥲',
+ slarr: '←',
+ SmallCircle: '∘',
+ smallsetminus: '∖',
+ smashp: '⨳',
+ smeparsl: '⧤',
+ smid: '∣',
+ smile: '⌣',
+ smt: '⪪',
+ smte: '⪬',
+ smtes: '⪬',
+ SOFTcy: 'Ь',
+ softcy: 'ь',
+ solbar: '⌿',
+ solb: '⧄',
+ sol: '/',
+ Sopf: '𝕊',
+ sopf: '𝕤',
+ spades: '♠',
+ spadesuit: '♠',
+ spar: '∥',
+ sqcap: '⊓',
+ sqcaps: '⊓',
+ sqcup: '⊔',
+ sqcups: '⊔',
+ Sqrt: '√',
+ sqsub: '⊏',
+ sqsube: '⊑',
+ sqsubset: '⊏',
+ sqsubseteq: '⊑',
+ sqsup: '⊐',
+ sqsupe: '⊒',
+ sqsupset: '⊐',
+ sqsupseteq: '⊒',
+ square: '□',
+ Square: '□',
+ SquareIntersection: '⊓',
+ SquareSubset: '⊏',
+ SquareSubsetEqual: '⊑',
+ SquareSuperset: '⊐',
+ SquareSupersetEqual: '⊒',
+ SquareUnion: '⊔',
+ squarf: '▪',
+ squ: '□',
+ squf: '▪',
+ srarr: '→',
+ Sscr: '𝒮',
+ sscr: '𝓈',
+ ssetmn: '∖',
+ ssmile: '⌣',
+ sstarf: '⋆',
+ Star: '⋆',
+ star: '☆',
+ starf: '★',
+ straightepsilon: 'ϵ',
+ straightphi: 'ϕ',
+ strns: '¯',
+ sub: '⊂',
+ Sub: '⋐',
+ subdot: '⪽',
+ subE: '⫅',
+ sube: '⊆',
+ subedot: '⫃',
+ submult: '⫁',
+ subnE: '⫋',
+ subne: '⊊',
+ subplus: '⪿',
+ subrarr: '⥹',
+ subset: '⊂',
+ Subset: '⋐',
+ subseteq: '⊆',
+ subseteqq: '⫅',
+ SubsetEqual: '⊆',
+ subsetneq: '⊊',
+ subsetneqq: '⫋',
+ subsim: '⫇',
+ subsub: '⫕',
+ subsup: '⫓',
+ succapprox: '⪸',
+ succ: '≻',
+ succcurlyeq: '≽',
+ Succeeds: '≻',
+ SucceedsEqual: '⪰',
+ SucceedsSlantEqual: '≽',
+ SucceedsTilde: '≿',
+ succeq: '⪰',
+ succnapprox: '⪺',
+ succneqq: '⪶',
+ succnsim: '⋩',
+ succsim: '≿',
+ SuchThat: '∋',
+ sum: '∑',
+ Sum: '∑',
+ sung: '♪',
+ sup1: '¹',
+ sup2: '²',
+ sup3: '³',
+ sup: '⊃',
+ Sup: '⋑',
+ supdot: '⪾',
+ supdsub: '⫘',
+ supE: '⫆',
+ supe: '⊇',
+ supedot: '⫄',
+ Superset: '⊃',
+ SupersetEqual: '⊇',
+ suphsol: '⟉',
+ suphsub: '⫗',
+ suplarr: '⥻',
+ supmult: '⫂',
+ supnE: '⫌',
+ supne: '⊋',
+ supplus: '⫀',
+ supset: '⊃',
+ Supset: '⋑',
+ supseteq: '⊇',
+ supseteqq: '⫆',
+ supsetneq: '⊋',
+ supsetneqq: '⫌',
+ supsim: '⫈',
+ supsub: '⫔',
+ supsup: '⫖',
+ swarhk: '⤦',
+ swarr: '↙',
+ swArr: '⇙',
+ swarrow: '↙',
+ swnwar: '⤪',
+ szlig: 'ß',
+ Tab: ' ',
+ target: '⌖',
+ Tau: 'Τ',
+ tau: 'τ',
+ tbrk: '⎴',
+ Tcaron: 'Ť',
+ tcaron: 'ť',
+ Tcedil: 'Ţ',
+ tcedil: 'ţ',
+ Tcy: 'Т',
+ tcy: 'т',
+ tdot: '⃛',
+ telrec: '⌕',
+ Tfr: '𝔗',
+ tfr: '𝔱',
+ there4: '∴',
+ therefore: '∴',
+ Therefore: '∴',
+ Theta: 'Θ',
+ theta: 'θ',
+ thetasym: 'ϑ',
+ thetav: 'ϑ',
+ thickapprox: '≈',
+ thicksim: '∼',
+ ThickSpace: ' ',
+ ThinSpace: ' ',
+ thinsp: ' ',
+ thkap: '≈',
+ thksim: '∼',
+ THORN: 'Þ',
+ thorn: 'þ',
+ tilde: '˜',
+ Tilde: '∼',
+ TildeEqual: '≃',
+ TildeFullEqual: '≅',
+ TildeTilde: '≈',
+ timesbar: '⨱',
+ timesb: '⊠',
+ times: '×',
+ timesd: '⨰',
+ tint: '∭',
+ toea: '⤨',
+ topbot: '⌶',
+ topcir: '⫱',
+ top: '⊤',
+ Topf: '𝕋',
+ topf: '𝕥',
+ topfork: '⫚',
+ tosa: '⤩',
+ tprime: '‴',
+ trade: '™',
+ TRADE: '™',
+ triangle: '▵',
+ triangledown: '▿',
+ triangleleft: '◃',
+ trianglelefteq: '⊴',
+ triangleq: '≜',
+ triangleright: '▹',
+ trianglerighteq: '⊵',
+ tridot: '◬',
+ trie: '≜',
+ triminus: '⨺',
+ TripleDot: '⃛',
+ triplus: '⨹',
+ trisb: '⧍',
+ tritime: '⨻',
+ trpezium: '⏢',
+ Tscr: '𝒯',
+ tscr: '𝓉',
+ TScy: 'Ц',
+ tscy: 'ц',
+ TSHcy: 'Ћ',
+ tshcy: 'ћ',
+ Tstrok: 'Ŧ',
+ tstrok: 'ŧ',
+ twixt: '≬',
+ twoheadleftarrow: '↞',
+ twoheadrightarrow: '↠',
+ Uacute: 'Ú',
+ uacute: 'ú',
+ uarr: '↑',
+ Uarr: '↟',
+ uArr: '⇑',
+ Uarrocir: '⥉',
+ Ubrcy: 'Ў',
+ ubrcy: 'ў',
+ Ubreve: 'Ŭ',
+ ubreve: 'ŭ',
+ Ucirc: 'Û',
+ ucirc: 'û',
+ Ucy: 'У',
+ ucy: 'у',
+ udarr: '⇅',
+ Udblac: 'Ű',
+ udblac: 'ű',
+ udhar: '⥮',
+ ufisht: '⥾',
+ Ufr: '𝔘',
+ ufr: '𝔲',
+ Ugrave: 'Ù',
+ ugrave: 'ù',
+ uHar: '⥣',
+ uharl: '↿',
+ uharr: '↾',
+ uhblk: '▀',
+ ulcorn: '⌜',
+ ulcorner: '⌜',
+ ulcrop: '⌏',
+ ultri: '◸',
+ Umacr: 'Ū',
+ umacr: 'ū',
+ uml: '¨',
+ UnderBar: '_',
+ UnderBrace: '⏟',
+ UnderBracket: '⎵',
+ UnderParenthesis: '⏝',
+ Union: '⋃',
+ UnionPlus: '⊎',
+ Uogon: 'Ų',
+ uogon: 'ų',
+ Uopf: '𝕌',
+ uopf: '𝕦',
+ UpArrowBar: '⤒',
+ uparrow: '↑',
+ UpArrow: '↑',
+ Uparrow: '⇑',
+ UpArrowDownArrow: '⇅',
+ updownarrow: '↕',
+ UpDownArrow: '↕',
+ Updownarrow: '⇕',
+ UpEquilibrium: '⥮',
+ upharpoonleft: '↿',
+ upharpoonright: '↾',
+ uplus: '⊎',
+ UpperLeftArrow: '↖',
+ UpperRightArrow: '↗',
+ upsi: 'υ',
+ Upsi: 'ϒ',
+ upsih: 'ϒ',
+ Upsilon: 'Υ',
+ upsilon: 'υ',
+ UpTeeArrow: '↥',
+ UpTee: '⊥',
+ upuparrows: '⇈',
+ urcorn: '⌝',
+ urcorner: '⌝',
+ urcrop: '⌎',
+ Uring: 'Ů',
+ uring: 'ů',
+ urtri: '◹',
+ Uscr: '𝒰',
+ uscr: '𝓊',
+ utdot: '⋰',
+ Utilde: 'Ũ',
+ utilde: 'ũ',
+ utri: '▵',
+ utrif: '▴',
+ uuarr: '⇈',
+ Uuml: 'Ü',
+ uuml: 'ü',
+ uwangle: '⦧',
+ vangrt: '⦜',
+ varepsilon: 'ϵ',
+ varkappa: 'ϰ',
+ varnothing: '∅',
+ varphi: 'ϕ',
+ varpi: 'ϖ',
+ varpropto: '∝',
+ varr: '↕',
+ vArr: '⇕',
+ varrho: 'ϱ',
+ varsigma: 'ς',
+ varsubsetneq: '⊊',
+ varsubsetneqq: '⫋',
+ varsupsetneq: '⊋',
+ varsupsetneqq: '⫌',
+ vartheta: 'ϑ',
+ vartriangleleft: '⊲',
+ vartriangleright: '⊳',
+ vBar: '⫨',
+ Vbar: '⫫',
+ vBarv: '⫩',
+ Vcy: 'В',
+ vcy: 'в',
+ vdash: '⊢',
+ vDash: '⊨',
+ Vdash: '⊩',
+ VDash: '⊫',
+ Vdashl: '⫦',
+ veebar: '⊻',
+ vee: '∨',
+ Vee: '⋁',
+ veeeq: '≚',
+ vellip: '⋮',
+ verbar: '|',
+ Verbar: '‖',
+ vert: '|',
+ Vert: '‖',
+ VerticalBar: '∣',
+ VerticalLine: '|',
+ VerticalSeparator: '❘',
+ VerticalTilde: '≀',
+ VeryThinSpace: ' ',
+ Vfr: '𝔙',
+ vfr: '𝔳',
+ vltri: '⊲',
+ vnsub: '⊂',
+ vnsup: '⊃',
+ Vopf: '𝕍',
+ vopf: '𝕧',
+ vprop: '∝',
+ vrtri: '⊳',
+ Vscr: '𝒱',
+ vscr: '𝓋',
+ vsubnE: '⫋',
+ vsubne: '⊊',
+ vsupnE: '⫌',
+ vsupne: '⊋',
+ Vvdash: '⊪',
+ vzigzag: '⦚',
+ Wcirc: 'Ŵ',
+ wcirc: 'ŵ',
+ wedbar: '⩟',
+ wedge: '∧',
+ Wedge: '⋀',
+ wedgeq: '≙',
+ weierp: '℘',
+ Wfr: '𝔚',
+ wfr: '𝔴',
+ Wopf: '𝕎',
+ wopf: '𝕨',
+ wp: '℘',
+ wr: '≀',
+ wreath: '≀',
+ Wscr: '𝒲',
+ wscr: '𝓌',
+ xcap: '⋂',
+ xcirc: '◯',
+ xcup: '⋃',
+ xdtri: '▽',
+ Xfr: '𝔛',
+ xfr: '𝔵',
+ xharr: '⟷',
+ xhArr: '⟺',
+ Xi: 'Ξ',
+ xi: 'ξ',
+ xlarr: '⟵',
+ xlArr: '⟸',
+ xmap: '⟼',
+ xnis: '⋻',
+ xodot: '⨀',
+ Xopf: '𝕏',
+ xopf: '𝕩',
+ xoplus: '⨁',
+ xotime: '⨂',
+ xrarr: '⟶',
+ xrArr: '⟹',
+ Xscr: '𝒳',
+ xscr: '𝓍',
+ xsqcup: '⨆',
+ xuplus: '⨄',
+ xutri: '△',
+ xvee: '⋁',
+ xwedge: '⋀',
+ Yacute: 'Ý',
+ yacute: 'ý',
+ YAcy: 'Я',
+ yacy: 'я',
+ Ycirc: 'Ŷ',
+ ycirc: 'ŷ',
+ Ycy: 'Ы',
+ ycy: 'ы',
+ yen: '¥',
+ Yfr: '𝔜',
+ yfr: '𝔶',
+ YIcy: 'Ї',
+ yicy: 'ї',
+ Yopf: '𝕐',
+ yopf: '𝕪',
+ Yscr: '𝒴',
+ yscr: '𝓎',
+ YUcy: 'Ю',
+ yucy: 'ю',
+ yuml: 'ÿ',
+ Yuml: 'Ÿ',
+ Zacute: 'Ź',
+ zacute: 'ź',
+ Zcaron: 'Ž',
+ zcaron: 'ž',
+ Zcy: 'З',
+ zcy: 'з',
+ Zdot: 'Ż',
+ zdot: 'ż',
+ zeetrf: 'ℨ',
+ ZeroWidthSpace: '​',
+ Zeta: 'Ζ',
+ zeta: 'ζ',
+ zfr: '𝔷',
+ Zfr: 'ℨ',
+ ZHcy: 'Ж',
+ zhcy: 'ж',
+ zigrarr: '⇝',
+ zopf: '𝕫',
+ Zopf: 'ℤ',
+ Zscr: '𝒵',
+ zscr: '𝓏',
+ zwj: '‍',
+ zwnj: '‌' };
+
+var entityToChar = function(m) {
+ var isNumeric = /^&#/.test(m);
+ var isHex = /^&#[Xx]/.test(m);
+ var uchar;
+ if (isNumeric) {
+ var num;
+ if (isHex) {
+ num = parseInt(m.slice(3,-1), 16);
+ } else {
+ num = parseInt(m.slice(2,-1), 10);
+ }
+ uchar = fromCodePoint(num);
+ } else {
+ uchar = entities[m.slice(1,-1)];
+ }
+ return (uchar || m);
+};
+
+module.exports.entityToChar = entityToChar;
diff --git a/js/lib/index.js b/js/lib/index.js
new file mode 100755
index 0000000..d1f3577
--- /dev/null
+++ b/js/lib/index.js
@@ -0,0 +1,20 @@
+// commonmark.js - CommomMark in JavaScript
+// Copyright (C) 2014 John MacFarlane
+// License: BSD3.
+
+// Basic usage:
+//
+// var commonmark = require('commonmark');
+// var parser = new commonmark.DocParser();
+// var renderer = new commonmark.HtmlRenderer();
+// console.log(renderer.render(parser.parse('Hello *world*')));
+
+var util = require('util');
+
+var renderAST = function(tree) {
+ return util.inspect(tree, {depth: null});
+}
+
+module.exports.DocParser = require('./blocks');
+module.exports.HtmlRenderer = require('./html-renderer');
+module.exports.ASTRenderer = renderAST;
diff --git a/js/lib/inlines.js b/js/lib/inlines.js
new file mode 100644
index 0000000..5fde099
--- /dev/null
+++ b/js/lib/inlines.js
@@ -0,0 +1,714 @@
+var fromCodePoint = require('./from-code-point.js');
+var entityToChar = require('./html5-entities.js').entityToChar;
+
+// Constants for character codes:
+
+var C_NEWLINE = 10;
+var C_SPACE = 32;
+var C_ASTERISK = 42;
+var C_UNDERSCORE = 95;
+var C_BACKTICK = 96;
+var C_OPEN_BRACKET = 91;
+var C_CLOSE_BRACKET = 93;
+var C_LESSTHAN = 60;
+var C_GREATERTHAN = 62;
+var C_BANG = 33;
+var C_BACKSLASH = 92;
+var C_AMPERSAND = 38;
+var C_OPEN_PAREN = 40;
+var C_COLON = 58;
+
+// Some regexps used in inline parser:
+
+var ESCAPABLE = '[!"#$%&\'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]';
+var ESCAPED_CHAR = '\\\\' + ESCAPABLE;
+var IN_DOUBLE_QUOTES = '"(' + ESCAPED_CHAR + '|[^"\\x00])*"';
+var IN_SINGLE_QUOTES = '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'';
+var IN_PARENS = '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\)';
+var REG_CHAR = '[^\\\\()\\x00-\\x20]';
+var IN_PARENS_NOSP = '\\((' + REG_CHAR + '|' + ESCAPED_CHAR + ')*\\)';
+var TAGNAME = '[A-Za-z][A-Za-z0-9]*';
+var ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
+var UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+";
+var SINGLEQUOTEDVALUE = "'[^']*'";
+var DOUBLEQUOTEDVALUE = '"[^"]*"';
+var ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")";
+var ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")";
+var ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)";
+var OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>";
+var CLOSETAG = "</" + TAGNAME + "\\s*[>]";
+var HTMLCOMMENT = "<!--([^-]+|[-][^-]+)*-->";
+var PROCESSINGINSTRUCTION = "[<][?].*?[?][>]";
+var DECLARATION = "<![A-Z]+" + "\\s+[^>]*>";
+var CDATA = "<!\\[CDATA\\[([^\\]]+|\\][^\\]]|\\]\\][^>])*\\]\\]>";
+var HTMLTAG = "(?:" + OPENTAG + "|" + CLOSETAG + "|" + HTMLCOMMENT + "|" +
+ PROCESSINGINSTRUCTION + "|" + DECLARATION + "|" + CDATA + ")";
+var ENTITY = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});";
+
+var reHtmlTag = new RegExp('^' + HTMLTAG, 'i');
+
+var reLinkTitle = new RegExp(
+ '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' +
+ '|' +
+ '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'' +
+ '|' +
+ '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\))');
+
+var reLinkDestinationBraces = new RegExp(
+ '^(?:[<](?:[^<>\\n\\\\\\x00]' + '|' + ESCAPED_CHAR + '|' + '\\\\)*[>])');
+
+var reLinkDestination = new RegExp(
+ '^(?:' + REG_CHAR + '+|' + ESCAPED_CHAR + '|' + IN_PARENS_NOSP + ')*');
+
+var reEscapable = new RegExp(ESCAPABLE);
+
+var reAllEscapedChar = new RegExp('\\\\(' + ESCAPABLE + ')', 'g');
+
+var reEscapedChar = new RegExp('^\\\\(' + ESCAPABLE + ')');
+
+var reEntityHere = new RegExp('^' + ENTITY, 'i');
+
+var reEntity = new RegExp(ENTITY, 'gi');
+
+// Matches a character with a special meaning in markdown,
+// or a string of non-special characters. Note: we match
+// clumps of _ or * or `, because they need to be handled in groups.
+var reMain = /^(?:[_*`\n]+|[\[\]\\!<&*_]|(?: *[^\n `\[\]\\!<&*_]+)+|[ \n]+)/m;
+
+// Replace entities and backslash escapes with literal characters.
+var unescapeString = function(s) {
+ return s.replace(reAllEscapedChar, '$1')
+ .replace(reEntity, entityToChar);
+};
+
+// Normalize reference label: collapse internal whitespace
+// to single space, remove leading/trailing whitespace, case fold.
+var normalizeReference = function(s) {
+ return s.trim()
+ .replace(/\s+/,' ')
+ .toUpperCase();
+};
+
+// INLINE PARSER
+
+// These are methods of an InlineParser object, defined below.
+// An InlineParser keeps track of a subject (a string to be
+// parsed) and a position in that subject.
+
+// If re matches at current position in the subject, advance
+// position in subject and return the match; otherwise return null.
+var match = function(re) {
+ var match = re.exec(this.subject.slice(this.pos));
+ if (match) {
+ this.pos += match.index + match[0].length;
+ return match[0];
+ } else {
+ return null;
+ }
+};
+
+// Returns the code for the character at the current subject position, or -1
+// there are no more characters.
+var peek = function() {
+ if (this.pos < this.subject.length) {
+ return this.subject.charCodeAt(this.pos);
+ } else {
+ return -1;
+ }
+};
+
+// Parse zero or more space characters, including at most one newline
+var spnl = function() {
+ this.match(/^ *(?:\n *)?/);
+ return 1;
+};
+
+// All of the parsers below try to match something at the current position
+// in the subject. If they succeed in matching anything, they
+// return the inline matched, advancing the subject.
+
+// Attempt to parse backticks, returning either a backtick code span or a
+// literal sequence of backticks.
+var parseBackticks = function(inlines) {
+ var startpos = this.pos;
+ var ticks = this.match(/^`+/);
+ if (!ticks) {
+ return 0;
+ }
+ var afterOpenTicks = this.pos;
+ var foundCode = false;
+ var match;
+ while (!foundCode && (match = this.match(/`+/m))) {
+ if (match == ticks) {
+ inlines.push({ t: 'Code', c: this.subject.slice(afterOpenTicks,
+ this.pos - ticks.length)
+ .replace(/[ \n]+/g,' ')
+ .trim() });
+ return true;
+ }
+ }
+ // If we got here, we didn't match a closing backtick sequence.
+ this.pos = afterOpenTicks;
+ inlines.push({ t: 'Str', c: ticks });
+ return true;
+};
+
+// Parse a backslash-escaped special character, adding either the escaped
+// character, a hard line break (if the backslash is followed by a newline),
+// or a literal backslash to the 'inlines' list.
+var parseBackslash = function(inlines) {
+ var subj = this.subject,
+ pos = this.pos;
+ if (subj.charCodeAt(pos) === C_BACKSLASH) {
+ if (subj.charAt(pos + 1) === '\n') {
+ this.pos = this.pos + 2;
+ inlines.push({ t: 'Hardbreak' });
+ } else if (reEscapable.test(subj.charAt(pos + 1))) {
+ this.pos = this.pos + 2;
+ inlines.push({ t: 'Str', c: subj.charAt(pos + 1) });
+ } else {
+ this.pos++;
+ inlines.push({t: 'Str', c: '\\'});
+ }
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// Attempt to parse an autolink (URL or email in pointy brackets).
+var parseAutolink = function(inlines) {
+ var m;
+ var dest;
+ if ((m = this.match(/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/))) { // email autolink
+ dest = m.slice(1,-1);
+ inlines.push(
+ {t: 'Link',
+ label: [{ t: 'Str', c: dest }],
+ destination: 'mailto:' + encodeURI(unescape(dest)) });
+ return true;
+ } else if ((m = this.match(/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i))) {
+ dest = m.slice(1,-1);
+ inlines.push({
+ t: 'Link',
+ label: [{ t: 'Str', c: dest }],
+ destination: encodeURI(unescape(dest)) });
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// Attempt to parse a raw HTML tag.
+var parseHtmlTag = function(inlines) {
+ var m = this.match(reHtmlTag);
+ if (m) {
+ inlines.push({ t: 'Html', c: m });
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// Scan a sequence of characters with code cc, and return information about
+// the number of delimiters and whether they are positioned such that
+// they can open and/or close emphasis or strong emphasis. A utility
+// function for strong/emph parsing.
+var scanDelims = function(cc) {
+ var numdelims = 0;
+ var first_close_delims = 0;
+ var char_before, char_after, cc_after;
+ var startpos = this.pos;
+
+ char_before = this.pos === 0 ? '\n' :
+ this.subject.charAt(this.pos - 1);
+
+ while (this.peek() === cc) {
+ numdelims++;
+ this.pos++;
+ }
+
+ cc_after = this.peek();
+ if (cc_after === -1) {
+ char_after = '\n';
+ } else {
+ char_after = fromCodePoint(cc_after);
+ }
+
+ var can_open = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_after));
+ var can_close = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_before));
+ if (cc === C_UNDERSCORE) {
+ can_open = can_open && !((/[a-z0-9]/i).test(char_before));
+ can_close = can_close && !((/[a-z0-9]/i).test(char_after));
+ }
+ this.pos = startpos;
+ return { numdelims: numdelims,
+ can_open: can_open,
+ can_close: can_close };
+};
+
+var Emph = function(ils) {
+ return {t: 'Emph', c: ils};
+};
+
+var Strong = function(ils) {
+ return {t: 'Strong', c: ils};
+};
+
+var Str = function(s) {
+ return {t: 'Str', c: s};
+};
+
+// Attempt to parse emphasis or strong emphasis.
+var parseEmphasis = function(cc,inlines) {
+ var startpos = this.pos;
+
+ var res = this.scanDelims(cc);
+ var numdelims = res.numdelims;
+
+ if (numdelims === 0) {
+ this.pos = startpos;
+ return false;
+ }
+
+ if (res.can_close) {
+
+ // Walk the stack and find a matching opener, if possible
+ var opener = this.emphasis_openers;
+ while (opener) {
+
+ if (opener.cc === cc) { // we have a match!
+
+ if (opener.numdelims <= numdelims) { // all openers used
+
+ this.pos += opener.numdelims;
+ var X;
+ switch (opener.numdelims) {
+ case 3:
+ X = function(x) { return Strong([Emph(x)]); };
+ break;
+ case 2:
+ X = Strong;
+ break;
+ case 1:
+ default:
+ X = Emph;
+ break;
+ }
+ inlines[opener.pos] = X(inlines.slice(opener.pos + 1));
+ inlines.splice(opener.pos + 1, inlines.length - (opener.pos + 1));
+ // Remove entries after this, to prevent overlapping nesting:
+ this.emphasis_openers = opener.previous;
+ return true;
+
+ } else if (opener.numdelims > numdelims) { // only some openers used
+
+ this.pos += numdelims;
+ opener.numdelims -= numdelims;
+ inlines[opener.pos].c =
+ inlines[opener.pos].c.slice(0, opener.numdelims);
+ var X = numdelims === 2 ? Strong : Emph;
+ inlines[opener.pos + 1] = X(inlines.slice(opener.pos + 1));
+ inlines.splice(opener.pos + 2, inlines.length - (opener.pos + 2));
+ // Remove entries after this, to prevent overlapping nesting:
+ this.emphasis_openers = opener;
+ return true;
+
+ }
+
+ }
+ opener = opener.previous;
+ }
+ }
+
+ // If we're here, we didn't match a closer.
+
+ this.pos += numdelims;
+ inlines.push(Str(this.subject.slice(startpos, startpos + numdelims)));
+
+ if (res.can_open) {
+
+ // Add entry to stack for this opener
+ this.emphasis_openers = { cc: cc,
+ numdelims: numdelims,
+ pos: inlines.length - 1,
+ previous: this.emphasis_openers };
+ }
+
+ return true;
+
+};
+
+// Attempt to parse link title (sans quotes), returning the string
+// or null if no match.
+var parseLinkTitle = function() {
+ var title = this.match(reLinkTitle);
+ if (title) {
+ // chop off quotes from title and unescape:
+ return unescapeString(title.substr(1, title.length - 2));
+ } else {
+ return null;
+ }
+};
+
+// Attempt to parse link destination, returning the string or
+// null if no match.
+var parseLinkDestination = function() {
+ var res = this.match(reLinkDestinationBraces);
+ if (res) { // chop off surrounding <..>:
+ return encodeURI(unescape(unescapeString(res.substr(1, res.length - 2))));
+ } else {
+ res = this.match(reLinkDestination);
+ if (res !== null) {
+ return encodeURI(unescape(unescapeString(res)));
+ } else {
+ return null;
+ }
+ }
+};
+
+// Attempt to parse a link label, returning number of characters parsed.
+var parseLinkLabel = function() {
+ if (this.peek() != C_OPEN_BRACKET) {
+ return 0;
+ }
+ var startpos = this.pos;
+ var nest_level = 0;
+ if (this.label_nest_level > 0) {
+ // If we've already checked to the end of this subject
+ // for a label, even with a different starting [, we
+ // know we won't find one here and we can just return.
+ // This avoids lots of backtracking.
+ // Note: nest level 1 would be: [foo [bar]
+ // nest level 2 would be: [foo [bar [baz]
+ this.label_nest_level--;
+ return 0;
+ }
+ this.pos++; // advance past [
+ var c;
+ while ((c = this.peek()) && c != -1 && (c != C_CLOSE_BRACKET || nest_level > 0)) {
+ switch (c) {
+ case C_BACKTICK:
+ this.parseBackticks([]);
+ break;
+ case C_LESSTHAN:
+ if (!(this.parseAutolink([]) || this.parseHtmlTag([]))) {
+ this.pos++;
+ }
+ break;
+ case C_OPEN_BRACKET: // nested []
+ nest_level++;
+ this.pos++;
+ break;
+ case C_CLOSE_BRACKET: // nested []
+ nest_level--;
+ this.pos++;
+ break;
+ case C_BACKSLASH:
+ this.parseBackslash([]);
+ break;
+ default:
+ this.parseString([]);
+ }
+ }
+ if (c === C_CLOSE_BRACKET) {
+ this.label_nest_level = 0;
+ this.pos++; // advance past ]
+ return this.pos - startpos;
+ } else {
+ if (c === -1) {
+ this.label_nest_level = nest_level;
+ }
+ this.pos = startpos;
+ return 0;
+ }
+};
+
+// Parse raw link label, including surrounding [], and return
+// inline contents. (Note: this is not a method of InlineParser.)
+var parseRawLabel = function(s) {
+ // note: parse without a refmap; we don't want links to resolve
+ // in nested brackets!
+ return new InlineParser().parse(s.substr(1, s.length - 2), {});
+};
+
+// Attempt to parse a link. If successful, return the link.
+var parseLink = function(inlines) {
+ var startpos = this.pos;
+ var reflabel;
+ var n;
+ var dest;
+ var title;
+
+ n = this.parseLinkLabel();
+ if (n === 0) {
+ return false;
+ }
+ var afterlabel = this.pos;
+ var rawlabel = this.subject.substr(startpos, n);
+
+ // if we got this far, we've parsed a label.
+ // Try to parse an explicit link: [label](url "title")
+ if (this.peek() == C_OPEN_PAREN) {
+ this.pos++;
+ if (this.spnl() &&
+ ((dest = this.parseLinkDestination()) !== null) &&
+ this.spnl() &&
+ // make sure there's a space before the title:
+ (/^\s/.test(this.subject.charAt(this.pos - 1)) &&
+ (title = this.parseLinkTitle() || '') || true) &&
+ this.spnl() &&
+ this.match(/^\)/)) {
+ inlines.push({ t: 'Link',
+ destination: dest,
+ title: title,
+ label: parseRawLabel(rawlabel) });
+ return true;
+ } else {
+ this.pos = startpos;
+ return false;
+ }
+ }
+ // If we're here, it wasn't an explicit link. Try to parse a reference link.
+ // first, see if there's another label
+ var savepos = this.pos;
+ this.spnl();
+ var beforelabel = this.pos;
+ n = this.parseLinkLabel();
+ if (n == 2) {
+ // empty second label
+ reflabel = rawlabel;
+ } else if (n > 0) {
+ reflabel = this.subject.slice(beforelabel, beforelabel + n);
+ } else {
+ this.pos = savepos;
+ reflabel = rawlabel;
+ }
+ // lookup rawlabel in refmap
+ var link = this.refmap[normalizeReference(reflabel)];
+ if (link) {
+ inlines.push({t: 'Link',
+ destination: link.destination,
+ title: link.title,
+ label: parseRawLabel(rawlabel) });
+ return true;
+ } else {
+ this.pos = startpos;
+ return false;
+ }
+ // Nothing worked, rewind:
+ this.pos = startpos;
+ return false;
+};
+
+// Attempt to parse an entity, return Entity object if successful.
+var parseEntity = function(inlines) {
+ var m;
+ if ((m = this.match(reEntityHere))) {
+ inlines.push({ t: 'Str', c: entityToChar(m) });
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// Parse a run of ordinary characters, or a single character with
+// a special meaning in markdown, as a plain string, adding to inlines.
+var parseString = function(inlines) {
+ var m;
+ if ((m = this.match(reMain))) {
+ inlines.push({ t: 'Str', c: m });
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// Parse a newline. If it was preceded by two spaces, return a hard
+// line break; otherwise a soft line break.
+var parseNewline = function(inlines) {
+ var m = this.match(/^ *\n/);
+ if (m) {
+ if (m.length > 2) {
+ inlines.push({ t: 'Hardbreak' });
+ } else if (m.length > 0) {
+ inlines.push({ t: 'Softbreak' });
+ }
+ return true;
+ }
+ return false;
+};
+
+// Attempt to parse an image. If the opening '!' is not followed
+// by a link, return a literal '!'.
+var parseImage = function(inlines) {
+ if (this.match(/^!/)) {
+ var link = this.parseLink(inlines);
+ if (link) {
+ inlines[inlines.length - 1].t = 'Image';
+ return true;
+ } else {
+ inlines.push({ t: 'Str', c: '!' });
+ return true;
+ }
+ } else {
+ return false;
+ }
+};
+
+// Attempt to parse a link reference, modifying refmap.
+var parseReference = function(s, refmap) {
+ this.subject = s;
+ this.pos = 0;
+ this.label_nest_level = 0;
+ var rawlabel;
+ var dest;
+ var title;
+ var matchChars;
+ var startpos = this.pos;
+ var match;
+
+ // label:
+ matchChars = this.parseLinkLabel();
+ if (matchChars === 0) {
+ return 0;
+ } else {
+ rawlabel = this.subject.substr(0, matchChars);
+ }
+
+ // colon:
+ if (this.peek() === C_COLON) {
+ this.pos++;
+ } else {
+ this.pos = startpos;
+ return 0;
+ }
+
+ // link url
+ this.spnl();
+
+ dest = this.parseLinkDestination();
+ if (dest === null || dest.length === 0) {
+ this.pos = startpos;
+ return 0;
+ }
+
+ var beforetitle = this.pos;
+ this.spnl();
+ title = this.parseLinkTitle();
+ if (title === null) {
+ title = '';
+ // rewind before spaces
+ this.pos = beforetitle;
+ }
+
+ // make sure we're at line end:
+ if (this.match(/^ *(?:\n|$)/) === null) {
+ this.pos = startpos;
+ return 0;
+ }
+
+ var normlabel = normalizeReference(rawlabel);
+
+ if (!refmap[normlabel]) {
+ refmap[normlabel] = { destination: dest, title: title };
+ }
+ return this.pos - startpos;
+};
+
+// Parse the next inline element in subject, advancing subject position.
+// On success, add the result to the inlines list, and return true.
+// On failure, return false.
+var parseInline = function(inlines) {
+ var startpos = this.pos;
+ var origlen = inlines.length;
+
+ var c = this.peek();
+ if (c === -1) {
+ return false;
+ }
+ var res;
+ switch(c) {
+ case C_NEWLINE:
+ case C_SPACE:
+ res = this.parseNewline(inlines);
+ break;
+ case C_BACKSLASH:
+ res = this.parseBackslash(inlines);
+ break;
+ case C_BACKTICK:
+ res = this.parseBackticks(inlines);
+ break;
+ case C_ASTERISK:
+ case C_UNDERSCORE:
+ res = this.parseEmphasis(c, inlines);
+ break;
+ case C_OPEN_BRACKET:
+ res = this.parseLink(inlines);
+ break;
+ case C_BANG:
+ res = this.parseImage(inlines);
+ break;
+ case C_LESSTHAN:
+ res = this.parseAutolink(inlines) || this.parseHtmlTag(inlines);
+ break;
+ case C_AMPERSAND:
+ res = this.parseEntity(inlines);
+ break;
+ default:
+ res = this.parseString(inlines);
+ break;
+ }
+ if (!res) {
+ this.pos += 1;
+ inlines.push({t: 'Str', c: fromCodePoint(c)});
+ }
+
+ return true;
+};
+
+// Parse s as a list of inlines, using refmap to resolve references.
+var parseInlines = function(s, refmap) {
+ this.subject = s;
+ this.pos = 0;
+ this.refmap = refmap || {};
+ this.emphasis_openers = null;
+ var inlines = [];
+ while (this.parseInline(inlines)) {
+ }
+ return inlines;
+};
+
+// The InlineParser object.
+function InlineParser(){
+ return {
+ subject: '',
+ label_nest_level: 0, // used by parseLinkLabel method
+ emphasis_openers: null, // used by parseEmphasis method
+ pos: 0,
+ refmap: {},
+ match: match,
+ peek: peek,
+ spnl: spnl,
+ unescapeString: unescapeString,
+ parseBackticks: parseBackticks,
+ parseBackslash: parseBackslash,
+ parseAutolink: parseAutolink,
+ parseHtmlTag: parseHtmlTag,
+ scanDelims: scanDelims,
+ parseEmphasis: parseEmphasis,
+ parseLinkTitle: parseLinkTitle,
+ parseLinkDestination: parseLinkDestination,
+ parseLinkLabel: parseLinkLabel,
+ parseLink: parseLink,
+ parseEntity: parseEntity,
+ parseString: parseString,
+ parseNewline: parseNewline,
+ parseImage: parseImage,
+ parseReference: parseReference,
+ parseInline: parseInline,
+ parse: parseInlines
+ };
+}
+
+module.exports = InlineParser;
diff --git a/js/stmd.js b/js/stmd.js
deleted file mode 100755
index f7f48fd..0000000
--- a/js/stmd.js
+++ /dev/null
@@ -1,1547 +0,0 @@
-// stmd.js - CommonMark in javascript
-// Copyright (C) 2014 John MacFarlane
-// License: BSD3.
-
-// Basic usage:
-//
-// var stmd = require('stmd');
-// var parser = new stmd.DocParser();
-// var renderer = new stmd.HtmlRenderer();
-// console.log(renderer.render(parser.parse('Hello *world*')));
-
-(function(exports) {
-
-// Some regexps used in inline parser:
-
-var ESCAPABLE = '[!"#$%&\'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]';
-var ESCAPED_CHAR = '\\\\' + ESCAPABLE;
-var IN_DOUBLE_QUOTES = '"(' + ESCAPED_CHAR + '|[^"\\x00])*"';
-var IN_SINGLE_QUOTES = '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'';
-var IN_PARENS = '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\)';
-var REG_CHAR = '[^\\\\()\\x00-\\x20]';
-var IN_PARENS_NOSP = '\\((' + REG_CHAR + '|' + ESCAPED_CHAR + ')*\\)';
-var TAGNAME = '[A-Za-z][A-Za-z0-9]*';
-var BLOCKTAGNAME = '(?:article|header|aside|hgroup|iframe|blockquote|hr|body|li|map|button|object|canvas|ol|caption|output|col|p|colgroup|pre|dd|progress|div|section|dl|table|td|dt|tbody|embed|textarea|fieldset|tfoot|figcaption|th|figure|thead|footer|footer|tr|form|ul|h1|h2|h3|h4|h5|h6|video|script|style)';
-var ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
-var UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+";
-var SINGLEQUOTEDVALUE = "'[^']*'";
-var DOUBLEQUOTEDVALUE = '"[^"]*"';
-var ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")";
-var ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")";
-var ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)";
-var OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>";
-var CLOSETAG = "</" + TAGNAME + "\\s*[>]";
-var OPENBLOCKTAG = "<" + BLOCKTAGNAME + ATTRIBUTE + "*" + "\\s*/?>";
-var CLOSEBLOCKTAG = "</" + BLOCKTAGNAME + "\\s*[>]";
-var HTMLCOMMENT = "<!--([^-]+|[-][^-]+)*-->";
-var PROCESSINGINSTRUCTION = "[<][?].*?[?][>]";
-var DECLARATION = "<![A-Z]+" + "\\s+[^>]*>";
-var CDATA = "<!\\[CDATA\\[([^\\]]+|\\][^\\]]|\\]\\][^>])*\\]\\]>";
-var HTMLTAG = "(?:" + OPENTAG + "|" + CLOSETAG + "|" + HTMLCOMMENT + "|" +
- PROCESSINGINSTRUCTION + "|" + DECLARATION + "|" + CDATA + ")";
-var HTMLBLOCKOPEN = "<(?:" + BLOCKTAGNAME + "[\\s/>]" + "|" +
- "/" + BLOCKTAGNAME + "[\\s>]" + "|" + "[?!])";
-
-var reHtmlTag = new RegExp('^' + HTMLTAG, 'i');
-
-var reHtmlBlockOpen = new RegExp('^' + HTMLBLOCKOPEN, 'i');
-
-var reLinkTitle = new RegExp(
- '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' +
- '|' +
- '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'' +
- '|' +
- '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\))');
-
-var reLinkDestinationBraces = new RegExp(
- '^(?:[<](?:[^<>\\n\\\\\\x00]' + '|' + ESCAPED_CHAR + '|' + '\\\\)*[>])');
-
-var reLinkDestination = new RegExp(
- '^(?:' + REG_CHAR + '+|' + ESCAPED_CHAR + '|' + IN_PARENS_NOSP + ')*');
-
-var reEscapable = new RegExp(ESCAPABLE);
-
-var reAllEscapedChar = new RegExp('\\\\(' + ESCAPABLE + ')', 'g');
-
-var reEscapedChar = new RegExp('^\\\\(' + ESCAPABLE + ')');
-
-var reAllTab = /\t/g;
-
-var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/;
-
-// Matches a character with a special meaning in markdown,
-// or a string of non-special characters.
-var reMain = /^(?:[\n`\[\]\\!<&*_]|[^\n`\[\]\\!<&*_]+)/m;
-
-// UTILITY FUNCTIONS
-
-// Replace backslash escapes with literal characters.
-var unescape = function(s) {
- return s.replace(reAllEscapedChar, '$1');
-};
-
-// Returns true if string contains only space characters.
-var isBlank = function(s) {
- return /^\s*$/.test(s);
-};
-
-// Normalize reference label: collapse internal whitespace
-// to single space, remove leading/trailing whitespace, case fold.
-var normalizeReference = function(s) {
- return s.trim()
- .replace(/\s+/,' ')
- .toUpperCase();
-};
-
-// Attempt to match a regex in string s at offset offset.
-// Return index of match or null.
-var matchAt = function(re, s, offset) {
- var res = s.slice(offset).match(re);
- if (res) {
- return offset + res.index;
- } else {
- return null;
- }
-};
-
-// Convert tabs to spaces on each line using a 4-space tab stop.
-var detabLine = function(text) {
- if (text.indexOf('\t') == -1) {
- return text;
- } else {
- var lastStop = 0;
- return text.replace(reAllTab, function(match, offset) {
- var result = ' '.slice((offset - lastStop) % 4);
- lastStop = offset + 1;
- return result;
- });
- }
-};
-
-// INLINE PARSER
-
-// These are methods of an InlineParser object, defined below.
-// An InlineParser keeps track of a subject (a string to be
-// parsed) and a position in that subject.
-
-// If re matches at current position in the subject, advance
-// position in subject and return the match; otherwise return null.
-var match = function(re) {
- var match = re.exec(this.subject.slice(this.pos));
- if (match) {
- this.pos += match.index + match[0].length;
- return match[0];
- } else {
- return null;
- }
-};
-
-// Returns the character at the current subject position, or null if
-// there are no more characters.
-var peek = function() {
- return this.subject.charAt(this.pos) || null;
-};
-
-// Parse zero or more space characters, including at most one newline
-var spnl = function() {
- this.match(/^ *(?:\n *)?/);
- return 1;
-};
-
-// All of the parsers below try to match something at the current position
-// in the subject. If they succeed in matching anything, they
-// push an inline element onto the 'inlines' list. They return the
-// number of characters parsed (possibly 0).
-
-// Attempt to parse backticks, adding either a backtick code span or a
-// literal sequence of backticks to the 'inlines' list.
-var parseBackticks = function(inlines) {
- var startpos = this.pos;
- var ticks = this.match(/^`+/);
- if (!ticks) {
- return 0;
- }
- var afterOpenTicks = this.pos;
- var foundCode = false;
- var match;
- while (!foundCode && (match = this.match(/`+/m))) {
- if (match == ticks) {
- inlines.push({ t: 'Code', c: this.subject.slice(afterOpenTicks,
- this.pos - ticks.length)
- .replace(/[ \n]+/g,' ')
- .trim() });
- return (this.pos - startpos);
- }
- }
- // If we got here, we didn't match a closing backtick sequence.
- inlines.push({ t: 'Str', c: ticks });
- this.pos = afterOpenTicks;
- return (this.pos - startpos);
-};
-
-// Parse a backslash-escaped special character, adding either the escaped
-// character, a hard line break (if the backslash is followed by a newline),
-// or a literal backslash to the 'inlines' list.
-var parseEscaped = function(inlines) {
- var subj = this.subject,
- pos = this.pos;
- if (subj.charAt(pos) === '\\') {
- if (subj.charAt(pos + 1) === '\n') {
- inlines.push({ t: 'Hardbreak' });
- this.pos = this.pos + 2;
- return 2;
- } else if (reEscapable.test(subj.charAt(pos + 1))) {
- inlines.push({ t: 'Str', c: subj.charAt(pos + 1) });
- this.pos = this.pos + 2;
- return 2;
- } else {
- this.pos++;
- inlines.push({t: 'Str', c: '\\'});
- return 1;
- }
- } else {
- return 0;
- }
-};
-
-// Attempt to parse an autolink (URL or email in pointy brackets).
-var parseAutolink = function(inlines) {
- var m;
- var dest;
- if ((m = this.match(/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/))) { // email autolink
- dest = m.slice(1,-1);
- inlines.push({ t: 'Link', label: [{ t: 'Str', c: dest }],
- destination: 'mailto:' + dest });
- return m.length;
- } else if ((m = this.match(/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i))) {
- dest = m.slice(1,-1);
- inlines.push({ t: 'Link', label: [{ t: 'Str', c: dest }],
- destination: dest });
- return m.length;
- } else {
- return 0;
- }
-};
-
-// Attempt to parse a raw HTML tag.
-var parseHtmlTag = function(inlines) {
- var m = this.match(reHtmlTag);
- if (m) {
- inlines.push({ t: 'Html', c: m });
- return m.length;
- } else {
- return 0;
- }
-};
-
-// Scan a sequence of characters == c, and return information about
-// the number of delimiters and whether they are positioned such that
-// they can open and/or close emphasis or strong emphasis. A utility
-// function for strong/emph parsing.
-var scanDelims = function(c) {
- var numdelims = 0;
- var first_close_delims = 0;
- var char_before, char_after;
- var startpos = this.pos;
-
- char_before = this.pos === 0 ? '\n' :
- this.subject.charAt(this.pos - 1);
-
- while (this.peek() === c) {
- numdelims++;
- this.pos++;
- }
-
- char_after = this.peek() || '\n';
-
- var can_open = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_after));
- var can_close = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_before));
- if (c === '_') {
- can_open = can_open && !((/[a-z0-9]/i).test(char_before));
- can_close = can_close && !((/[a-z0-9]/i).test(char_after));
- }
- this.pos = startpos;
- return { numdelims: numdelims,
- can_open: can_open,
- can_close: can_close };
-};
-
-// Attempt to parse emphasis or strong emphasis in an efficient way,
-// with no backtracking.
-var parseEmphasis = function(inlines) {
- var startpos = this.pos;
- var c ;
- var first_close = 0;
- var nxt = this.peek();
- if (nxt == '*' || nxt == '_') {
- c = nxt;
- } else {
- return 0;
- }
-
- var numdelims;
- var delimpos;
-
- // Get opening delimiters.
- res = this.scanDelims(c);
- numdelims = res.numdelims;
- this.pos += numdelims;
- // We provisionally add a literal string. If we match appropriate
- // closing delimiters, we'll change this to Strong or Emph.
- inlines.push({t: 'Str',
- c: this.subject.substr(this.pos - numdelims, numdelims)});
- // Record the position of this opening delimiter:
- delimpos = inlines.length - 1;
-
- if (!res.can_open || numdelims === 0) {
- return 0;
- }
-
- var first_close_delims = 0;
-
- switch (numdelims) {
- case 1: // we started with * or _
- while (true) {
- res = this.scanDelims(c);
- if (res.numdelims >= 1 && res.can_close) {
- this.pos += 1;
- // Convert the inline at delimpos, currently a string with the delim,
- // into an Emph whose contents are the succeeding inlines
- inlines[delimpos].t = 'Emph';
- inlines[delimpos].c = inlines.slice(delimpos + 1);
- inlines.splice(delimpos + 1, inlines.length - delimpos - 1);
- break;
- } else {
- if (this.parseInline(inlines) === 0) {
- break;
- }
- }
- }
- return (this.pos - startpos);
-
- case 2: // We started with ** or __
- while (true) {
- res = this.scanDelims(c);
- if (res.numdelims >= 2 && res.can_close) {
- this.pos += 2;
- inlines[delimpos].t = 'Strong';
- inlines[delimpos].c = inlines.slice(delimpos + 1);
- inlines.splice(delimpos + 1, inlines.length - delimpos - 1);
- break;
- } else {
- if (this.parseInline(inlines) === 0) {
- break;
- }
- }
- }
- return (this.pos - startpos);
-
- case 3: // We started with *** or ___
- while (true) {
- res = this.scanDelims(c);
- if (res.numdelims >= 1 && res.numdelims <= 3 && res.can_close &&
- res.numdelims != first_close_delims) {
-
- if (first_close_delims === 1 && numdelims > 2) {
- res.numdelims = 2;
- } else if (first_close_delims === 2) {
- res.numdelims = 1;
- } else if (res.numdelims === 3) {
- // If we opened with ***, then we interpret *** as ** followed by *
- // giving us <strong><em>
- res.numdelims = 1;
- }
-
- this.pos += res.numdelims;
-
- if (first_close > 0) { // if we've already passed the first closer:
- inlines[delimpos].t = first_close_delims === 1 ? 'Strong' : 'Emph';
- inlines[delimpos].c = [
- { t: first_close_delims === 1 ? 'Emph' : 'Strong',
- c: inlines.slice(delimpos + 1, first_close)}
- ].concat(inlines.slice(first_close + 1));
- inlines.splice(delimpos + 1);
- break;
- } else { // this is the first closer; for now, add literal string;
- // we'll change this when he hit the second closer
- inlines.push({t: 'Str',
- c: this.subject.slice(this.pos - res.numdelims,
- this.pos) });
- first_close = inlines.length - 1;
- first_close_delims = res.numdelims;
- }
- } else { // parse another inline element, til we hit the end
- if (this.parseInline(inlines) === 0) {
- break;
- }
- }
- }
- return (this.pos - startpos);
-
- default:
- return res;
- }
-
- return 0;
-};
-
-// Attempt to parse link title (sans quotes), returning the string
-// or null if no match.
-var parseLinkTitle = function() {
- var title = this.match(reLinkTitle);
- if (title) {
- // chop off quotes from title and unescape:
- return unescape(title.substr(1, title.length - 2));
- } else {
- return null;
- }
-};
-
-// Attempt to parse link destination, returning the string or
-// null if no match.
-var parseLinkDestination = function() {
- var res = this.match(reLinkDestinationBraces);
- if (res) { // chop off surrounding <..>:
- return unescape(res.substr(1, res.length - 2));
- } else {
- res = this.match(reLinkDestination);
- if (res !== null) {
- return unescape(res);
- } else {
- return null;
- }
- }
-};
-
-// Attempt to parse a link label, returning number of characters parsed.
-var parseLinkLabel = function() {
- if (this.peek() != '[') {
- return 0;
- }
- var startpos = this.pos;
- var nest_level = 0;
- if (this.label_nest_level > 0) {
- // If we've already checked to the end of this subject
- // for a label, even with a different starting [, we
- // know we won't find one here and we can just return.
- // This avoids lots of backtracking.
- // Note: nest level 1 would be: [foo [bar]
- // nest level 2 would be: [foo [bar [baz]
- this.label_nest_level--;
- return 0;
- }
- this.pos++; // advance past [
- var c;
- while ((c = this.peek()) && (c != ']' || nest_level > 0)) {
- switch (c) {
- case '`':
- this.parseBackticks([]);
- break;
- case '<':
- this.parseAutolink([]) || this.parseHtmlTag([]) || this.parseString([]);
- break;
- case '[': // nested []
- nest_level++;
- this.pos++;
- break;
- case ']': // nested []
- nest_level--;
- this.pos++;
- break;
- case '\\':
- this.parseEscaped([]);
- break;
- default:
- this.parseString([]);
- }
- }
- if (c === ']') {
- this.label_nest_level = 0;
- this.pos++; // advance past ]
- return this.pos - startpos;
- } else {
- if (!c) {
- this.label_nest_level = nest_level;
- }
- this.pos = startpos;
- return 0;
- }
-};
-
-// Parse raw link label, including surrounding [], and return
-// inline contents. (Note: this is not a method of InlineParser.)
-var parseRawLabel = function(s) {
- // note: parse without a refmap; we don't want links to resolve
- // in nested brackets!
- return new InlineParser().parse(s.substr(1, s.length - 2), {});
-};
-
-// Attempt to parse a link. If successful, add the link to
-// inlines.
-var parseLink = function(inlines) {
- var startpos = this.pos;
- var reflabel;
- var n;
- var dest;
- var title;
-
- n = this.parseLinkLabel();
- if (n === 0) {
- return 0;
- }
- var afterlabel = this.pos;
- var rawlabel = this.subject.substr(startpos, n);
-
- // if we got this far, we've parsed a label.
- // Try to parse an explicit link: [label](url "title")
- if (this.peek() == '(') {
- this.pos++;
- if (this.spnl() &&
- ((dest = this.parseLinkDestination()) !== null) &&
- this.spnl() &&
- // make sure there's a space before the title:
- (/^\s/.test(this.subject.charAt(this.pos - 1)) &&
- (title = this.parseLinkTitle() || '') || true) &&
- this.spnl() &&
- this.match(/^\)/)) {
- inlines.push({ t: 'Link',
- destination: dest,
- title: title,
- label: parseRawLabel(rawlabel) });
- return this.pos - startpos;
- } else {
- this.pos = startpos;
- return 0;
- }
- }
- // If we're here, it wasn't an explicit link. Try to parse a reference link.
- // first, see if there's another label
- var savepos = this.pos;
- this.spnl();
- var beforelabel = this.pos;
- n = this.parseLinkLabel();
- if (n == 2) {
- // empty second label
- reflabel = rawlabel;
- } else if (n > 0) {
- reflabel = this.subject.slice(beforelabel, beforelabel + n);
- } else {
- this.pos = savepos;
- reflabel = rawlabel;
- }
- // lookup rawlabel in refmap
- var link = this.refmap[normalizeReference(reflabel)];
- if (link) {
- inlines.push({t: 'Link',
- destination: link.destination,
- title: link.title,
- label: parseRawLabel(rawlabel) });
- return this.pos - startpos;
- } else {
- this.pos = startpos;
- return 0;
- }
- // Nothing worked, rewind:
- this.pos = startpos;
- return 0;
-};
-
-// Attempt to parse an entity, adding to inlines if successful.
-var parseEntity = function(inlines) {
- var m;
- if ((m = this.match(/^&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});/i))) {
- inlines.push({ t: 'Entity', c: m });
- return m.length;
- } else {
- return 0;
- }
-};
-
-// Parse a run of ordinary characters, or a single character with
-// a special meaning in markdown, as a plain string, adding to inlines.
-var parseString = function(inlines) {
- var m;
- if ((m = this.match(reMain))) {
- inlines.push({ t: 'Str', c: m });
- return m.length;
- } else {
- return 0;
- }
-};
-
-// Parse a newline. If it was preceded by two spaces, return a hard
-// line break; otherwise a soft line break.
-var parseNewline = function(inlines) {
- if (this.peek() == '\n') {
- this.pos++;
- var last = inlines[inlines.length - 1];
- if (last && last.t == 'Str' && last.c.slice(-2) == ' ') {
- last.c = last.c.replace(/ *$/,'');
- inlines.push({ t: 'Hardbreak' });
- } else {
- if (last && last.t == 'Str' && last.c.slice(-1) == ' ') {
- last.c = last.c.slice(0, -1);
- }
- inlines.push({ t: 'Softbreak' });
- }
- return 1;
- } else {
- return 0;
- }
-};
-
-// Attempt to parse an image. If the opening '!' is not followed
-// by a link, add a literal '!' to inlines.
-var parseImage = function(inlines) {
- if (this.match(/^!/)) {
- var n = this.parseLink(inlines);
- if (n === 0) {
- inlines.push({ t: 'Str', c: '!' });
- return 1;
- } else if (inlines[inlines.length - 1] &&
- inlines[inlines.length - 1].t == 'Link') {
- inlines[inlines.length - 1].t = 'Image';
- return n+1;
- } else {
- throw "Shouldn't happen";
- }
- } else {
- return 0;
- }
-};
-
-// Attempt to parse a link reference, modifying refmap.
-var parseReference = function(s, refmap) {
- this.subject = s;
- this.pos = 0;
- var rawlabel;
- var dest;
- var title;
- var matchChars;
- var startpos = this.pos;
- var match;
-
- // label:
- matchChars = this.parseLinkLabel();
- if (matchChars === 0) {
- return 0;
- } else {
- rawlabel = this.subject.substr(0, matchChars);
- }
-
- // colon:
- if (this.peek() === ':') {
- this.pos++;
- } else {
- this.pos = startpos;
- return 0;
- }
-
- // link url
- this.spnl();
-
- dest = this.parseLinkDestination();
- if (dest === null || dest.length === 0) {
- this.pos = startpos;
- return 0;
- }
-
- var beforetitle = this.pos;
- this.spnl();
- title = this.parseLinkTitle();
- if (title === null) {
- title = '';
- // rewind before spaces
- this.pos = beforetitle;
- }
-
- // make sure we're at line end:
- if (this.match(/^ *(?:\n|$)/) === null) {
- this.pos = startpos;
- return 0;
- }
-
- var normlabel = normalizeReference(rawlabel);
-
- if (!refmap[normlabel]) {
- refmap[normlabel] = { destination: dest, title: title };
- }
- return this.pos - startpos;
-};
-
-// Parse the next inline element in subject, advancing subject position
-// and adding the result to 'inlines'.
-var parseInline = function(inlines) {
- var c = this.peek();
- var res;
- switch(c) {
- case '\n':
- res = this.parseNewline(inlines);
- break;
- case '\\':
- res = this.parseEscaped(inlines);
- break;
- case '`':
- res = this.parseBackticks(inlines);
- break;
- case '*':
- case '_':
- res = this.parseEmphasis(inlines);
- break;
- case '[':
- res = this.parseLink(inlines);
- break;
- case '!':
- res = this.parseImage(inlines);
- break;
- case '<':
- res = this.parseAutolink(inlines) ||
- this.parseHtmlTag(inlines);
- break;
- case '&':
- res = this.parseEntity(inlines);
- break;
- default:
- }
- return res || this.parseString(inlines);
-};
-
-// Parse s as a list of inlines, using refmap to resolve references.
-var parseInlines = function(s, refmap) {
- this.subject = s;
- this.pos = 0;
- this.refmap = refmap || {};
- var inlines = [];
- while (this.parseInline(inlines)) ;
- return inlines;
-};
-
-// The InlineParser object.
-function InlineParser(){
- return {
- subject: '',
- label_nest_level: 0, // used by parseLinkLabel method
- pos: 0,
- refmap: {},
- match: match,
- peek: peek,
- spnl: spnl,
- parseBackticks: parseBackticks,
- parseEscaped: parseEscaped,
- parseAutolink: parseAutolink,
- parseHtmlTag: parseHtmlTag,
- scanDelims: scanDelims,
- parseEmphasis: parseEmphasis,
- parseLinkTitle: parseLinkTitle,
- parseLinkDestination: parseLinkDestination,
- parseLinkLabel: parseLinkLabel,
- parseLink: parseLink,
- parseEntity: parseEntity,
- parseString: parseString,
- parseNewline: parseNewline,
- parseImage: parseImage,
- parseReference: parseReference,
- parseInline: parseInline,
- parse: parseInlines
- };
-}
-
-// DOC PARSER
-
-// These are methods of a DocParser object, defined below.
-
-var makeBlock = function(tag, start_line, start_column) {
- return { t: tag,
- open: true,
- last_line_blank: false,
- start_line: start_line,
- start_column: start_column,
- end_line: start_line,
- children: [],
- parent: null,
- // string_content is formed by concatenating strings, in finalize:
- string_content: "",
- strings: [],
- inline_content: []
- };
-};
-
-// Returns true if parent block can contain child block.
-var canContain = function(parent_type, child_type) {
- return ( parent_type == 'Document' ||
- parent_type == 'BlockQuote' ||
- parent_type == 'ListItem' ||
- (parent_type == 'List' && child_type == 'ListItem') );
-};
-
-// Returns true if block type can accept lines of text.
-var acceptsLines = function(block_type) {
- return ( block_type == 'Paragraph' ||
- block_type == 'IndentedCode' ||
- block_type == 'FencedCode' );
-};
-
-// Returns true if block ends with a blank line, descending if needed
-// into lists and sublists.
-var endsWithBlankLine = function(block) {
- if (block.last_line_blank) {
- return true;
- }
- if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) {
- return endsWithBlankLine(block.children[block.children.length - 1]);
- } else {
- return false;
- }
-};
-
-// Break out of all containing lists, resetting the tip of the
-// document to the parent of the highest list, and finalizing
-// all the lists. (This is used to implement the "two blank lines
-// break of of all lists" feature.)
-var breakOutOfLists = function(block, line_number) {
- var b = block;
- var last_list = null;
- do {
- if (b.t === 'List') {
- last_list = b;
- }
- b = b.parent;
- } while (b);
-
- if (last_list) {
- while (block != last_list) {
- this.finalize(block, line_number);
- block = block.parent;
- }
- this.finalize(last_list, line_number);
- this.tip = last_list.parent;
- }
-};
-
-// Add a line to the block at the tip. We assume the tip
-// can accept lines -- that check should be done before calling this.
-var addLine = function(ln, offset) {
- var s = ln.slice(offset);
- if (!(this.tip.open)) {
- throw({ msg: "Attempted to add line (" + ln + ") to closed container." });
- }
- this.tip.strings.push(s);
-};
-
-// Add block of type tag as a child of the tip. If the tip can't
-// accept children, close and finalize it and try its parent,
-// and so on til we find a block that can accept children.
-var addChild = function(tag, line_number, offset) {
- while (!canContain(this.tip.t, tag)) {
- this.finalize(this.tip, line_number);
- }
-
- var column_number = offset + 1; // offset 0 = column 1
- var newBlock = makeBlock(tag, line_number, column_number);
- this.tip.children.push(newBlock);
- newBlock.parent = this.tip;
- this.tip = newBlock;
- return newBlock;
-};
-
-// Parse a list marker and return data on the marker (type,
-// start, delimiter, bullet character, padding) or null.
-var parseListMarker = function(ln, offset) {
- var rest = ln.slice(offset);
- var match;
- var spaces_after_marker;
- var data = {};
- if (rest.match(reHrule)) {
- return null;
- }
- if ((match = rest.match(/^[*+-]( +|$)/))) {
- spaces_after_marker = match[1].length;
- data.type = 'Bullet';
- data.bullet_char = match[0].charAt(0);
-
- } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) {
- spaces_after_marker = match[3].length;
- data.type = 'Ordered';
- data.start = parseInt(match[1]);
- data.delimiter = match[2];
- } else {
- return null;
- }
- var blank_item = match[0].length === rest.length;
- if (spaces_after_marker >= 5 ||
- spaces_after_marker < 1 ||
- blank_item) {
- data.padding = match[0].length - spaces_after_marker + 1;
- } else {
- data.padding = match[0].length;
- }
- return data;
-};
-
-// Returns true if the two list items are of the same type,
-// with the same delimiter and bullet character. This is used
-// in agglomerating list items into lists.
-var listsMatch = function(list_data, item_data) {
- return (list_data.type === item_data.type &&
- list_data.delimiter === item_data.delimiter &&
- list_data.bullet_char === item_data.bullet_char);
-};
-
-// Analyze a line of text and update the document appropriately.
-// We parse markdown text by calling this on each line of input,
-// then finalizing the document.
-var incorporateLine = function(ln, line_number) {
-
- var all_matched = true;
- var last_child;
- var first_nonspace;
- var offset = 0;
- var match;
- var data;
- var blank;
- var indent;
- var last_matched_container;
- var i;
- var CODE_INDENT = 4;
-
- var container = this.doc;
- var oldtip = this.tip;
-
- // Convert tabs to spaces:
- ln = detabLine(ln);
-
- // For each containing block, try to parse the associated line start.
- // Bail out on failure: container will point to the last matching block.
- // Set all_matched to false if not all containers match.
- while (container.children.length > 0) {
- last_child = container.children[container.children.length - 1];
- if (!last_child.open) {
- break;
- }
- container = last_child;
-
- match = matchAt(/[^ ]/, ln, offset);
- if (match === null) {
- first_nonspace = ln.length;
- blank = true;
- } else {
- first_nonspace = match;
- blank = false;
- }
- indent = first_nonspace - offset;
-
- switch (container.t) {
- case 'BlockQuote':
- var matched = indent <= 3 && ln.charAt(first_nonspace) === '>';
- if (matched) {
- offset = first_nonspace + 1;
- if (ln.charAt(offset) === ' ') {
- offset++;
- }
- } else {
- all_matched = false;
- }
- break;
-
- case 'ListItem':
- if (indent >= container.list_data.marker_offset +
- container.list_data.padding) {
- offset += container.list_data.marker_offset +
- container.list_data.padding;
- } else if (blank) {
- offset = first_nonspace;
- } else {
- all_matched = false;
- }
- break;
-
- case 'IndentedCode':
- if (indent >= CODE_INDENT) {
- offset += CODE_INDENT;
- } else if (blank) {
- offset = first_nonspace;
- } else {
- all_matched = false;
- }
- break;
-
- case 'ATXHeader':
- case 'SetextHeader':
- case 'HorizontalRule':
- // a header can never container > 1 line, so fail to match:
- all_matched = false;
- break;
-
- case 'FencedCode':
- // skip optional spaces of fence offset
- i = container.fence_offset;
- while (i > 0 && ln.charAt(offset) === ' ') {
- offset++;
- i--;
- }
- break;
-
- case 'HtmlBlock':
- if (blank) {
- all_matched = false;
- }
- break;
-
- case 'Paragraph':
- if (blank) {
- container.last_line_blank = true;
- all_matched = false;
- }
- break;
-
- default:
- }
-
- if (!all_matched) {
- container = container.parent; // back up to last matching block
- break;
- }
- }
-
- last_matched_container = container;
-
- // This function is used to finalize and close any unmatched
- // blocks. We aren't ready to do this now, because we might
- // have a lazy paragraph continuation, in which case we don't
- // want to close unmatched blocks. So we store this closure for
- // use later, when we have more information.
- var closeUnmatchedBlocks = function(mythis) {
- // finalize any blocks not matched
- while (!already_done && oldtip != last_matched_container) {
- mythis.finalize(oldtip, line_number);
- oldtip = oldtip.parent;
- }
- var already_done = true;
- };
-
- // Check to see if we've hit 2nd blank line; if so break out of list:
- if (blank && container.last_line_blank) {
- this.breakOutOfLists(container, line_number);
- }
-
- // Unless last matched container is a code block, try new container starts,
- // adding children to the last matched container:
- while (container.t != 'FencedCode' &&
- container.t != 'IndentedCode' &&
- container.t != 'HtmlBlock' &&
- // this is a little performance optimization:
- matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) {
-
- match = matchAt(/[^ ]/, ln, offset);
- if (match === null) {
- first_nonspace = ln.length;
- blank = true;
- } else {
- first_nonspace = match;
- blank = false;
- }
- indent = first_nonspace - offset;
-
- if (indent >= CODE_INDENT) {
- // indented code
- if (this.tip.t != 'Paragraph' && !blank) {
- offset += CODE_INDENT;
- closeUnmatchedBlocks(this);
- container = this.addChild('IndentedCode', line_number, offset);
- } else { // indent > 4 in a lazy paragraph continuation
- break;
- }
-
- } else if (ln.charAt(first_nonspace) === '>') {
- // blockquote
- offset = first_nonspace + 1;
- // optional following space
- if (ln.charAt(offset) === ' ') {
- offset++;
- }
- closeUnmatchedBlocks(this);
- container = this.addChild('BlockQuote', line_number, offset);
-
- } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) {
- // ATX header
- offset = first_nonspace + match[0].length;
- closeUnmatchedBlocks(this);
- container = this.addChild('ATXHeader', line_number, first_nonspace);
- container.level = match[0].trim().length; // number of #s
- // remove trailing ###s:
- container.strings =
- [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')];
- break;
-
- } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) {
- // fenced code block
- var fence_length = match[0].length;
- closeUnmatchedBlocks(this);
- container = this.addChild('FencedCode', line_number, first_nonspace);
- container.fence_length = fence_length;
- container.fence_char = match[0].charAt(0);
- container.fence_offset = first_nonspace - offset;
- offset = first_nonspace + fence_length;
- break;
-
- } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) {
- // html block
- closeUnmatchedBlocks(this);
- container = this.addChild('HtmlBlock', line_number, first_nonspace);
- // note, we don't adjust offset because the tag is part of the text
- break;
-
- } else if (container.t == 'Paragraph' &&
- container.strings.length === 1 &&
- ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) {
- // setext header line
- closeUnmatchedBlocks(this);
- container.t = 'SetextHeader'; // convert Paragraph to SetextHeader
- container.level = match[0].charAt(0) === '=' ? 1 : 2;
- offset = ln.length;
-
- } else if (matchAt(reHrule, ln, first_nonspace) !== null) {
- // hrule
- closeUnmatchedBlocks(this);
- container = this.addChild('HorizontalRule', line_number, first_nonspace);
- offset = ln.length - 1;
- break;
-
- } else if ((data = parseListMarker(ln, first_nonspace))) {
- // list item
- closeUnmatchedBlocks(this);
- data.marker_offset = indent;
- offset = first_nonspace + data.padding;
-
- // add the list if needed
- if (container.t !== 'List' ||
- !(listsMatch(container.list_data, data))) {
- container = this.addChild('List', line_number, first_nonspace);
- container.list_data = data;
- }
-
- // add the list item
- container = this.addChild('ListItem', line_number, first_nonspace);
- container.list_data = data;
-
- } else {
- break;
-
- }
-
- if (acceptsLines(container.t)) {
- // if it's a line container, it can't contain other containers
- break;
- }
- }
-
- // What remains at the offset is a text line. Add the text to the
- // appropriate container.
-
- match = matchAt(/[^ ]/, ln, offset);
- if (match === null) {
- first_nonspace = ln.length;
- blank = true;
- } else {
- first_nonspace = match;
- blank = false;
- }
- indent = first_nonspace - offset;
-
- // First check for a lazy paragraph continuation:
- if (this.tip !== last_matched_container &&
- !blank &&
- this.tip.t == 'Paragraph' &&
- this.tip.strings.length > 0) {
- // lazy paragraph continuation
-
- this.last_line_blank = false;
- this.addLine(ln, offset);
-
- } else { // not a lazy continuation
-
- // finalize any blocks not matched
- closeUnmatchedBlocks(this);
-
- // Block quote lines are never blank as they start with >
- // and we don't count blanks in fenced code for purposes of tight/loose
- // lists or breaking out of lists. We also don't set last_line_blank
- // on an empty list item.
- container.last_line_blank = blank &&
- !(container.t == 'BlockQuote' ||
- container.t == 'FencedCode' ||
- (container.t == 'ListItem' &&
- container.children.length === 0 &&
- container.start_line == line_number));
-
- var cont = container;
- while (cont.parent) {
- cont.parent.last_line_blank = false;
- cont = cont.parent;
- }
-
- switch (container.t) {
- case 'IndentedCode':
- case 'HtmlBlock':
- this.addLine(ln, offset);
- break;
-
- case 'FencedCode':
- // check for closing code fence:
- match = (indent <= 3 &&
- ln.charAt(first_nonspace) == container.fence_char &&
- ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/));
- if (match && match[0].length >= container.fence_length) {
- // don't add closing fence to container; instead, close it:
- this.finalize(container, line_number);
- } else {
- this.addLine(ln, offset);
- }
- break;
-
- case 'ATXHeader':
- case 'SetextHeader':
- case 'HorizontalRule':
- // nothing to do; we already added the contents.
- break;
-
- default:
- if (acceptsLines(container.t)) {
- this.addLine(ln, first_nonspace);
- } else if (blank) {
- // do nothing
- } else if (container.t != 'HorizontalRule' &&
- container.t != 'SetextHeader') {
- // create paragraph container for line
- container = this.addChild('Paragraph', line_number, first_nonspace);
- this.addLine(ln, first_nonspace);
- } else {
- console.log("Line " + line_number.toString() +
- " with container type " + container.t +
- " did not match any condition.");
-
- }
- }
- }
-};
-
-// Finalize a block. Close it and do any necessary postprocessing,
-// e.g. creating string_content from strings, setting the 'tight'
-// or 'loose' status of a list, and parsing the beginnings
-// of paragraphs for reference definitions. Reset the tip to the
-// parent of the closed block.
-var finalize = function(block, line_number) {
- var pos;
- // don't do anything if the block is already closed
- if (!block.open) {
- return 0;
- }
- block.open = false;
- if (line_number > block.start_line) {
- block.end_line = line_number - 1;
- } else {
- block.end_line = line_number;
- }
-
- switch (block.t) {
- case 'Paragraph':
- block.string_content = block.strings.join('\n').replace(/^ */m,'');
-
- // try parsing the beginning as link reference definitions:
- while (block.string_content.charAt(0) === '[' &&
- (pos = this.inlineParser.parseReference(block.string_content,
- this.refmap))) {
- block.string_content = block.string_content.slice(pos);
- if (isBlank(block.string_content)) {
- block.t = 'ReferenceDef';
- break;
- }
- }
- break;
-
- case 'ATXHeader':
- case 'SetextHeader':
- case 'HtmlBlock':
- block.string_content = block.strings.join('\n');
- break;
-
- case 'IndentedCode':
- block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n');
- break;
-
- case 'FencedCode':
- // first line becomes info string
- block.info = unescape(block.strings[0].trim());
- if (block.strings.length == 1) {
- block.string_content = '';
- } else {
- block.string_content = block.strings.slice(1).join('\n') + '\n';
- }
- break;
-
- case 'List':
- block.tight = true; // tight by default
-
- var numitems = block.children.length;
- var i = 0;
- while (i < numitems) {
- var item = block.children[i];
- // check for non-final list item ending with blank line:
- var last_item = i == numitems - 1;
- if (endsWithBlankLine(item) && !last_item) {
- block.tight = false;
- break;
- }
- // recurse into children of list item, to see if there are
- // spaces between any of them:
- var numsubitems = item.children.length;
- var j = 0;
- while (j < numsubitems) {
- var subitem = item.children[j];
- var last_subitem = j == numsubitems - 1;
- if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) {
- block.tight = false;
- break;
- }
- j++;
- }
- i++;
- }
- break;
-
- default:
- break;
- }
-
- this.tip = block.parent || this.top;
-};
-
-// Walk through a block & children recursively, parsing string content
-// into inline content where appropriate.
-var processInlines = function(block) {
- switch(block.t) {
- case 'Paragraph':
- case 'SetextHeader':
- case 'ATXHeader':
- block.inline_content =
- this.inlineParser.parse(block.string_content.trim(), this.refmap);
- block.string_content = "";
- break;
- default:
- break;
- }
-
- if (block.children) {
- for (var i = 0; i < block.children.length; i++) {
- this.processInlines(block.children[i]);
- }
- }
-
-};
-
-// The main parsing function. Returns a parsed document AST.
-var parse = function(input) {
- this.doc = makeBlock('Document', 1, 1);
- this.tip = this.doc;
- this.refmap = {};
- var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/);
- var len = lines.length;
- for (var i = 0; i < len; i++) {
- this.incorporateLine(lines[i], i+1);
- }
- while (this.tip) {
- this.finalize(this.tip, len - 1);
- }
- this.processInlines(this.doc);
- return this.doc;
-};
-
-
-// The DocParser object.
-function DocParser(){
- return {
- doc: makeBlock('Document', 1, 1),
- tip: this.doc,
- refmap: {},
- inlineParser: new InlineParser(),
- breakOutOfLists: breakOutOfLists,
- addLine: addLine,
- addChild: addChild,
- incorporateLine: incorporateLine,
- finalize: finalize,
- processInlines: processInlines,
- parse: parse
- };
-}
-
-// HTML RENDERER
-
-// Helper function to produce content in a pair of HTML tags.
-var inTags = function(tag, attribs, contents, selfclosing) {
- var result = '<' + tag;
- if (attribs) {
- var i = 0;
- var attrib;
- while ((attrib = attribs[i]) !== undefined) {
- result = result.concat(' ', attrib[0], '="', attrib[1], '"');
- i++;
- }
- }
- if (contents) {
- result = result.concat('>', contents, '</', tag, '>');
- } else if (selfclosing) {
- result = result + ' />';
- } else {
- result = result.concat('></', tag, '>');
- }
- return result;
-};
-
-// Render an inline element as HTML.
-var renderInline = function(inline) {
- var attrs;
- switch (inline.t) {
- case 'Str':
- return this.escape(inline.c);
- case 'Softbreak':
- return this.softbreak;
- case 'Hardbreak':
- return inTags('br',[],"",true) + '\n';
- case 'Emph':
- return inTags('em', [], this.renderInlines(inline.c));
- case 'Strong':
- return inTags('strong', [], this.renderInlines(inline.c));
- case 'Html':
- return inline.c;
- case 'Entity':
- return inline.c;
- case 'Link':
- attrs = [['href', this.escape(inline.destination, true)]];
- if (inline.title) {
- attrs.push(['title', this.escape(inline.title, true)]);
- }
- return inTags('a', attrs, this.renderInlines(inline.label));
- case 'Image':
- attrs = [['src', this.escape(inline.destination, true)],
- ['alt', this.escape(this.renderInlines(inline.label))]];
- if (inline.title) {
- attrs.push(['title', this.escape(inline.title, true)]);
- }
- return inTags('img', attrs, "", true);
- case 'Code':
- return inTags('code', [], this.escape(inline.c));
- default:
- console.log("Uknown inline type " + inline.t);
- return "";
- }
-};
-
-// Render a list of inlines.
-var renderInlines = function(inlines) {
- var result = '';
- for (var i=0; i < inlines.length; i++) {
- result = result + this.renderInline(inlines[i]);
- }
- return result;
-};
-
-// Render a single block element.
-var renderBlock = function(block, in_tight_list) {
- var tag;
- var attr;
- var info_words;
- switch (block.t) {
- case 'Document':
- var whole_doc = this.renderBlocks(block.children);
- return (whole_doc === '' ? '' : whole_doc + '\n');
- case 'Paragraph':
- if (in_tight_list) {
- return this.renderInlines(block.inline_content);
- } else {
- return inTags('p', [], this.renderInlines(block.inline_content));
- }
- break;
- case 'BlockQuote':
- var filling = this.renderBlocks(block.children);
- return inTags('blockquote', [], filling === '' ? this.innersep :
- this.innersep + this.renderBlocks(block.children) + this.innersep);
- case 'ListItem':
- return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim());
- case 'List':
- tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol';
- attr = (!block.list_data.start || block.list_data.start == 1) ?
- [] : [['start', block.list_data.start.toString()]];
- return inTags(tag, attr, this.innersep +
- this.renderBlocks(block.children, block.tight) +
- this.innersep);
- case 'ATXHeader':
- case 'SetextHeader':
- tag = 'h' + block.level;
- return inTags(tag, [], this.renderInlines(block.inline_content));
- case 'IndentedCode':
- return inTags('pre', [],
- inTags('code', [], this.escape(block.string_content)));
- case 'FencedCode':
- info_words = block.info.split(/ +/);
- attr = info_words.length === 0 || info_words[0].length === 0 ?
- [] : [['class','language-' +
- this.escape(info_words[0],true)]];
- return inTags('pre', [],
- inTags('code', attr, this.escape(block.string_content)));
- case 'HtmlBlock':
- return block.string_content;
- case 'ReferenceDef':
- return "";
- case 'HorizontalRule':
- return inTags('hr',[],"",true);
- default:
- console.log("Uknown block type " + block.t);
- return "";
- }
-};
-
-// Render a list of block elements, separated by this.blocksep.
-var renderBlocks = function(blocks, in_tight_list) {
- var result = [];
- for (var i=0; i < blocks.length; i++) {
- if (blocks[i].t !== 'ReferenceDef') {
- result.push(this.renderBlock(blocks[i], in_tight_list));
- }
- }
- return result.join(this.blocksep);
-};
-
-// The HtmlRenderer object.
-function HtmlRenderer(){
- return {
- // default options:
- blocksep: '\n', // space between blocks
- innersep: '\n', // space between block container tag and contents
- softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML
- // set to "<br />" to make them hard breaks
- // set to " " if you want to ignore line wrapping in source
- escape: function(s, preserve_entities) {
- if (preserve_entities) {
- return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&amp;')
- .replace(/[<]/g,'&lt;')
- .replace(/[>]/g,'&gt;')
- .replace(/["]/g,'&quot;');
- } else {
- return s.replace(/[&]/g,'&amp;')
- .replace(/[<]/g,'&lt;')
- .replace(/[>]/g,'&gt;')
- .replace(/["]/g,'&quot;');
- }
- },
- renderInline: renderInline,
- renderInlines: renderInlines,
- renderBlock: renderBlock,
- renderBlocks: renderBlocks,
- render: renderBlock
- };
-}
-
-exports.DocParser = DocParser;
-exports.HtmlRenderer = HtmlRenderer;
-
-})(typeof exports === 'undefined' ? this.stmd = {} : exports);
diff --git a/js/test.js b/js/test.js
index f2d06d8..5427bbf 100755
--- a/js/test.js
+++ b/js/test.js
@@ -1,12 +1,12 @@
#!/usr/bin/env node
var fs = require('fs');
-var stmd = require('./stmd');
+var commonmark = require('./lib/index.js');
var ansi = require('./ansi/ansi');
var cursor = ansi(process.stdout);
-var writer = new stmd.HtmlRenderer();
-var reader = new stmd.DocParser();
+var writer = new commonmark.HtmlRenderer();
+var reader = new commonmark.DocParser();
var passed = 0;
var failed = 0;
diff --git a/leakcheck.md b/leakcheck.md
new file mode 100644
index 0000000..06716e1
--- /dev/null
+++ b/leakcheck.md
@@ -0,0 +1,1561 @@
+→foo→baz→→bim
+
+ a→a
+ ὐ→a
+
+- `one
+- two`
+
+***
+---
+___
+
++++
+
+===
+
+--
+**
+__
+
+ ***
+ ***
+ ***
+
+ ***
+
+Foo
+ ***
+
+_____________________________________
+
+ - - -
+
+ ** * ** * ** * **
+
+- - - -
+
+- - - -
+
+_ _ _ _ a
+
+a------
+
+ *-*
+
+- foo
+***
+- bar
+
+Foo
+***
+bar
+
+Foo
+---
+bar
+
+* Foo
+* * *
+* Bar
+
+- Foo
+- * * *
+
+# foo
+## foo
+### foo
+#### foo
+##### foo
+###### foo
+
+####### foo
+
+#5 bolt
+
+\## foo
+
+# foo *bar* \*baz\*
+
+# foo
+
+ ### foo
+ ## foo
+ # foo
+
+ # foo
+
+foo
+ # bar
+
+## foo ##
+ ### bar ###
+
+# foo ##################################
+##### foo ##
+
+### foo ###
+
+### foo ### b
+
+### foo \###
+## foo \#\##
+# foo \#
+
+****
+## foo
+****
+
+Foo bar
+# baz
+Bar foo
+
+##
+#
+### ###
+
+Foo *bar*
+=========
+
+Foo *bar*
+---------
+
+Foo
+-------------------------
+
+Foo
+=
+
+ Foo
+---
+
+ Foo
+-----
+
+ Foo
+ ===
+
+ Foo
+ ---
+
+ Foo
+---
+
+Foo
+ ----
+
+Foo
+ ---
+
+Foo
+= =
+
+Foo
+--- -
+
+Foo
+-----
+
+Foo\
+----
+
+`Foo
+----
+`
+
+<a title="a lot
+---
+of dashes"/>
+
+> Foo
+---
+
+Foo
+Bar
+---
+
+Foo
+Bar
+===
+
+---
+Foo
+---
+Bar
+---
+Baz
+
+
+====
+
+ a simple
+ indented code block
+
+ <a/>
+ *hi*
+
+ - one
+
+ chunk1
+
+ chunk2
+
+
+
+ chunk3
+
+ chunk1
+
+ chunk2
+
+Foo
+ bar
+
+
+ foo
+bar
+
+# Header
+ foo
+Header
+------
+ foo
+----
+
+ foo
+ bar
+
+
+
+ foo
+
+
+
+ foo
+
+```
+<
+ >
+```
+
+~~~
+<
+ >
+~~~
+
+```
+aaa
+~~~
+```
+
+~~~
+aaa
+```
+~~~
+
+````
+aaa
+```
+``````
+
+~~~~
+aaa
+~~~
+~~~~
+
+```
+
+`````
+
+```
+aaa
+
+```
+
+
+```
+
+```
+```
+
+ ```
+ aaa
+aaa
+```
+
+ ```
+aaa
+ aaa
+aaa
+ ```
+
+ ```
+ aaa
+ aaa
+ aaa
+ ```
+
+ ```
+ aaa
+ ```
+
+``` ```
+aaa
+
+~~~~~~
+aaa
+~~~ ~~
+
+foo
+```
+bar
+```
+baz
+
+foo
+---
+~~~
+bar
+~~~
+# baz
+
+```ruby
+def foo(x)
+ return 3
+end
+```
+
+~~~~ ruby startline=3 $%@#$
+def foo(x)
+ return 3
+end
+~~~~~~~
+
+````;
+````
+
+``` aa ```
+foo
+
+```
+``` aaa
+```
+
+<table>
+ <tr>
+ <td>
+ hi
+ </td>
+ </tr>
+</table>
+
+okay.
+
+ <div>
+ *hello*
+ <foo><a>
+
+<DIV CLASS="foo">
+
+*Markdown*
+
+</DIV>
+
+<div></div>
+``` c
+int x = 33;
+```
+
+<!-- Foo
+bar
+ baz -->
+
+<?php
+ echo 'foo'
+?>
+
+<![CDATA[
+function matchwo(a,b)
+{
+if (a < b && a < 0) then
+ {
+ return 1;
+ }
+else
+ {
+ return 0;
+ }
+}
+]]>
+
+ <!-- foo -->
+
+ <!-- foo -->
+
+Foo
+<div>
+bar
+</div>
+
+<div>
+bar
+</div>
+*foo*
+
+<div class
+foo
+
+<div>
+
+*Emphasized* text.
+
+</div>
+
+<div>
+*Emphasized* text.
+</div>
+
+<table>
+
+<tr>
+
+<td>
+Hi
+</td>
+
+</tr>
+
+</table>
+
+[foo]: /url "title"
+
+[foo]
+
+ [foo]:
+ /url
+ 'the title'
+
+[foo]
+
+[Foo*bar\]]:my_(url) 'title (with parens)'
+
+[Foo*bar\]]
+
+[Foo bar]:
+<my url>
+'title'
+
+[Foo bar]
+
+[foo]:
+/url
+
+[foo]
+
+[foo]:
+
+[foo]
+
+[foo]
+
+[foo]: url
+
+[foo]
+
+[foo]: first
+[foo]: second
+
+[FOO]: /url
+
+[Foo]
+
+[ΑΓΩ]: /φου
+
+[αγω]
+
+[foo]: /url
+
+[foo]: /url "title" ok
+
+ [foo]: /url "title"
+
+[foo]
+
+```
+[foo]: /url
+```
+
+[foo]
+
+Foo
+[bar]: /baz
+
+[bar]
+
+# [Foo]
+[foo]: /url
+> bar
+
+[foo]: /foo-url "foo"
+[bar]: /bar-url
+ "bar"
+[baz]: /baz-url
+
+[foo],
+[bar],
+[baz]
+
+[foo]
+
+> [foo]: /url
+
+aaa
+
+bbb
+
+aaa
+bbb
+
+ccc
+ddd
+
+aaa
+
+
+bbb
+
+ aaa
+ bbb
+
+aaa
+ bbb
+ ccc
+
+ aaa
+bbb
+
+ aaa
+bbb
+
+aaa
+bbb
+
+
+
+aaa
+
+
+# aaa
+
+
+
+> # Foo
+> bar
+> baz
+
+># Foo
+>bar
+> baz
+
+ > # Foo
+ > bar
+ > baz
+
+ > # Foo
+ > bar
+ > baz
+
+> # Foo
+> bar
+baz
+
+> bar
+baz
+> foo
+
+> foo
+---
+
+> - foo
+- bar
+
+> foo
+ bar
+
+> ```
+foo
+```
+
+>
+
+>
+>
+>
+
+>
+> foo
+>
+
+> foo
+
+> bar
+
+> foo
+> bar
+
+> foo
+>
+> bar
+
+foo
+> bar
+
+> aaa
+***
+> bbb
+
+> bar
+baz
+
+> bar
+
+baz
+
+> bar
+>
+baz
+
+> > > foo
+bar
+
+>>> foo
+> bar
+>>baz
+
+> code
+
+> not code
+
+A paragraph
+with two lines.
+
+ indented code
+
+> A block quote.
+
+1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+
+- one
+
+ two
+
+- one
+
+ two
+
+ - one
+
+ two
+
+ - one
+
+ two
+
+ > > 1. one
+>>
+>> two
+
+>>- one
+>>
+ > > two
+
+- foo
+
+ bar
+
+- foo
+
+
+ bar
+
+- ```
+ foo
+
+
+ bar
+ ```
+
+1. foo
+
+ ```
+ bar
+ ```
+
+ baz
+
+ > bam
+
+- foo
+
+ bar
+
+ 10. foo
+
+ bar
+
+ indented code
+
+paragraph
+
+ more code
+
+1. indented code
+
+ paragraph
+
+ more code
+
+1. indented code
+
+ paragraph
+
+ more code
+
+ foo
+
+bar
+
+- foo
+
+ bar
+
+- foo
+
+ bar
+
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+
+ 1. A paragraph
+ with two lines.
+
+ indented code
+
+ > A block quote.
+
+ 1. A paragraph
+with two lines.
+
+ indented code
+
+ > A block quote.
+
+ 1. A paragraph
+ with two lines.
+
+> 1. > Blockquote
+continued here.
+
+> 1. > Blockquote
+> continued here.
+
+- foo
+ - bar
+ - baz
+
+- foo
+ - bar
+ - baz
+
+10) foo
+ - bar
+
+10) foo
+ - bar
+
+- - foo
+
+1. - 2. foo
+
+- foo
+-
+- bar
+
+-
+
+- foo
+- bar
++ baz
+
+1. foo
+2. bar
+3) baz
+
+- foo
+
+- bar
+
+
+- baz
+
+- foo
+
+
+ bar
+- baz
+
+- foo
+ - bar
+ - baz
+
+
+ bim
+
+- foo
+- bar
+
+
+- baz
+- bim
+
+- foo
+
+ notcode
+
+- foo
+
+
+ code
+
+- a
+ - b
+ - c
+ - d
+ - e
+ - f
+- g
+
+- a
+- b
+
+- c
+
+* a
+*
+
+* c
+
+- a
+- b
+
+ c
+- d
+
+- a
+- b
+
+ [ref]: /url
+- d
+
+- a
+- ```
+ b
+
+
+ ```
+- c
+
+- a
+ - b
+
+ c
+- d
+
+* a
+ > b
+ >
+* c
+
+- a
+ > b
+ ```
+ c
+ ```
+- d
+
+- a
+
+- a
+ - b
+
+* foo
+ * bar
+
+ baz
+
+- a
+ - b
+ - c
+
+- d
+ - e
+ - f
+
+`hi`lo`
+
+\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+
+\→\A\a\ \3\φ\«
+
+\*not emphasized*
+\<br/> not a tag
+\[not a link](/foo)
+\`not code`
+1\. not a list
+\* not a list
+\# not a header
+\[foo]: /url "not a reference"
+
+\\*emphasis*
+
+foo\
+bar
+
+`` \[\` ``
+
+ \[\]
+
+~~~
+\[\]
+~~~
+
+<http://example.com?find=\*>
+
+<a href="/bar\/)">
+
+[foo](/bar\* "ti\*tle")
+
+[foo]
+
+[foo]: /bar\* "ti\*tle"
+
+``` foo\+bar
+foo
+```
+
+&nbsp; &amp; &copy; &AElig; &Dcaron; &frac34; &HilbertSpace; &DifferentialD; &ClockwiseContourIntegral;
+
+&#35; &#1234; &#992; &#98765432;
+
+&#X22; &#XD06; &#xcab;
+
+&nbsp &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;
+
+&copy
+
+&MadeUpEntity;
+
+<a href="&ouml;&ouml;.html">
+
+[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
+
+[foo]
+
+[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
+
+``` f&ouml;&ouml;
+foo
+```
+
+`f&ouml;&ouml;`
+
+ f&ouml;f&ouml;
+
+`foo`
+
+`` foo ` bar ``
+
+` `` `
+
+``
+foo
+``
+
+`foo bar
+ baz`
+
+`foo `` bar`
+
+`foo\`bar`
+
+*foo`*`
+
+[not a `link](/foo`)
+
+<http://foo.bar.`baz>`
+
+<a href="`">`
+
+```foo``
+
+`foo
+
+*foo bar*
+
+_foo bar_
+
+**foo bar**
+
+__foo bar__
+
+*foo
+bar*
+
+_foo
+bar_
+
+**foo
+bar**
+
+__foo
+bar__
+
+*foo [bar](/url)*
+
+_foo [bar](/url)_
+
+**foo [bar](/url)**
+
+__foo [bar](/url)__
+
+*foo [bar*](/url)
+
+_foo [bar_](/url)
+
+**<a href="**">
+
+__<a href="__">
+
+*a `*`*
+
+_a `_`_
+
+**a<http://foo.bar?q=**>
+
+__a<http://foo.bar?q=__>
+
+and * foo bar*
+
+_ foo bar_
+
+and ** foo bar**
+
+__ foo bar__
+
+and *foo bar *
+
+and _foo bar _
+
+and **foo bar **
+
+and __foo bar __
+
+****hi****
+
+_____hi_____
+
+Sign here: _________
+
+** is not an empty emphasis
+
+**** is not an empty strong emphasis
+
+*here is a \**
+
+__this is a double underscore (`__`)__
+
+*_*
+
+_*_
+
+*__*
+
+_**_
+
+foo*bar*baz
+
+foo_bar_baz
+
+foo__bar__baz
+
+_foo_bar_baz_
+
+11*15*32
+
+11_15_32
+
+_foo_bar_baz_
+
+__foo__bar__baz__
+
+***foo bar***
+
+___foo bar___
+
+***foo** bar*
+
+___foo__ bar_
+
+***foo* bar**
+
+___foo_ bar__
+
+*foo **bar***
+
+_foo __bar___
+
+**foo *bar***
+
+__foo _bar___
+
+*foo **bar***
+
+_foo __bar___
+
+*foo *bar* baz*
+
+_foo _bar_ baz_
+
+**foo **bar** baz**
+
+__foo __bar__ baz__
+
+*foo **bar** baz*
+
+_foo __bar__ baz_
+
+**foo *bar* baz**
+
+__foo _bar_ baz__
+
+**foo, *bar*, baz**
+
+__foo, _bar_, baz__
+
+*foo**bar**baz*
+
+**foo*bar*baz**
+
+**foo**
+
+****foo****
+
+*_foo_*
+
+**__foo__**
+
+*foo**
+
+*foo *bar**
+
+**foo***
+
+***foo* bar***
+
+***foo** bar***
+
+*foo**bar***
+
+*foo****
+
+*foo**
+
+**foo*
+
+*foo *bar**
+
+**foo* bar*
+
+*bar***
+
+***foo*
+
+**bar***
+
+***foo**
+
+***foo *bar*
+
+[link](/uri "title")
+
+[link](/uri)
+
+[link]()
+
+[link](<>)
+
+[link](/my uri)
+
+[link](</my uri>)
+
+[link](foo
+bar)
+
+[link]((foo)and(bar))
+
+[link](foo(and(bar)))
+
+[link](foo(and\(bar\)))
+
+[link](<foo(and(bar))>)
+
+[link](foo\)\:)
+
+[link](foo%20b&auml;)
+
+[link]("title")
+
+[link](/url "title")
+[link](/url 'title')
+[link](/url (title))
+
+[link](/url "title \"&quot;")
+
+[link](/url "title "and" title")
+
+[link](/url 'title "and" title')
+
+[link]( /uri
+ "title" )
+
+[link] (/uri)
+
+[foo <bar attr="](baz)">
+
+[foo][bar]
+
+[bar]: /url "title"
+
+[*foo\!*][bar]
+
+[bar]: /url "title"
+
+[foo][BaR]
+
+[bar]: /url "title"
+
+[Толпой][Толпой] is a Russian word.
+
+[ТОЛПОЙ]: /url
+
+[Foo
+ bar]: /url
+
+[Baz][Foo bar]
+
+[foo] [bar]
+
+[bar]: /url "title"
+
+[foo]
+[bar]
+
+[bar]: /url "title"
+
+[foo]: /url1
+
+[foo]: /url2
+
+[bar][foo]
+
+[bar][foo\!]
+
+[foo!]: /url
+
+[foo][]
+
+[foo]: /url "title"
+
+[*foo* bar][]
+
+[*foo* bar]: /url "title"
+
+[Foo][]
+
+[foo]: /url "title"
+
+[foo]
+[]
+
+[foo]: /url "title"
+
+[foo]
+
+[foo]: /url "title"
+
+[*foo* bar]
+
+[*foo* bar]: /url "title"
+
+[[*foo* bar]]
+
+[*foo* bar]: /url "title"
+
+[Foo]
+
+[foo]: /url "title"
+
+\[foo]
+
+[foo]: /url "title"
+
+[foo*]: /url
+
+*[foo*]
+
+[foo`]: /url
+
+[foo`]`
+
+[[[foo]]]
+
+[[[foo]]]: /url
+
+[[[foo]]]
+
+[[[foo]]]: /url1
+[foo]: /url2
+
+[\[foo]
+
+[\[foo]: /url
+
+[foo][bar]
+
+[foo]: /url1
+[bar]: /url2
+
+[foo][bar][baz]
+
+[baz]: /url
+
+[foo][bar][baz]
+
+[baz]: /url1
+[bar]: /url2
+
+[foo][bar][baz]
+
+[baz]: /url1
+[foo]: /url2
+
+![foo](/url "title")
+
+![foo *bar*]
+
+[foo *bar*]: train.jpg "train & tracks"
+
+![foo *bar*][]
+
+[foo *bar*]: train.jpg "train & tracks"
+
+![foo *bar*][foobar]
+
+[FOOBAR]: train.jpg "train & tracks"
+
+![foo](train.jpg)
+
+My ![foo bar](/path/to/train.jpg "title" )
+
+![foo](<url>)
+
+![](/url)
+
+![foo] [bar]
+
+[bar]: /url
+
+![foo] [bar]
+
+[BAR]: /url
+
+![foo][]
+
+[foo]: /url "title"
+
+![*foo* bar][]
+
+[*foo* bar]: /url "title"
+
+![Foo][]
+
+[foo]: /url "title"
+
+![foo]
+[]
+
+[foo]: /url "title"
+
+![foo]
+
+[foo]: /url "title"
+
+![*foo* bar]
+
+[*foo* bar]: /url "title"
+
+![[foo]]
+
+[[foo]]: /url "title"
+
+![Foo]
+
+[foo]: /url "title"
+
+\!\[foo]
+
+[foo]: /url "title"
+
+\![foo]
+
+[foo]: /url "title"
+
+<http://foo.bar.baz>
+
+<http://foo.bar.baz?q=hello&id=22&boolean>
+
+<irc://foo.bar:2233/baz>
+
+<MAILTO:FOO@BAR.BAZ>
+
+<http://foo.bar/baz bim>
+
+<foo@bar.example.com>
+
+<foo+special@Bar.baz-bar0.com>
+
+<>
+
+<heck://bing.bong>
+
+< http://foo.bar >
+
+<foo.bar.baz>
+
+<localhost:5001/foo>
+
+http://example.com
+
+foo@bar.example.com
+
+<a><bab><c2c>
+
+<a/><b2/>
+
+<a /><b2
+data="foo" >
+
+<a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 />
+
+<33> <__>
+
+<a h*#ref="hi">
+
+<a href="hi'> <a href=hi'>
+
+< a><
+foo><bar/ >
+
+<a href='bar'title=title>
+
+</a>
+</foo >
+
+</a href="foo">
+
+foo <!-- this is a
+comment - with hyphen -->
+
+foo <!-- not a comment -- two hyphens -->
+
+foo <?php echo $a; ?>
+
+foo <!ELEMENT br EMPTY>
+
+foo <![CDATA[>&<]]>
+
+<a href="&ouml;">
+
+<a href="\*">
+
+<a href="\"">
+
+foo
+baz
+
+foo\
+baz
+
+foo
+baz
+
+foo
+ bar
+
+foo\
+ bar
+
+*foo
+bar*
+
+*foo\
+bar*
+
+`code
+span`
+
+`code\
+span`
+
+<a href="foo
+bar">
+
+<a href="foo\
+bar">
+
+foo
+baz
+
+foo
+ baz
+
+hello $.;'there
+
+Foo χρῆν
+
+Multiple spaces
+
diff --git a/license.bstrlib.txt b/license.bstrlib.txt
deleted file mode 100644
index cf78a98..0000000
--- a/license.bstrlib.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2002-2008 Paul Hsieh
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- Neither the name of bstrlib nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/license.uthash.txt b/license.uthash.txt
deleted file mode 100644
index ad8e16a..0000000
--- a/license.uthash.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2005-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/man/Makefile b/man/Makefile
index 98528c3..f5a5fad 100644
--- a/man/Makefile
+++ b/man/Makefile
@@ -1,4 +1,4 @@
-ALL=man1/stmd.1
+ALL=man1/cmark.1
.PHONY: all
diff --git a/man/stmd.1.md b/man/cmark.1.md
index 3947a79..ddc1b42 100644
--- a/man/stmd.1.md
+++ b/man/cmark.1.md
@@ -1,22 +1,22 @@
---
-title: stmd
+title: cmark
section: 1
-footer: stmd manual
-date: August 12, 2014
+footer: cmark manual
+date: October 22, 2014
...
# NAME
-stmd - convert markdown formatted text to HTML
+cmark - convert CommonMark formatted text to HTML
# SYNOPSIS
-stmd [*options*] [file\*]
+cmark [*options*] [file\*]
# DESCRIPTION
-`stmd` acts as a pipe, reading from stdin or from the specified
-files and writing to stdout. It converts markdown formatted plain
+`cmark` acts as a pipe, reading from stdin or from the specified
+files and writing to stdout. It converts Markdown formatted plain
text to HTML, using the conventions described in the CommonMark
spec.
diff --git a/man/man1/stmd.1 b/man/man1/cmark.1
index 6bfdd80..65e10c1 100644
--- a/man/man1/stmd.1
+++ b/man/man1/cmark.1
@@ -1,15 +1,15 @@
-.TH "stmd" "1" "August 12, 2014" "stmd manual" ""
+.TH "cmark" "1" "October 22, 2014" "cmark manual" ""
.SH NAME
.PP
-stmd \- convert markdown formatted text to HTML
+cmark \- convert CommonMark formatted text to HTML
.SH SYNOPSIS
.PP
-stmd [\f[I]options\f[]] [file*]
+cmark [\f[I]options\f[]] [file*]
.SH DESCRIPTION
.PP
-\f[C]stmd\f[] acts as a pipe, reading from stdin or from the specified
+\f[C]cmark\f[] acts as a pipe, reading from stdin or from the specified
files and writing to stdout.
-It converts markdown formatted plain text to HTML, using the conventions
+It converts Markdown formatted plain text to HTML, using the conventions
described in the CommonMark spec.
.SH OPTIONS
.TP
diff --git a/narrative.md b/narrative.md
index 2448ad8..7390662 100644
--- a/narrative.md
+++ b/narrative.md
@@ -4,15 +4,15 @@ title: CommonMark
CommonMark is a [specification of Markdown
syntax](http://jgm.github.io/stmd/spec.html), together with
-BSD3-licensed implementations (`stmd`) in C and javascript. The source
+BSD3-licensed implementations in C and JavaScript. The source
for the spec and the two implementations can be found in [this
repository](http://github.com/jgm/stmd).
The C implementation provides both a library and a standalone program
-`stmd` that converts Markdown to HTML. It is written in standard C99 and
-has no library dependencies.
+`cmark` that converts Markdown to HTML. It is written in standard C99
+and has no library dependencies.
-The javascript implementation is a single javascript file, with no
+The JavaScript implementation is a single JavaScript file, with no
dependencies. [Try it now!](http://jgm.github.io/stmd/js/)
[The spec](http://jgm.github.io/stmd/spec.html) contains over 400
@@ -129,3 +129,12 @@ working out the spec, I benefited greatly from collaboration with David
Greenspan, and from extensive discussions with a group of industrial
users of Markdown, including Jeff Atwood, Vincent Marti, and Neil
Williams.
+
+### Contributing
+
+There is a [forum for discussing
+CommonMark](http://talk.commonmark.org); you should use it instead of
+github issues for questions and possibly open-ended discussions.
+Use the [github issue tracker](http://github.com/jgm/stmd/issues)
+only for simple, clear, actionable issues.
+
diff --git a/oldtests/Blockquotes/Indents.html b/oldtests/Blockquotes/Indents.html
deleted file mode 100644
index fd98ee8..0000000
--- a/oldtests/Blockquotes/Indents.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<blockquote>
-<p>one
-blockquote</p>
-</blockquote>
-<blockquote>
-<blockquote>
-<blockquote>
-<p>triply nested
-triply nested</p>
-</blockquote>
-</blockquote>
-</blockquote>
diff --git a/oldtests/Blockquotes/Indents.markdown b/oldtests/Blockquotes/Indents.markdown
deleted file mode 100644
index f9342ff..0000000
--- a/oldtests/Blockquotes/Indents.markdown
+++ /dev/null
@@ -1,5 +0,0 @@
-> one
- > blockquote
-
->>> triply nested
- > > > triply nested
diff --git a/oldtests/Blockquotes/Nesting.html b/oldtests/Blockquotes/Nesting.html
deleted file mode 100644
index f40e999..0000000
--- a/oldtests/Blockquotes/Nesting.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<p>These are all equivalent:</p>
-<blockquote>
-<blockquote>
-<p>nested
-blockquote</p>
-</blockquote>
-</blockquote>
-<blockquote>
-<blockquote>
-<p>nested
-blockquote</p>
-</blockquote>
-</blockquote>
-<blockquote>
-<blockquote>
-<p>nested
-blockquote</p>
-</blockquote>
-</blockquote>
-<blockquote>
-<blockquote>
-<p>nested
-blockquote</p>
-</blockquote>
-</blockquote>
-<p>This is not:</p>
-<blockquote>
-<p>nested</p>
-<blockquote>
-<p>blockquote</p>
-</blockquote>
-</blockquote>
diff --git a/oldtests/Blockquotes/Nesting.markdown b/oldtests/Blockquotes/Nesting.markdown
deleted file mode 100644
index 3d67843..0000000
--- a/oldtests/Blockquotes/Nesting.markdown
+++ /dev/null
@@ -1,22 +0,0 @@
-These are all equivalent:
-
-> > nested
-> > blockquote
-
-
->> nested
->> blockquote
-
-
-> > nested
-blockquote
-
-
-> > nested
-> blockquote
-
-
-This is not:
-
-> nested
-> > blockquote
diff --git a/oldtests/Blockquotes/Separation.html b/oldtests/Blockquotes/Separation.html
deleted file mode 100644
index 910d545..0000000
--- a/oldtests/Blockquotes/Separation.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<p>One blockquote, two paragraphs:</p>
-<blockquote>
-<p>one</p>
-<p>two</p>
-</blockquote>
-<p>Two blockquotes:</p>
-<blockquote>
-<p>one</p>
-</blockquote>
-<blockquote>
-<p>two</p>
-</blockquote>
-<p>Nested blockquote, two paragraphs:</p>
-<blockquote>
-<blockquote>
-<p>one</p>
-<p>two</p>
-</blockquote>
-</blockquote>
-<p>Nested blockquote, two blockquotes:</p>
-<blockquote>
-<blockquote>
-<p>one</p>
-</blockquote>
-<blockquote>
-<p>two</p>
-</blockquote>
-</blockquote>
-<p>Two nested blockquotes:</p>
-<blockquote>
-<blockquote>
-<p>one</p>
-</blockquote>
-</blockquote>
-<blockquote>
-<blockquote>
-<p>two</p>
-</blockquote>
-</blockquote>
diff --git a/oldtests/Blockquotes/Separation.markdown b/oldtests/Blockquotes/Separation.markdown
deleted file mode 100644
index 823d865..0000000
--- a/oldtests/Blockquotes/Separation.markdown
+++ /dev/null
@@ -1,29 +0,0 @@
-One blockquote, two paragraphs:
-
-> one
->
-> two
-
-Two blockquotes:
-
-> one
-
-> two
-
-Nested blockquote, two paragraphs:
-
-> > one
-> >
-> > two
-
-Nested blockquote, two blockquotes:
-
-> > one
->
-> > two
-
-Two nested blockquotes:
-
-> > one
-
-> > two
diff --git a/oldtests/Code/BlankLines.html b/oldtests/Code/BlankLines.html
deleted file mode 100644
index ae0abf7..0000000
--- a/oldtests/Code/BlankLines.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<pre><code>foo
-
-
-
-bar
-</code></pre>
-<blockquote>
-<pre><code>foo
-
-
-
-bar
-</code></pre>
-</blockquote>
-<pre><code>foo
-
-
-
-bar
-</code></pre>
-<ol>
-<li><p>One</p>
-<pre><code>CodeA
-
-CodeB
-</code></pre></li>
-<li><p>Two</p>
-<pre><code>CodeA
-</code></pre></li>
-</ol>
-<ol>
-<li>One</li>
-</ol>
diff --git a/oldtests/Code/BlankLines.markdown b/oldtests/Code/BlankLines.markdown
deleted file mode 100644
index b0d5a0c..0000000
--- a/oldtests/Code/BlankLines.markdown
+++ /dev/null
@@ -1,28 +0,0 @@
- foo
-
-
-
- bar
-> foo
->
->
->
-> bar
- foo
-
-
-
- bar
-
-1. One
-
- CodeA
-
- CodeB
-
-2. Two
-
- CodeA
-
-
-1. One
diff --git a/oldtests/Code/BlankLinesAtEnd.html b/oldtests/Code/BlankLinesAtEnd.html
deleted file mode 100644
index ac803d9..0000000
--- a/oldtests/Code/BlankLinesAtEnd.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<ul>
-<li><p>List</p>
-<pre><code>code
-</code></pre></li>
-</ul>
-<ul>
-<li>one</li>
-<li>two</li>
-</ul>
-<ul>
-<li><p>one
-not code</p></li>
-<li><p>two</p></li>
-</ul>
diff --git a/oldtests/Code/BlankLinesAtEnd.markdown b/oldtests/Code/BlankLinesAtEnd.markdown
deleted file mode 100644
index 55879ae..0000000
--- a/oldtests/Code/BlankLinesAtEnd.markdown
+++ /dev/null
@@ -1,14 +0,0 @@
-* List
-
- code
-
-
- * one
- * two
-
-
-
-* one
- not code
-
-* two
diff --git a/oldtests/Code/FenceMatching.html b/oldtests/Code/FenceMatching.html
deleted file mode 100644
index 4c7468e..0000000
--- a/oldtests/Code/FenceMatching.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<pre class="abc"><code>```
-</code></pre>
-<pre class="blah"><code>
-`````
-
-````
-
-</code></pre>
diff --git a/oldtests/Code/FenceMatching.markdown b/oldtests/Code/FenceMatching.markdown
deleted file mode 100644
index d86169a..0000000
--- a/oldtests/Code/FenceMatching.markdown
+++ /dev/null
@@ -1,10 +0,0 @@
-````abc
-```
-````
-``````blah
-
-`````
-
-````
-
-```````````
diff --git a/oldtests/Code/FencedCodeBlocks.html b/oldtests/Code/FencedCodeBlocks.html
deleted file mode 100644
index 4813d72..0000000
--- a/oldtests/Code/FencedCodeBlocks.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<p>This is a fenced code block:</p>
-<pre class="haskell"><code>pairs :: [(Int,Char)]
-pairs = [(x,y) | x &lt;- [0..10], y &lt;- ['a'..'z']]
-</code></pre>
-<p>Here is one with tildes:</p>
-<pre class="haskell"><code>pairs :: [(Int,Char)]
-pairs = [(x,y) | x &lt;- [0..10], y &lt;- ['a'..'z']]
-</code></pre>
-<p>More metadata:</p>
-<pre class="haskell"><code>pairs :: [(Int,Char)]
-pairs = [(x,y) | x &lt;- [0..10], y &lt;- ['a'..'z']]
-</code></pre>
-<p>More backticks:</p>
-<pre class="haskell"><code>pairs :: [(Int,Char)]
-pairs = [(x,y) | x &lt;- [0..10], y &lt;- ['a'..'z']]
-
-backticks :: String
-backticks = &quot;`````&quot;
-</code></pre>
-<p>Without an end:</p>
-<pre><code>code with
-no end
-
-</code></pre>
diff --git a/oldtests/Code/FencedCodeBlocks.markdown b/oldtests/Code/FencedCodeBlocks.markdown
deleted file mode 100644
index 6ccc6be..0000000
--- a/oldtests/Code/FencedCodeBlocks.markdown
+++ /dev/null
@@ -1,35 +0,0 @@
-This is a fenced code block:
-```haskell
-pairs :: [(Int,Char)]
-pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
-```
-Here is one with tildes:
-
-~~~ haskell
-pairs :: [(Int,Char)]
-pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
-~~~
-
-More metadata:
-
-```haskell numberLines start=50
-pairs :: [(Int,Char)]
-pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
-```
-
-More backticks:
-
-```````` haskell
-pairs :: [(Int,Char)]
-pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
-
-backticks :: String
-backticks = "`````"
-`````````````
-
-Without an end:
-
-```
-code with
-no end
-
diff --git a/oldtests/Code/IndentedCodeBlocks.html b/oldtests/Code/IndentedCodeBlocks.html
deleted file mode 100644
index 0b9b7e7..0000000
--- a/oldtests/Code/IndentedCodeBlocks.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<p>Indented code with two space indent in first and last line:</p>
-<pre><code> two spaces *hello*
-{ more }
-
- and
-</code></pre>
-<p>Indented code requires a leading/trailing blank line:
-quick-command --option &quot;$*&quot;</p>
-<p>Indented code does not require a trailing blank line:</p>
-<pre><code>code
-</code></pre>
-<p>and not code.</p>
-<p>Code in blockquote:</p>
-<blockquote>
-<pre><code>code
-</code></pre>
-</blockquote>
-<p>Code in list:</p>
-<ol>
-<li><pre><code>code
-</code></pre></li>
-</ol>
diff --git a/oldtests/Code/IndentedCodeBlocks.markdown b/oldtests/Code/IndentedCodeBlocks.markdown
deleted file mode 100644
index 2a99db0..0000000
--- a/oldtests/Code/IndentedCodeBlocks.markdown
+++ /dev/null
@@ -1,22 +0,0 @@
-Indented code with two space indent in first and last line:
-
- two spaces *hello*
- { more }
-
- and
-
-Indented code requires a leading/trailing blank line:
- quick-command --option "$*"
-
-Indented code does not require a trailing blank line:
-
- code
-and not code.
-
-Code in blockquote:
-
-> code
-
-Code in list:
-
-1. code
diff --git a/oldtests/Code/IndentedFences.html b/oldtests/Code/IndentedFences.html
deleted file mode 100644
index 66e76da..0000000
--- a/oldtests/Code/IndentedFences.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<pre><code>a
-</code></pre>
-<pre><code>z
-</code></pre>
-<pre><code>a
-a
-a
- a
-</code></pre>
-<ul>
-<li><p>foo</p>
-<pre><code> Hello
-
-World
-</code></pre></li>
-</ul>
-<blockquote>
-<pre><code>a
-</code></pre>
-</blockquote>
diff --git a/oldtests/Code/IndentedFences.markdown b/oldtests/Code/IndentedFences.markdown
deleted file mode 100644
index 098545f..0000000
--- a/oldtests/Code/IndentedFences.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
- ```
- a
- ```
-
- ```
-z
-```
-
- ```
-a
- a
- a
- a
- ```
-
-* foo
-
- ```
- Hello
-
- World
- ```
-
-> ```
->a
->```
diff --git a/oldtests/Code/IndentedInLists.html b/oldtests/Code/IndentedInLists.html
deleted file mode 100644
index 76ed424..0000000
--- a/oldtests/Code/IndentedInLists.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<ul>
-<li><pre><code>code starts here
-</code></pre></li>
-</ul>
-<ol>
-<li><p>foo</p>
-<pre><code>code starts here
-</code></pre></li>
-<li><p>foo</p>
-<pre><code>code starts here
-</code></pre></li>
-</ol>
-<ul>
-<li><p>foo</p>
-<pre><code>code starts here
-</code></pre>
-<ul>
-<li><p>foo</p>
-<pre><code>code starts here
-</code></pre></li>
-</ul></li>
-</ul>
diff --git a/oldtests/Code/IndentedInLists.markdown b/oldtests/Code/IndentedInLists.markdown
deleted file mode 100644
index 54e1af1..0000000
--- a/oldtests/Code/IndentedInLists.markdown
+++ /dev/null
@@ -1,17 +0,0 @@
-- code starts here
-
-1. foo
-
- code starts here
-
-2. foo
-
- code starts here
-
-- foo
-
- code starts here
-
- - foo
-
- code starts here
diff --git a/oldtests/Code/Inline.html b/oldtests/Code/Inline.html
deleted file mode 100644
index 9c52790..0000000
--- a/oldtests/Code/Inline.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<p>All of these are equivalent:</p>
-<ul>
-<li><code>*hi*</code></li>
-<li><code>*hi*</code></li>
-<li><code>*hi*</code></li>
-<li><code>*hi*</code></li>
-<li><code>*hi*</code></li>
-</ul>
-<p>Backticks in code spans:</p>
-<ul>
-<li><code>``code``</code></li>
-<li><code>``code``</code></li>
-</ul>
diff --git a/oldtests/Code/Inline.markdown b/oldtests/Code/Inline.markdown
deleted file mode 100644
index 38e5b0c..0000000
--- a/oldtests/Code/Inline.markdown
+++ /dev/null
@@ -1,13 +0,0 @@
-All of these are equivalent:
-
-- `*hi*`
-- ` *hi* `
-- ``*hi* ``
-- ````*hi*````
-- `*hi*
- `
-
-Backticks in code spans:
-
-- ``` ``code`` ```
-- ` ``code`` `
diff --git a/oldtests/Code/ListBreakAfter.html b/oldtests/Code/ListBreakAfter.html
deleted file mode 100644
index 29d6d5e..0000000
--- a/oldtests/Code/ListBreakAfter.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<ul>
-<li><p>foo</p>
-<ul>
-<li><p>bar</p>
-<pre><code>code1
-code2
-</code></pre>
-<p>code?</p></li>
-</ul></li>
-<li><p>foo</p>
-<ul>
-<li><p>bar</p>
-<pre><code>code1
-code2
-</code></pre></li>
-</ul></li>
-</ul>
-<pre><code>code?
-</code></pre>
-<ul>
-<li>foo
-<ul>
-<li><p>bar</p>
-<pre><code>code1
-code2
-</code></pre></li>
-</ul></li>
-</ul>
-<pre><code>code?
-</code></pre>
diff --git a/oldtests/Code/ListBreakAfter.markdown b/oldtests/Code/ListBreakAfter.markdown
deleted file mode 100644
index 4fa79f1..0000000
--- a/oldtests/Code/ListBreakAfter.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
-* foo
- * bar
-
- code1
- code2
-
- code?
-
-* foo
- * bar
-
- code1
- code2
-
-
- code?
-
-* foo
- * bar
-
- code1
- code2
-
-
-
- code?
diff --git a/oldtests/Code/WhiteLines.html b/oldtests/Code/WhiteLines.html
deleted file mode 100644
index 7fa137f..0000000
--- a/oldtests/Code/WhiteLines.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<pre><code>ABC
-
-
-
-DEF
-</code></pre>
-<p>GHI</p>
diff --git a/oldtests/Code/WhiteLines.markdown b/oldtests/Code/WhiteLines.markdown
deleted file mode 100644
index ea17af7..0000000
--- a/oldtests/Code/WhiteLines.markdown
+++ /dev/null
@@ -1,9 +0,0 @@
- ABC
-
-
-
- DEF
-
-
-
-GHI
diff --git a/oldtests/Emphasis/Escapes.html b/oldtests/Emphasis/Escapes.html
deleted file mode 100644
index 17c9e2d..0000000
--- a/oldtests/Emphasis/Escapes.html
+++ /dev/null
@@ -1 +0,0 @@
-<p><em>hi* there</em></p>
diff --git a/oldtests/Emphasis/Escapes.markdown b/oldtests/Emphasis/Escapes.markdown
deleted file mode 100644
index 4f14698..0000000
--- a/oldtests/Emphasis/Escapes.markdown
+++ /dev/null
@@ -1 +0,0 @@
-*hi\* there* \ No newline at end of file
diff --git a/oldtests/Emphasis/NestedEmphAndStrong.html b/oldtests/Emphasis/NestedEmphAndStrong.html
deleted file mode 100644
index b41b527..0000000
--- a/oldtests/Emphasis/NestedEmphAndStrong.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<ol>
-<li><strong><em>test test</em></strong></li>
-<li><strong><em>test test</em></strong></li>
-<li><em>test <strong>test</strong></em></li>
-<li><strong>test <em>test</em></strong></li>
-<li><strong><em>test</em> test</strong></li>
-<li><em><strong>test</strong> test</em></li>
-<li><strong><em>test</em> test</strong></li>
-<li><strong>test <em>test</em></strong></li>
-<li><em>test <strong>test</strong></em></li>
-<li><em>test <strong>test</strong></em></li>
-<li><strong>test <em>test</em></strong></li>
-<li><strong><em>test</em> test</strong></li>
-<li><em><strong>test</strong> test</em></li>
-<li><strong><em>test</em> test</strong></li>
-<li><strong>test <em>test</em></strong></li>
-<li><em>test <strong>test</strong></em></li>
-</ol>
-<p>Incorrect nesting:</p>
-<ol>
-<li>*test <strong>test* test</strong></li>
-<li>_test <strong>test_ test</strong></li>
-<li>**test <em>test</em>* test*</li>
-<li>__test␣<em>test</em>_␣test_</li>
-<li><em>test <em>test</em> test</em></li>
-<li><em>test <em>test</em> test</em></li>
-<li><strong>test <strong>test</strong> test</strong></li>
-<li><strong>test <strong>test</strong> test</strong></li>
-</ol>
-<p>No emphasis:</p>
-<ol>
-<li>test* test *test</li>
-<li>test** test **test</li>
-<li>test_ test _test</li>
-<li>test__ test __test</li>
-</ol>
-<p>Middle-word emphasis (asterisks):</p>
-<ol>
-<li><em>a</em>b</li>
-<li>a<em>b</em></li>
-<li>a<em>b</em>c</li>
-<li><strong>a</strong>b</li>
-<li>a<strong>b</strong></li>
-<li>a<strong>b</strong>c</li>
-</ol>
-<p>Middle-word emphasis (underscore):</p>
-<ol>
-<li>_a_b</li>
-<li>a_b_</li>
-<li>a_b_c</li>
-<li>__a__b</li>
-<li>a__b__</li>
-<li>a__b__c</li>
-<li>my_precious_file.txt</li>
-</ol>
-<p>Tricky Cases:</p>
-<ol>
-<li>E**. <strong>Test</strong> TestTestTest</li>
-<li>E**. <strong>Test</strong> Test Test Test</li>
-</ol>
-<p>Overlong emphasis:</p>
-<p>Name: ____________<br />
-Organization: ____<br />
-Region/Country: __</p>
-<p>_____Cut here_____</p>
-<p>____Cut here____</p>
diff --git a/oldtests/Emphasis/NestedEmphAndStrong.markdown b/oldtests/Emphasis/NestedEmphAndStrong.markdown
deleted file mode 100644
index ec7da25..0000000
--- a/oldtests/Emphasis/NestedEmphAndStrong.markdown
+++ /dev/null
@@ -1,69 +0,0 @@
-1. ***test test***
-2. ___test test___
-3. *test **test***
-4. **test *test***
-5. ***test* test**
-6. ***test** test*
-7. ***test* test**
-8. **test *test***
-9. *test **test***
-10. _test __test___
-11. __test _test___
-12. ___test_ test__
-13. ___test__ test_
-14. ___test_ test__
-15. __test _test___
-16. _test __test___
-
-Incorrect nesting:
-
-1. *test **test* test**
-2. _test __test_ test__
-3. **test *test** test*
-4. __test _test__ test_
-5. *test *test* test*
-6. _test _test_ test_
-7. **test **test** test**
-8. __test __test__ test__
-
-No emphasis:
-
-1. test* test *test
-2. test** test **test
-3. test_ test _test
-4. test__ test __test
-
-Middle-word emphasis (asterisks):
-
-1. *a*b
-2. a*b*
-3. a*b*c
-4. **a**b
-5. a**b**
-6. a**b**c
-
-Middle-word emphasis (underscore):
-
-1. _a_b
-2. a_b_
-3. a_b_c
-4. __a__b
-5. a__b__
-6. a__b__c
-7. my_precious_file.txt
-
-Tricky Cases:
-
-1. E**. **Test** TestTestTest
-2. E**. **Test** Test Test Test
-
-Overlong emphasis:
-
-Name: ____________
-Organization: ____
-Region/Country: __
-
-_____Cut here_____
-
-____Cut here____
-
diff --git a/oldtests/Emphasis/Pathological.html b/oldtests/Emphasis/Pathological.html
deleted file mode 100644
index 37eb9fa..0000000
--- a/oldtests/Emphasis/Pathological.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<p>This input can take a long time to parse in some implementations.</p>
-<p>*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-aaaaa</p>
-<p><em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a**</p>
diff --git a/oldtests/Emphasis/Pathological.markdown b/oldtests/Emphasis/Pathological.markdown
deleted file mode 100644
index 5deb95e..0000000
--- a/oldtests/Emphasis/Pathological.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
-This input can take a long time to parse in some implementations.
-
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-*a
-aaaaa
-
-*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**
diff --git a/oldtests/Emphasis/Punctuation.html b/oldtests/Emphasis/Punctuation.html
deleted file mode 100644
index 6061b81..0000000
--- a/oldtests/Emphasis/Punctuation.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<p>Here is a _ that is <em>cool</em>.</p>
-<p><em>Foo.</em></p>
-<p><strong>Foo.</strong></p>
-<p><strong><em>Foo.</em></strong></p>
-<p><em>Foo</em>.</p>
-<p><strong>Foo</strong>.</p>
-<p><strong><em>Foo</em></strong>.</p>
-<p><em>Foo</em>. <em>Foo</em>? <em>Foo</em>! <em>Foo</em>: <em>Foo</em>; (<em>Foo</em>)</p>
-<p><strong>Foo</strong>. <strong>Foo</strong>? <strong>Foo</strong>! <strong>Foo</strong>: <strong>Foo</strong>; (<strong>Foo</strong>)</p>
-<p><strong><em>Foo</em></strong>. <strong><em>Foo</em></strong>? <strong><em>Foo</em></strong>! <strong><em>Foo</em></strong>: <strong><em>Foo</em></strong>; (<strong><em>Foo</em></strong>)</p>
diff --git a/oldtests/Emphasis/Punctuation.markdown b/oldtests/Emphasis/Punctuation.markdown
deleted file mode 100644
index e3f23b8..0000000
--- a/oldtests/Emphasis/Punctuation.markdown
+++ /dev/null
@@ -1,19 +0,0 @@
-Here is a _ that is _cool_.
-
-_Foo._
-
-__Foo.__
-
-___Foo.___
-
-_Foo_.
-
-__Foo__.
-
-___Foo___.
-
-_Foo_. _Foo_? _Foo_! _Foo_: _Foo_; (_Foo_)
-
-__Foo__. __Foo__? __Foo__! __Foo__: __Foo__; (__Foo__)
-
-___Foo___. ___Foo___? ___Foo___! ___Foo___: ___Foo___; (___Foo___)
diff --git a/oldtests/HTML/Blocks.html b/oldtests/HTML/Blocks.html
deleted file mode 100644
index dc80335..0000000
--- a/oldtests/HTML/Blocks.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<div>
- <div>
- *raw html*
- </div>
-</div>
-<div>
-<div>
-<p><em>this is markdown</em></p>
-</div>
-</div>
-<!-- comment
-here -->
-<!--
-<p><em>commented out markdown</em></p>
--->
-<div>
-* raw html with trailing space
-</div>
diff --git a/oldtests/HTML/Blocks.markdown b/oldtests/HTML/Blocks.markdown
deleted file mode 100644
index a83fa66..0000000
--- a/oldtests/HTML/Blocks.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
-<div>
- <div>
- *raw html*
- </div>
-</div>
-
-<div>
-<div>
-
-*this is markdown*
-
-</div>
-</div>
-
-<!-- comment
-here -->
-
-<!--
-
-*commented out markdown*
-
--->
-
-<div>
-* raw html with trailing space
-</div>
diff --git a/oldtests/HTML/Inline.html b/oldtests/HTML/Inline.html
deleted file mode 100644
index 94d40ac..0000000
--- a/oldtests/HTML/Inline.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<p><span>hi</span>
-<span><code>hi</code></span>
-<span class="foo bar"
-title='whatever' blue=yes/>
-Hello <!-- this
-is a comment --> there.
-A line<br />break.
-<not a tag></p>
diff --git a/oldtests/HTML/Inline.markdown b/oldtests/HTML/Inline.markdown
deleted file mode 100644
index 2259421..0000000
--- a/oldtests/HTML/Inline.markdown
+++ /dev/null
@@ -1,8 +0,0 @@
-<span>hi</span>
-<span>`hi`</span>
-<span class="foo bar"
-title='whatever' blue=yes/>
-Hello <!-- this
-is a comment --> there.
-A line<br />break.
-<not a tag>
diff --git a/oldtests/HTML/UppercaseTags.html b/oldtests/HTML/UppercaseTags.html
deleted file mode 100644
index 8d2d828..0000000
--- a/oldtests/HTML/UppercaseTags.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<DIV>
-this is a block
-</DIV>
-<p>Here is some <I>inline</I> html.</p>
diff --git a/oldtests/HTML/UppercaseTags.markdown b/oldtests/HTML/UppercaseTags.markdown
deleted file mode 100644
index b476ffb..0000000
--- a/oldtests/HTML/UppercaseTags.markdown
+++ /dev/null
@@ -1,5 +0,0 @@
-<DIV>
-this is a block
-</DIV>
-
-Here is some <I>inline</I> html. \ No newline at end of file
diff --git a/oldtests/Headers/ATX.html b/oldtests/Headers/ATX.html
deleted file mode 100644
index f375b98..0000000
--- a/oldtests/Headers/ATX.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<h1>One</h1>
-<h2>Two</h2>
-<h3>Three</h3>
-<h4>Four</h4>
-<h5>Five</h5>
-<h6>Six</h6>
-<p>####### Seven</p>
-<h3>Three with</h3>
-<h2>Spacing doesn't matter</h2>
-<h2>Escaped final #</h2>
-<p>## Not a header</p>
-<p>#5 not a header</p>
-<h2></h2>
-<p>(empty header)</p>
diff --git a/oldtests/Headers/ATX.markdown b/oldtests/Headers/ATX.markdown
deleted file mode 100644
index f687aa5..0000000
--- a/oldtests/Headers/ATX.markdown
+++ /dev/null
@@ -1,20 +0,0 @@
-# One
-## Two
-### Three
-#### Four
-##### Five
-
-###### Six
-
-####### Seven
-
-### Three with ###
-## Spacing doesn't matter ##
-## Escaped final \##
-
-\## Not a header
-
-#5 not a header
-
-##
-(empty header)
diff --git a/oldtests/Headers/Setext.html b/oldtests/Headers/Setext.html
deleted file mode 100644
index 787fb02..0000000
--- a/oldtests/Headers/Setext.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<h1>Level one</h1>
-<h2>Two</h2>
-<p>In a paragraph</p>
-<h2>Level two</h2>
-<p>more text</p>
-<p>======
-no empty headers</p>
-<p>not a header</p>
-<hr />
diff --git a/oldtests/Headers/Setext.markdown b/oldtests/Headers/Setext.markdown
deleted file mode 100644
index da0c7e2..0000000
--- a/oldtests/Headers/Setext.markdown
+++ /dev/null
@@ -1,17 +0,0 @@
-Level one
-=========
-
-Two
----
-
-In a paragraph
-
-Level two
----------
-more text
-
-======
-no empty headers
-
-not a header
------------- -----
diff --git a/oldtests/Links/AngleBrackets.html b/oldtests/Links/AngleBrackets.html
deleted file mode 100644
index 21ac00d..0000000
--- a/oldtests/Links/AngleBrackets.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<p><a href="?}]*+|&amp;)">silly URL with angle brackets</a>.</p>
-<p><a href="url://with spaces" title="title">link</a>.</p>
-<p><a href="url with spaces" title="title">link</a>.</p>
diff --git a/oldtests/Links/AngleBrackets.markdown b/oldtests/Links/AngleBrackets.markdown
deleted file mode 100644
index c2e06ff..0000000
--- a/oldtests/Links/AngleBrackets.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-[silly URL with angle brackets](<?}]*+|&)>).
-
-[link](<url://with spaces> "title").
-
-[link][].
-
-[link]: <url with spaces> "title"
diff --git a/oldtests/Links/AutoLinks.html b/oldtests/Links/AutoLinks.html
deleted file mode 100644
index 092353f..0000000
--- a/oldtests/Links/AutoLinks.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<p><a href="http://google.com?query=blah&amp;time=15">http://google.com?query=blah&amp;time=15</a>
-<a href="mailto:someone.else@somedomain.com">someone.else@somedomain.com</a>
-<a href="ftp://old.ftp.server.edu">ftp://old.ftp.server.edu</a>
-<a href="git://some.git.repo/project.git">git://some.git.repo/project.git</a>
-<not autolink>
-&lt;http://not.an autolink&gt;
-&lt;relative/not/autolink&gt;</p>
diff --git a/oldtests/Links/AutoLinks.markdown b/oldtests/Links/AutoLinks.markdown
deleted file mode 100644
index bf95b8d..0000000
--- a/oldtests/Links/AutoLinks.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-<http://google.com?query=blah&time=15>
-<someone.else@somedomain.com>
-<ftp://old.ftp.server.edu>
-<git://some.git.repo/project.git>
-<not autolink>
-<http://not.an autolink>
-<relative/not/autolink>
diff --git a/oldtests/Links/BackticksInLinks.html b/oldtests/Links/BackticksInLinks.html
deleted file mode 100644
index ff70383..0000000
--- a/oldtests/Links/BackticksInLinks.html
+++ /dev/null
@@ -1 +0,0 @@
-<p><a href="/url">the right bracket character (<code>]</code>)</a></p>
diff --git a/oldtests/Links/BackticksInLinks.markdown b/oldtests/Links/BackticksInLinks.markdown
deleted file mode 100644
index 539fd52..0000000
--- a/oldtests/Links/BackticksInLinks.markdown
+++ /dev/null
@@ -1 +0,0 @@
-[the right bracket character (`]`)](/url)
diff --git a/oldtests/Links/CaseInsensitiveReferences.html b/oldtests/Links/CaseInsensitiveReferences.html
deleted file mode 100644
index afe4557..0000000
--- a/oldtests/Links/CaseInsensitiveReferences.html
+++ /dev/null
@@ -1 +0,0 @@
-<p><a href="/url">Толпой</a> is a Russian word.</p>
diff --git a/oldtests/Links/CaseInsensitiveReferences.markdown b/oldtests/Links/CaseInsensitiveReferences.markdown
deleted file mode 100644
index f9653b9..0000000
--- a/oldtests/Links/CaseInsensitiveReferences.markdown
+++ /dev/null
@@ -1,3 +0,0 @@
-[Толпой] is a Russian word.
-
-[ТОЛПОЙ]: /url
diff --git a/oldtests/Links/Entities.html b/oldtests/Links/Entities.html
deleted file mode 100644
index 252dadb..0000000
--- a/oldtests/Links/Entities.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<p><a href="http://g&ouml;&ouml;gle.com">http://g&ouml;&ouml;gle.com</a></p>
-<p><a href="/url" title="g&ouml;&ouml;gle &amp; yahoo">hi</a></p>
diff --git a/oldtests/Links/Entities.markdown b/oldtests/Links/Entities.markdown
deleted file mode 100644
index d81ee36..0000000
--- a/oldtests/Links/Entities.markdown
+++ /dev/null
@@ -1,3 +0,0 @@
-<http://g&ouml;&ouml;gle.com>
-
-[hi](/url "g&ouml;&ouml;gle & yahoo")
diff --git a/oldtests/Links/InlineLinks.html b/oldtests/Links/InlineLinks.html
deleted file mode 100644
index ae33f33..0000000
--- a/oldtests/Links/InlineLinks.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<ol>
-<li><a href="/url">link</a></li>
-<li><a href="/url" title="title">link</a></li>
-<li><a href="/url" title="title">link</a></li>
-<li><a href="/url with spaces" title="title
-with linebreak">link <em>with
-linebreak</em></a>.</li>
-<li><a href="/url(withparens)" title="and single quoted title">link</a></li>
-<li>[not a link] (/url)</li>
-</ol>
diff --git a/oldtests/Links/InlineLinks.markdown b/oldtests/Links/InlineLinks.markdown
deleted file mode 100644
index a822c4d..0000000
--- a/oldtests/Links/InlineLinks.markdown
+++ /dev/null
@@ -1,9 +0,0 @@
-1. [link](/url)
-2. [link](/url "title")
-3. [link](/url
- "title")
-4. [link *with
-linebreak*](</url with spaces> "title
-with linebreak").
-5. [link](/url(withparens) 'and single quoted title')
-6. [not a link] (/url)
diff --git a/oldtests/Links/ParensInURLs.html b/oldtests/Links/ParensInURLs.html
deleted file mode 100644
index 9cd6de7..0000000
--- a/oldtests/Links/ParensInURLs.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<p><a href="/url(test)" title="title">Inline link 1 with parens</a>.</p>
-<p><a href="/url(test)" title="title">Inline link 2 with parens</a>.</p>
-<p><a href="/url(test)" title="title">Inline link 3 with non-escaped parens</a>.</p>
-<p><a href="/url(test)" title="title">Inline link 4 with non-escaped parens</a>.</p>
-<p><a href="/url(test)" title="title">Reference link 1 with parens</a>.</p>
-<p><a href="/url(test)" title="title">Reference link 2 with parens</a>.</p>
diff --git a/oldtests/Links/ParensInURLs.markdown b/oldtests/Links/ParensInURLs.markdown
deleted file mode 100644
index bb7be4f..0000000
--- a/oldtests/Links/ParensInURLs.markdown
+++ /dev/null
@@ -1,14 +0,0 @@
-[Inline link 1 with parens](/url\(test\) "title").
-
-[Inline link 2 with parens](</url\(test\)> "title").
-
-[Inline link 3 with non-escaped parens](/url(test) "title").
-
-[Inline link 4 with non-escaped parens](</url(test)> "title").
-
-[Reference link 1 with parens][1].
-
-[Reference link 2 with parens][2].
-
- [1]: /url(test) "title"
- [2]: </url(test)> "title"
diff --git a/oldtests/Links/ReferenceLinks.html b/oldtests/Links/ReferenceLinks.html
deleted file mode 100644
index 397cdb2..0000000
--- a/oldtests/Links/ReferenceLinks.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<ol>
-<li><p><a href="/url" title="even in a list item">Link references</a> can be defined anywhere.</p></li>
-</ol>
-<blockquote>
-<p><a href="/foo" title="can break
-lines">another</a> one</p>
-</blockquote>
diff --git a/oldtests/Links/ReferenceLinks.markdown b/oldtests/Links/ReferenceLinks.markdown
deleted file mode 100644
index ebcf5a9..0000000
--- a/oldtests/Links/ReferenceLinks.markdown
+++ /dev/null
@@ -1,10 +0,0 @@
-1. [Link references] can be defined anywhere.
-
- [Link references]: /url
- (even in a list item)
-
-> [another] one
->
-> [another]:
-> /foo "can break
-> lines"
diff --git a/oldtests/Lists/CodeBlocksInLists.html b/oldtests/Lists/CodeBlocksInLists.html
deleted file mode 100644
index fcd3e2a..0000000
--- a/oldtests/Lists/CodeBlocksInLists.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<ol>
-<li><p>list item
-code</p></li>
-<li><p>list item</p>
-<pre><code>code
-</code></pre></li>
-<li><pre><code>code
-</code></pre></li>
-<li><pre><code>code
-</code></pre></li>
-<li><pre><code>code
-code
-</code></pre></li>
-</ol>
diff --git a/oldtests/Lists/CodeBlocksInLists.markdown b/oldtests/Lists/CodeBlocksInLists.markdown
deleted file mode 100644
index 7730808..0000000
--- a/oldtests/Lists/CodeBlocksInLists.markdown
+++ /dev/null
@@ -1,18 +0,0 @@
-1. list item
- code
-
-2. list item
- ~~~
- code
- ~~~
-
-3. ~~~
- code
- ~~~
-
-4. ~~~
- code
- ~~~
-
-5. code
- code
diff --git a/oldtests/Lists/ConsecutiveLists.html b/oldtests/Lists/ConsecutiveLists.html
deleted file mode 100644
index f8f9098..0000000
--- a/oldtests/Lists/ConsecutiveLists.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<ul>
-<li>one</li>
-<li>one</li>
-</ul>
-<ul>
-<li>two</li>
-<li>two</li>
-</ul>
-<ul>
-<li>three</li>
-<li>three</li>
-</ul>
-<ol>
-<li>four</li>
-<li>four</li>
-</ol>
-<ol>
-<li>five</li>
-<li>five</li>
-</ol>
diff --git a/oldtests/Lists/ConsecutiveLists.markdown b/oldtests/Lists/ConsecutiveLists.markdown
deleted file mode 100644
index c4faa54..0000000
--- a/oldtests/Lists/ConsecutiveLists.markdown
+++ /dev/null
@@ -1,10 +0,0 @@
-* one
-* one
-+ two
-+ two
-- three
-- three
-1. four
-1. four
-1) five
-1) five
diff --git a/oldtests/Lists/EmptyListItem.html b/oldtests/Lists/EmptyListItem.html
deleted file mode 100644
index 2c23fe1..0000000
--- a/oldtests/Lists/EmptyListItem.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<ul>
-<li>one</li>
-<li></li>
-<li>three</li>
-</ul>
-<ol>
-<li>one</li>
-<li></li>
-<li>three</li>
-</ol>
diff --git a/oldtests/Lists/EmptyListItem.markdown b/oldtests/Lists/EmptyListItem.markdown
deleted file mode 100644
index d30cbc3..0000000
--- a/oldtests/Lists/EmptyListItem.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-- one
--
-- three
-
-1. one
-2.
-3. three
diff --git a/oldtests/Lists/InBlockquote.html b/oldtests/Lists/InBlockquote.html
deleted file mode 100644
index da233e8..0000000
--- a/oldtests/Lists/InBlockquote.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<blockquote>
-<ul>
-<li>tight</li>
-<li>tight</li>
-</ul>
-</blockquote>
-<blockquote>
-<ul>
-<li><p>loose</p></li>
-<li><p>loose</p></li>
-</ul>
-</blockquote>
-<blockquote>
-<ul>
-<li>one-item list</li>
-</ul>
-</blockquote>
-<blockquote>
-<ul>
-<li>one-item list</li>
-</ul>
-</blockquote>
diff --git a/oldtests/Lists/InBlockquote.markdown b/oldtests/Lists/InBlockquote.markdown
deleted file mode 100644
index 511563b..0000000
--- a/oldtests/Lists/InBlockquote.markdown
+++ /dev/null
@@ -1,12 +0,0 @@
-> - tight
-> - tight
-
-
-> - loose
->
-> - loose
-
-
-> - one-item list
-
-> - one-item list
diff --git a/oldtests/Lists/Indents.html b/oldtests/Lists/Indents.html
deleted file mode 100644
index a11a5a6..0000000
--- a/oldtests/Lists/Indents.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<blockquote>
-<ul>
-<li><p>foo</p>
-<p>bar</p></li>
-</ul>
-</blockquote>
-<ul>
-<li>one</li>
-<li>two</li>
-</ul>
-<ul>
-<li>one</li>
-<li>two</li>
-<li>three</li>
-</ul>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-<li>three</li>
-</ul>
diff --git a/oldtests/Lists/Indents.markdown b/oldtests/Lists/Indents.markdown
deleted file mode 100644
index 293d112..0000000
--- a/oldtests/Lists/Indents.markdown
+++ /dev/null
@@ -1,17 +0,0 @@
- > * foo
->
-> bar
-
-
- - one
- - two
-
-
-- one
- - two
-- three
-
-
-- one
- - two
-- three
diff --git a/oldtests/Lists/ListsAndHRs.html b/oldtests/Lists/ListsAndHRs.html
deleted file mode 100644
index 40826f7..0000000
--- a/oldtests/Lists/ListsAndHRs.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<ul>
-<li>item 1
-<ul>
-<li>item 2</li>
-</ul></li>
-</ul>
-<hr />
diff --git a/oldtests/Lists/ListsAndHRs.markdown b/oldtests/Lists/ListsAndHRs.markdown
deleted file mode 100644
index 19c07e7..0000000
--- a/oldtests/Lists/ListsAndHRs.markdown
+++ /dev/null
@@ -1,3 +0,0 @@
-* item 1
- * item 2
-* * * * *
diff --git a/oldtests/Lists/ListsAndSetextHeaders.html b/oldtests/Lists/ListsAndSetextHeaders.html
deleted file mode 100644
index c6af9eb..0000000
--- a/oldtests/Lists/ListsAndSetextHeaders.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<ol>
-<li>item</li>
-<li>item
-Not header</li>
-</ol>
-<hr />
diff --git a/oldtests/Lists/ListsAndSetextHeaders.markdown b/oldtests/Lists/ListsAndSetextHeaders.markdown
deleted file mode 100644
index acfa655..0000000
--- a/oldtests/Lists/ListsAndSetextHeaders.markdown
+++ /dev/null
@@ -1,4 +0,0 @@
-1. item
-2. item
-Not header
-----------
diff --git a/oldtests/Lists/MultipleBlankLines.html b/oldtests/Lists/MultipleBlankLines.html
deleted file mode 100644
index d894db1..0000000
--- a/oldtests/Lists/MultipleBlankLines.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<ol>
-<li><p>First Item</p>
-<ul>
-<li><p>one</p>
-<ul>
-<li>two</li>
-</ul></li>
-<li><p>one</p>
-<ul>
-<li>two</li>
-</ul></li>
-</ul></li>
-<li><p>Second Item</p>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul></li>
-</ol>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul>
-<ol>
-<li><p>Third Item</p>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul></li>
-</ol>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul>
-<ol>
-<li><p>Fourth Item</p>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul></li>
-</ol>
-<ul>
-<li>one
-<ul>
-<li>two</li>
-</ul></li>
-</ul>
diff --git a/oldtests/Lists/MultipleBlankLines.markdown b/oldtests/Lists/MultipleBlankLines.markdown
deleted file mode 100644
index e24a4f2..0000000
--- a/oldtests/Lists/MultipleBlankLines.markdown
+++ /dev/null
@@ -1,37 +0,0 @@
-1. First Item
-
- * one
- * two
-
- * one
- * two
-
-1. Second Item
-
- * one
- * two
-
-
- * one
- * two
-
-1. Third Item
-
- * one
- * two
-
-
-
- * one
- * two
-
-1. Fourth Item
-
- * one
- * two
-
-
-
-
- * one
- * two
diff --git a/oldtests/Lists/Start.html b/oldtests/Lists/Start.html
deleted file mode 100644
index 46e0550..0000000
--- a/oldtests/Lists/Start.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<ol start="4">
-<li>this list starts with 4.</li>
-<li>and continues</li>
-<li>the continuation number is irrelevant.</li>
-</ol>
-<ol start="2001">
-<li>a space odyssey</li>
-</ol>
-<ol>
-<li>standard lists get no start attribute</li>
-</ol>
diff --git a/oldtests/Lists/Start.markdown b/oldtests/Lists/Start.markdown
deleted file mode 100644
index 175226f..0000000
--- a/oldtests/Lists/Start.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-4. this list starts with 4.
-5. and continues
-1. the continuation number is irrelevant.
-
-2001) a space odyssey
-
-1. standard lists get no start attribute
diff --git a/oldtests/Lists/Sublists.html b/oldtests/Lists/Sublists.html
deleted file mode 100644
index af62915..0000000
--- a/oldtests/Lists/Sublists.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<p>Four levels:</p>
-<ul>
-<li>one
-<ul>
-<li>two
-<ul>
-<li>three
-<ul>
-<li>four</li>
-</ul></li>
-</ul></li>
-</ul></li>
-</ul>
-<ol>
-<li>one
-<ol>
-<li>two
-<ol>
-<li>three
-<ol>
-<li>four</li>
-</ol></li>
-</ol></li>
-</ol></li>
-</ol>
-<ol>
-<li>one
-<ul>
-<li>two
-<ol>
-<li>three
-<ul>
-<li>four</li>
-</ul></li>
-</ol></li>
-</ul></li>
-</ol>
-<ul>
-<li>one
-<ul>
-<li>two
-<ol>
-<li>three
-<ol>
-<li>four</li>
-</ol></li>
-</ol></li>
-</ul></li>
-</ul>
diff --git a/oldtests/Lists/Sublists.markdown b/oldtests/Lists/Sublists.markdown
deleted file mode 100644
index 9eced9e..0000000
--- a/oldtests/Lists/Sublists.markdown
+++ /dev/null
@@ -1,24 +0,0 @@
-Four levels:
-
-- one
- - two
- - three
- - four
-
-
-1. one
- 1. two
- 1. three
- 1. four
-
-
-1) one
- - two
- 1) three
- - four
-
-
-- one
- - two
- 1. three
- 1) four
diff --git a/oldtests/Lists/TightAndLoose.html b/oldtests/Lists/TightAndLoose.html
deleted file mode 100644
index 7792ebb..0000000
--- a/oldtests/Lists/TightAndLoose.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<ol>
-<li>tight</li>
-</ol>
-<ul>
-<li>tight</li>
-<li>list</li>
-</ul>
-<ul>
-<li><p>loose</p></li>
-<li><p>list</p></li>
-</ul>
-<ol>
-<li>tight</li>
-<li>list</li>
-</ol>
-<ol>
-<li><p>loose</p></li>
-<li><p>list</p></li>
-</ol>
-<ol>
-<li><p>loose</p>
-<ul>
-<li>sublist</li>
-</ul></li>
-</ol>
-<ol>
-<li>tight
-<ul>
-<li>sublist</li>
-</ul></li>
-</ol>
-<ul>
-<li>tight
-<blockquote>
-<p>blockquote
-and</p>
-</blockquote>
-<pre><code>code
-</code></pre></li>
-<li>tight</li>
-</ul>
-<ul>
-<li>tight
-<ul>
-<li><p>with loose</p></li>
-<li><p>sublist</p></li>
-</ul></li>
-<li>tight</li>
-</ul>
diff --git a/oldtests/Lists/TightAndLoose.markdown b/oldtests/Lists/TightAndLoose.markdown
deleted file mode 100644
index 263a34c..0000000
--- a/oldtests/Lists/TightAndLoose.markdown
+++ /dev/null
@@ -1,45 +0,0 @@
-1. tight
-
-
-- tight
-- list
-
-
-- loose
-
-- list
-
-
-1. tight
-2. list
-
-
-1. loose
-
-2. list
-
-
-1. loose
-
- - sublist
-
-
-
-1. tight
- - sublist
-
-
-- tight
- > blockquote
- and
- ```
- code
- ```
-- tight
-
-
-- tight
- - with loose
-
- - sublist
-- tight
diff --git a/oldtests/Lists/TightLooseBlockquote.html b/oldtests/Lists/TightLooseBlockquote.html
deleted file mode 100644
index 7e78214..0000000
--- a/oldtests/Lists/TightLooseBlockquote.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<ul>
-<li>tight I
-<blockquote>
-<p>bq</p>
-</blockquote></li>
-<li>tight I</li>
-</ul>
-<ul>
-<li>tight II
-<blockquote>
-<p>bq</p>
-</blockquote>
-foo</li>
-<li>tight II</li>
-</ul>
-<ol>
-<li>Blank lines in bq don't break list
-<blockquote>
-<p>bq</p>
-</blockquote></li>
-<li>Should say (2) in output</li>
-</ol>
-<ul>
-<li>Blank lines in bq don't break LI
-<ul>
-<li>item A
-<blockquote>
-<p>bq</p>
-</blockquote></li>
-<li>item B</li>
-</ul></li>
-</ul>
diff --git a/oldtests/Lists/TightLooseBlockquote.markdown b/oldtests/Lists/TightLooseBlockquote.markdown
deleted file mode 100644
index 08200cc..0000000
--- a/oldtests/Lists/TightLooseBlockquote.markdown
+++ /dev/null
@@ -1,25 +0,0 @@
-* tight I
- > bq
- >
-* tight I
-
-
-* tight II
- > bq
- >
- foo
-* tight II
-
-1. Blank lines in bq don't break list
- > bq
- >
- >
-1. Should say (2) in output
-
-* Blank lines in bq don't break LI
- * item A
- > bq
- >
- >
- * item B
- \ No newline at end of file
diff --git a/oldtests/Lists/TightLooseMore.html b/oldtests/Lists/TightLooseMore.html
deleted file mode 100644
index f26f457..0000000
--- a/oldtests/Lists/TightLooseMore.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<ul>
-<li><p>foo</p>
-<ul>
-<li>bar</li>
-</ul>
-<p>blah</p></li>
-</ul>
diff --git a/oldtests/Lists/TightLooseMore.markdown b/oldtests/Lists/TightLooseMore.markdown
deleted file mode 100644
index 7ace63f..0000000
--- a/oldtests/Lists/TightLooseMore.markdown
+++ /dev/null
@@ -1,4 +0,0 @@
-* foo
- * bar
-
- blah \ No newline at end of file
diff --git a/oldtests/Lists/TwoBlankLinesEndList.html b/oldtests/Lists/TwoBlankLinesEndList.html
deleted file mode 100644
index 629add1..0000000
--- a/oldtests/Lists/TwoBlankLinesEndList.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<ol>
-<li><p>one</p></li>
-<li><p>two</p></li>
-</ol>
-<ol>
-<li>new list</li>
-</ol>
-<blockquote>
-<ul>
-<li><p>one</p></li>
-<li><p>two</p></li>
-</ul>
-<ul>
-<li>new list</li>
-</ul>
-</blockquote>
-<ol>
-<li>one</li>
-</ol>
-<pre><code>code
-</code></pre>
diff --git a/oldtests/Lists/TwoBlankLinesEndList.markdown b/oldtests/Lists/TwoBlankLinesEndList.markdown
deleted file mode 100644
index 2984a19..0000000
--- a/oldtests/Lists/TwoBlankLinesEndList.markdown
+++ /dev/null
@@ -1,20 +0,0 @@
-1. one
-
-2. two
-
-
-1. new list
-
-
-> - one
->
-> - two
->
->
-> - new list
-
-
-1. one
-
-
- code
diff --git a/oldtests/Makefile b/oldtests/Makefile
deleted file mode 100644
index c8a30bd..0000000
--- a/oldtests/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-SHELL=/bin/bash
-TESTDIR ?= *
-PATT ?= .
-TESTS=$(shell ls $(TESTDIR)/*.markdown | grep $(PATT))
-DIFFS=$(patsubst %.markdown,%.diff,$(TESTS))
-PROG ?= ../stmd
-FILTER ?= perl -pe 's/ /␣/g'
-TIDYCMD ?= tidy -asxhtml -utf8 --show-body-only yes --show-warnings no -quiet
-DETAILS ?= 1
-
-# Check to see if echo supports -e option to allow backslash escapes
-ifeq ($(shell echo -e),-e)
-ECHO=echo
-else
-ECHO=echo -e
-endif
-
-all: $(DIFFS)
- PASS=0;TESTS=0; \
- for f in $(DIFFS); do \
- let TESTS=TESTS+1; \
- [ -s $$f ] || let PASS=PASS+1; \
- done; \
- $(ECHO) "\033[1m$$PASS of $$TESTS tests passed.\033[0m"; \
- if [ $$TESTS -eq $$PASS ]; then exit 0; else exit 1; fi
-
-%.actual.html: %.markdown
-ifeq ($(TIDY),1)
- -cat $< | $(PROG) | $(TIDYCMD) > $@
-else
- -cat $< | $(PROG) > $@
-endif
-
-%.expected.html: %.html
-ifeq ($(TIDY),1)
- -$(TIDYCMD) $< > $@
-else
- cp $< $@
-endif
-
-%.diff: %.expected.html %.actual.html
- diff --unified=1 <(cat $(word 1,$^) | $(FILTER)) <(cat $(word 2,$^) | $(FILTER)) > $@ ; \
- if [ -s $@ ]; then \
- $(ECHO) "\033[1;31m✘ $(patsubst %.diff,%,$@)\033[0m"; \
- if [ $(DETAILS) == "1" ]; then \
- $(ECHO) "\033[0;36m" ; cat $@; $(ECHO) "\033[0m"; \
- fi \
- else \
- $(ECHO) "\033[1;32m✓ $(patsubst %.diff,%,$@)\033[0m"; \
- fi
-
-.PHONY: all clean
-
-clean:
- -@rm */*.{diff,actual.html,expected.html}
diff --git a/oldtests/Misc/BackslashEscapes.html b/oldtests/Misc/BackslashEscapes.html
deleted file mode 100644
index 3eb2aed..0000000
--- a/oldtests/Misc/BackslashEscapes.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<p>*not emphasized*
-\<em>emphasis</em>
-**not bold**
-&lt;br/&gt; not a tag
-[link](/foo) not a link
-<a href="/foo)" title="title&quot;">link</a>
-`not code`</p>
-<p>1. not a list item</p>
-<p>* not a list.</p>
-<p># Not a header</p>
-<p>[foo]: /url &quot;not a reference&quot;</p>
-<p>$ ^ ; can be escaped.
-\a \b \T cannot.
-unicode letters and symbols cannot: \π \‥.</p>
diff --git a/oldtests/Misc/BackslashEscapes.markdown b/oldtests/Misc/BackslashEscapes.markdown
deleted file mode 100644
index 23496dc..0000000
--- a/oldtests/Misc/BackslashEscapes.markdown
+++ /dev/null
@@ -1,19 +0,0 @@
-\*not emphasized*
-\\*emphasis*
-\*\*not bold**
-\<br/> not a tag
-\[link](/foo) not a link
-[link](/foo\) "title\"")
-\`not code`
-
-1\. not a list item
-
-\* not a list.
-
-\# Not a header
-
-\[foo]: /url "not a reference"
-
-\$ \^ \; can be escaped.
-\a \b \T cannot.
-unicode letters and symbols cannot: \π \‥.
diff --git a/oldtests/Misc/Laziness.html b/oldtests/Misc/Laziness.html
deleted file mode 100644
index e130eb5..0000000
--- a/oldtests/Misc/Laziness.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<blockquote>
-<ol>
-<li>one
-two</li>
-</ol>
-</blockquote>
-<p>Laziness only affects paragraph continuations:</p>
-<blockquote>
-<pre><code>code
-</code></pre>
-</blockquote>
-<pre><code>not same code block
-</code></pre>
-<ol>
-<li>hello</li>
-</ol>
-<hr />
-<blockquote>
-<pre><code></code></pre>
-</blockquote>
-<p>code</p>
-<pre><code></code></pre>
diff --git a/oldtests/Misc/Laziness.markdown b/oldtests/Misc/Laziness.markdown
deleted file mode 100644
index 2c32870..0000000
--- a/oldtests/Misc/Laziness.markdown
+++ /dev/null
@@ -1,14 +0,0 @@
-> 1. one
-> two
-
-Laziness only affects paragraph continuations:
-
-> code
- not same code block
-
-1. hello
------
-
-> ```
-code
-```
diff --git a/oldtests/Misc/LineBreaks.html b/oldtests/Misc/LineBreaks.html
deleted file mode 100644
index 2d85e85..0000000
--- a/oldtests/Misc/LineBreaks.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<p>Two spaces<br />
-break a line. Or more than two<br />
-and spaces in the following line are absorbed.</p>
-<p>You can also break lines with<br />
-a backslash.</p>
-<p>Two spaces at the end of a paragraph are
-not a line break.</p>
-<p>A backslash at the end of a paragraph is
-not a line break.\</p>
-<h2>Similarly with setext headers</h2>
-<h2>And with backslashes\</h2>
diff --git a/oldtests/Misc/LineBreaks.markdown b/oldtests/Misc/LineBreaks.markdown
deleted file mode 100644
index 3632dcb..0000000
--- a/oldtests/Misc/LineBreaks.markdown
+++ /dev/null
@@ -1,18 +0,0 @@
-Two spaces
-break a line. Or more than two
- and spaces in the following line are absorbed.
-
-You can also break lines with\
-a backslash.
-
-Two spaces at the end of a paragraph are
-not a line break.
-
-A backslash at the end of a paragraph is
-not a line break.\
-
-Similarly with setext headers
--------------------------------
-
-And with backslashes\
----------------------
diff --git a/oldtests/Misc/Transitions.html b/oldtests/Misc/Transitions.html
deleted file mode 100644
index fceff9f..0000000
--- a/oldtests/Misc/Transitions.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<blockquote>
-<p>blockquote</p>
-<blockquote>
-<p>blockquote</p>
-</blockquote>
-</blockquote>
-<ol>
-<li>list</li>
-<li>list
-<ul>
-<li>sublist</li>
-</ul></li>
-</ol>
-<hr />
-<p>paragraph</p>
-<h2>header</h2>
-<h3>header</h3>
-<pre><code>code
-</code></pre>
-<pre><code>code
-</code></pre>
-<div>
- <div>
-# not a header
- </div>
-</div>
diff --git a/oldtests/Misc/Transitions.markdown b/oldtests/Misc/Transitions.markdown
deleted file mode 100644
index 5f3a9d3..0000000
--- a/oldtests/Misc/Transitions.markdown
+++ /dev/null
@@ -1,20 +0,0 @@
-> blockquote
-> > blockquote
-1. list
-2. list
- - sublist
-* * * * *
-paragraph
-
-header
-------
-### header
- code
-```
-code
-```
-<div>
- <div>
-# not a header
- </div>
-</div>
diff --git a/oldtests/Original/Amps_and_angle_encoding.html b/oldtests/Original/Amps_and_angle_encoding.html
deleted file mode 100644
index fc1b2c3..0000000
--- a/oldtests/Original/Amps_and_angle_encoding.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<p>AT&amp;T has an ampersand in their name.</p>
-<p>AT&amp;T is another way to write it.</p>
-<p>This &amp; that.</p>
-<p>4 &lt; 5.</p>
-<p>6 &gt; 5.</p>
-<p>Here's a <a href="http://example.com/?foo=1&amp;bar=2">link</a> with an ampersand in the URL.</p>
-<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>
-<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
-<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
diff --git a/oldtests/Original/Amps_and_angle_encoding.markdown b/oldtests/Original/Amps_and_angle_encoding.markdown
deleted file mode 100644
index 0e9527f..0000000
--- a/oldtests/Original/Amps_and_angle_encoding.markdown
+++ /dev/null
@@ -1,21 +0,0 @@
-AT&T has an ampersand in their name.
-
-AT&amp;T is another way to write it.
-
-This & that.
-
-4 < 5.
-
-6 > 5.
-
-Here's a [link] [1] with an ampersand in the URL.
-
-Here's a link with an amersand in the link text: [AT&T] [2].
-
-Here's an inline [link](/script?foo=1&bar=2).
-
-Here's an inline [link](</script?foo=1&bar=2>).
-
-
-[1]: http://example.com/?foo=1&bar=2
-[2]: http://att.com/ "AT&T" \ No newline at end of file
diff --git a/oldtests/Original/Auto_links.html b/oldtests/Original/Auto_links.html
deleted file mode 100644
index f517fe6..0000000
--- a/oldtests/Original/Auto_links.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<p>Link: <a href="http://example.com/">http://example.com/</a>.</p>
-<p>With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>
-<ul>
-<li>In a list?</li>
-<li><a href="http://example.com/">http://example.com/</a></li>
-<li>It should.</li>
-</ul>
-<blockquote>
-<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>
-</blockquote>
-<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
-<pre><code>or here: &lt;http://example.com/&gt;
-</code></pre>
diff --git a/oldtests/Original/Auto_links.markdown b/oldtests/Original/Auto_links.markdown
deleted file mode 100644
index abbc488..0000000
--- a/oldtests/Original/Auto_links.markdown
+++ /dev/null
@@ -1,13 +0,0 @@
-Link: <http://example.com/>.
-
-With an ampersand: <http://example.com/?foo=1&bar=2>
-
-* In a list?
-* <http://example.com/>
-* It should.
-
-> Blockquoted: <http://example.com/>
-
-Auto-links should not occur here: `<http://example.com/>`
-
- or here: <http://example.com/> \ No newline at end of file
diff --git a/oldtests/Original/Backslash_escapes.html b/oldtests/Original/Backslash_escapes.html
deleted file mode 100644
index 9a83379..0000000
--- a/oldtests/Original/Backslash_escapes.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<p>These should all get escaped:</p>
-<p>Backslash: \</p>
-<p>Backtick: `</p>
-<p>Asterisk: *</p>
-<p>Underscore: _</p>
-<p>Left brace: {</p>
-<p>Right brace: }</p>
-<p>Left bracket: [</p>
-<p>Right bracket: ]</p>
-<p>Left paren: (</p>
-<p>Right paren: )</p>
-<p>Greater-than: &gt;</p>
-<p>Hash: #</p>
-<p>Period: .</p>
-<p>Bang: !</p>
-<p>Plus: +</p>
-<p>Minus: -</p>
-<p>These should not, because they occur within a code block:</p>
-<pre><code>Backslash: \\
-
-Backtick: \`
-
-Asterisk: \*
-
-Underscore: \_
-
-Left brace: \{
-
-Right brace: \}
-
-Left bracket: \[
-
-Right bracket: \]
-
-Left paren: \(
-
-Right paren: \)
-
-Greater-than: \&gt;
-
-Hash: \#
-
-Period: \.
-
-Bang: \!
-
-Plus: \+
-
-Minus: \-
-</code></pre>
-<p>Nor should these, which occur in code spans:</p>
-<p>Backslash: <code>\\</code></p>
-<p>Backtick: <code>\`</code></p>
-<p>Asterisk: <code>\*</code></p>
-<p>Underscore: <code>\_</code></p>
-<p>Left brace: <code>\{</code></p>
-<p>Right brace: <code>\}</code></p>
-<p>Left bracket: <code>\[</code></p>
-<p>Right bracket: <code>\]</code></p>
-<p>Left paren: <code>\(</code></p>
-<p>Right paren: <code>\)</code></p>
-<p>Greater-than: <code>\&gt;</code></p>
-<p>Hash: <code>\#</code></p>
-<p>Period: <code>\.</code></p>
-<p>Bang: <code>\!</code></p>
-<p>Plus: <code>\+</code></p>
-<p>Minus: <code>\-</code></p>
-<p>These should get escaped, even though they're matching pairs for
-other Markdown constructs:</p>
-<p>*asterisks*</p>
-<p>_underscores_</p>
-<p>`backticks`</p>
-<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p>
-<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>
-<p>This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.</p>
diff --git a/oldtests/Original/Backslash_escapes.markdown b/oldtests/Original/Backslash_escapes.markdown
deleted file mode 100644
index 5b014cb..0000000
--- a/oldtests/Original/Backslash_escapes.markdown
+++ /dev/null
@@ -1,120 +0,0 @@
-These should all get escaped:
-
-Backslash: \\
-
-Backtick: \`
-
-Asterisk: \*
-
-Underscore: \_
-
-Left brace: \{
-
-Right brace: \}
-
-Left bracket: \[
-
-Right bracket: \]
-
-Left paren: \(
-
-Right paren: \)
-
-Greater-than: \>
-
-Hash: \#
-
-Period: \.
-
-Bang: \!
-
-Plus: \+
-
-Minus: \-
-
-
-
-These should not, because they occur within a code block:
-
- Backslash: \\
-
- Backtick: \`
-
- Asterisk: \*
-
- Underscore: \_
-
- Left brace: \{
-
- Right brace: \}
-
- Left bracket: \[
-
- Right bracket: \]
-
- Left paren: \(
-
- Right paren: \)
-
- Greater-than: \>
-
- Hash: \#
-
- Period: \.
-
- Bang: \!
-
- Plus: \+
-
- Minus: \-
-
-
-Nor should these, which occur in code spans:
-
-Backslash: `\\`
-
-Backtick: `` \` ``
-
-Asterisk: `\*`
-
-Underscore: `\_`
-
-Left brace: `\{`
-
-Right brace: `\}`
-
-Left bracket: `\[`
-
-Right bracket: `\]`
-
-Left paren: `\(`
-
-Right paren: `\)`
-
-Greater-than: `\>`
-
-Hash: `\#`
-
-Period: `\.`
-
-Bang: `\!`
-
-Plus: `\+`
-
-Minus: `\-`
-
-
-These should get escaped, even though they're matching pairs for
-other Markdown constructs:
-
-\*asterisks\*
-
-\_underscores\_
-
-\`backticks\`
-
-This is a code span with a literal backslash-backtick sequence: `` \` ``
-
-This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.
-
-This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.
diff --git a/oldtests/Original/Blockquotes_with_code_blocks.html b/oldtests/Original/Blockquotes_with_code_blocks.html
deleted file mode 100644
index fd1cb1b..0000000
--- a/oldtests/Original/Blockquotes_with_code_blocks.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<blockquote>
-<p>Example:</p>
-<pre><code>sub status {
- print &quot;working&quot;;
-}
-</code></pre>
-<p>Or:</p>
-<pre><code>sub status {
- return &quot;working&quot;;
-}
-</code></pre>
-</blockquote>
diff --git a/oldtests/Original/Blockquotes_with_code_blocks.markdown b/oldtests/Original/Blockquotes_with_code_blocks.markdown
deleted file mode 100644
index c31d171..0000000
--- a/oldtests/Original/Blockquotes_with_code_blocks.markdown
+++ /dev/null
@@ -1,11 +0,0 @@
-> Example:
->
-> sub status {
-> print "working";
-> }
->
-> Or:
->
-> sub status {
-> return "working";
-> }
diff --git a/oldtests/Original/Code_Blocks.html b/oldtests/Original/Code_Blocks.html
deleted file mode 100644
index 7d89615..0000000
--- a/oldtests/Original/Code_Blocks.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<pre><code>code block on the first line
-</code></pre>
-<p>Regular text.</p>
-<pre><code>code block indented by spaces
-</code></pre>
-<p>Regular text.</p>
-<pre><code>the lines in this block
-all contain trailing spaces
-</code></pre>
-<p>Regular Text.</p>
-<pre><code>code block on the last line
-</code></pre>
diff --git a/oldtests/Original/Code_Blocks.markdown b/oldtests/Original/Code_Blocks.markdown
deleted file mode 100644
index b54b092..0000000
--- a/oldtests/Original/Code_Blocks.markdown
+++ /dev/null
@@ -1,14 +0,0 @@
- code block on the first line
-
-Regular text.
-
- code block indented by spaces
-
-Regular text.
-
- the lines in this block
- all contain trailing spaces
-
-Regular Text.
-
- code block on the last line \ No newline at end of file
diff --git a/oldtests/Original/Code_Spans.html b/oldtests/Original/Code_Spans.html
deleted file mode 100644
index 27acea1..0000000
--- a/oldtests/Original/Code_Spans.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<p><code>&lt;test a=&quot;</code> content of attribute <code>&quot;&gt;</code></p>
-<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>
-<p>Here's how you put <code>`backticks`</code> in a code span.</p>
diff --git a/oldtests/Original/Code_Spans.markdown b/oldtests/Original/Code_Spans.markdown
deleted file mode 100644
index 5c229c7..0000000
--- a/oldtests/Original/Code_Spans.markdown
+++ /dev/null
@@ -1,5 +0,0 @@
-`<test a="` content of attribute `">`
-
-Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span>
-
-Here's how you put `` `backticks` `` in a code span. \ No newline at end of file
diff --git a/oldtests/Original/Horizontal_rules.html b/oldtests/Original/Horizontal_rules.html
deleted file mode 100644
index a89efdb..0000000
--- a/oldtests/Original/Horizontal_rules.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<p>Dashes:</p>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>---
-</code></pre>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>- - -
-</code></pre>
-<p>Asterisks:</p>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>***
-</code></pre>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>* * *
-</code></pre>
-<p>Underscores:</p>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>___
-</code></pre>
-<hr />
-<hr />
-<hr />
-<hr />
-<pre><code>_ _ _
-</code></pre>
diff --git a/oldtests/Original/Horizontal_rules.markdown b/oldtests/Original/Horizontal_rules.markdown
deleted file mode 100644
index 1594bda..0000000
--- a/oldtests/Original/Horizontal_rules.markdown
+++ /dev/null
@@ -1,67 +0,0 @@
-Dashes:
-
----
-
- ---
-
- ---
-
- ---
-
- ---
-
-- - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-
-Asterisks:
-
-***
-
- ***
-
- ***
-
- ***
-
- ***
-
-* * *
-
- * * *
-
- * * *
-
- * * *
-
- * * *
-
-
-Underscores:
-
-___
-
- ___
-
- ___
-
- ___
-
- ___
-
-_ _ _
-
- _ _ _
-
- _ _ _
-
- _ _ _
-
- _ _ _
diff --git a/oldtests/Original/Images.html b/oldtests/Original/Images.html
deleted file mode 100644
index bd5a7e0..0000000
--- a/oldtests/Original/Images.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<p><img src="/path/to/img.jpg" alt="Alt text" /></p>
-<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
-<p>Inline within a paragraph: <a href="/url/">alt text</a>.</p>
-<p><img src="/url/" alt="alt text" title="title preceded by two spaces" /></p>
-<p><img src="/url/" alt="alt text" title="title has spaces afterward" /></p>
-<p><img src="/url/" alt="alt text" /></p>
-<p><img src="/url/" alt="alt text" title="with a title" />.</p>
-<p><img src="" alt="Empty" /></p>
-<p><img src="http://example.com/(parens).jpg" alt="this is a stupid URL" /></p>
-<p><img src="/url/" alt="alt text" /></p>
-<p><img src="/url/" alt="alt text" title="Title here" /></p>
diff --git a/oldtests/Original/Images.markdown b/oldtests/Original/Images.markdown
deleted file mode 100644
index 5707590..0000000
--- a/oldtests/Original/Images.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
-![Alt text](/path/to/img.jpg)
-
-![Alt text](/path/to/img.jpg "Optional title")
-
-Inline within a paragraph: [alt text](/url/).
-
-![alt text](/url/ "title preceded by two spaces")
-
-![alt text](/url/ "title has spaces afterward" )
-
-![alt text](</url/>)
-
-![alt text](</url/> "with a title").
-
-![Empty]()
-
-![this is a stupid URL](http://example.com/(parens).jpg)
-
-
-![alt text][foo]
-
- [foo]: /url/
-
-![alt text][bar]
-
- [bar]: /url/ "Title here" \ No newline at end of file
diff --git a/oldtests/Original/Inline_HTML_Advanced.html b/oldtests/Original/Inline_HTML_Advanced.html
deleted file mode 100644
index 631c135..0000000
--- a/oldtests/Original/Inline_HTML_Advanced.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<p>Simple block on one line:</p>
-<div>foo</div>
-<p>And nested without indentation:</p>
-<div>
-<div>
-<div>
-foo
-</div>
-<div style=">"/>
-</div>
-<div>bar</div>
-</div>
-<p>And with attributes:</p>
-<div>
- <div id="foo">
- </div>
-</div>
-<p>This was broken in 1.0.2b7:</p>
-<div class="inlinepage">
-<div class="toggleableend">
-foo
-</div>
-</div>
diff --git a/oldtests/Original/Inline_HTML_Advanced.markdown b/oldtests/Original/Inline_HTML_Advanced.markdown
deleted file mode 100644
index 3633f81..0000000
--- a/oldtests/Original/Inline_HTML_Advanced.markdown
+++ /dev/null
@@ -1,30 +0,0 @@
-Simple block on one line:
-
-<div>foo</div>
-
-And nested without indentation:
-
-<div>
-<div>
-<div>
-foo
-</div>
-<div style=">"/>
-</div>
-<div>bar</div>
-</div>
-
-And with attributes:
-
-<div>
- <div id="foo">
- </div>
-</div>
-
-This was broken in 1.0.2b7:
-
-<div class="inlinepage">
-<div class="toggleableend">
-foo
-</div>
-</div>
diff --git a/oldtests/Original/Inline_HTML_Simple.html b/oldtests/Original/Inline_HTML_Simple.html
deleted file mode 100644
index 923a18c..0000000
--- a/oldtests/Original/Inline_HTML_Simple.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<p>Here's a simple block:</p>
-<div>
- foo
-</div>
-<p>This should be a code block, though:</p>
-<pre><code>&lt;div&gt;
- foo
-&lt;/div&gt;
-</code></pre>
-<p>As should this:</p>
-<pre><code>&lt;div&gt;foo&lt;/div&gt;
-</code></pre>
-<p>Now, nested:</p>
-<div>
- <div>
- <div>
- foo
- </div>
- </div>
-</div>
-<p>This should just be an HTML comment:</p>
-<!-- Comment -->
-<p>Multiline:</p>
-<!--
-Blah
-Blah
--->
-<p>Code block:</p>
-<pre><code>&lt;!-- Comment --&gt;
-</code></pre>
-<p>Just plain comment, with trailing spaces on the line:</p>
-<!-- foo -->
-<p>Code:</p>
-<pre><code>&lt;hr /&gt;
-</code></pre>
-<p>Hr's:</p>
-<hr>
-<hr/>
-<hr />
-<hr>
-<hr/>
-<hr />
-<hr class="foo" id="bar" />
-<hr class="foo" id="bar"/>
-<hr class="foo" id="bar" >
diff --git a/oldtests/Original/Inline_HTML_Simple.markdown b/oldtests/Original/Inline_HTML_Simple.markdown
deleted file mode 100644
index 14aa2dc..0000000
--- a/oldtests/Original/Inline_HTML_Simple.markdown
+++ /dev/null
@@ -1,69 +0,0 @@
-Here's a simple block:
-
-<div>
- foo
-</div>
-
-This should be a code block, though:
-
- <div>
- foo
- </div>
-
-As should this:
-
- <div>foo</div>
-
-Now, nested:
-
-<div>
- <div>
- <div>
- foo
- </div>
- </div>
-</div>
-
-This should just be an HTML comment:
-
-<!-- Comment -->
-
-Multiline:
-
-<!--
-Blah
-Blah
--->
-
-Code block:
-
- <!-- Comment -->
-
-Just plain comment, with trailing spaces on the line:
-
-<!-- foo -->
-
-Code:
-
- <hr />
-
-Hr's:
-
-<hr>
-
-<hr/>
-
-<hr />
-
-<hr>
-
-<hr/>
-
-<hr />
-
-<hr class="foo" id="bar" />
-
-<hr class="foo" id="bar"/>
-
-<hr class="foo" id="bar" >
-
diff --git a/oldtests/Original/Inline_HTML_comments.html b/oldtests/Original/Inline_HTML_comments.html
deleted file mode 100644
index ebc4818..0000000
--- a/oldtests/Original/Inline_HTML_comments.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<p>Paragraph one.</p>
-<!-- This is a simple comment -->
-<!--
- This is another comment.
--->
-<p>Paragraph two.</p>
-<!-- one comment block -- -- with two comments -->
-<p>The end.</p>
diff --git a/oldtests/Original/Inline_HTML_comments.markdown b/oldtests/Original/Inline_HTML_comments.markdown
deleted file mode 100644
index 41d830d..0000000
--- a/oldtests/Original/Inline_HTML_comments.markdown
+++ /dev/null
@@ -1,13 +0,0 @@
-Paragraph one.
-
-<!-- This is a simple comment -->
-
-<!--
- This is another comment.
--->
-
-Paragraph two.
-
-<!-- one comment block -- -- with two comments -->
-
-The end.
diff --git a/oldtests/Original/Links_inline_style.html b/oldtests/Original/Links_inline_style.html
deleted file mode 100644
index feb4637..0000000
--- a/oldtests/Original/Links_inline_style.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<p>Just a <a href="/url/">URL</a>.</p>
-<p><a href="/url/" title="title">URL and title</a>.</p>
-<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>
-<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>
-<p><a href="/url/" title="title has spaces afterward">URL and title</a>.</p>
-<p><a href="/url/">URL wrapped in angle brackets</a>.</p>
-<p><a href="/url/" title="Here's the title">URL w/ angle brackets + title</a>.</p>
-<p><a href="">Empty</a>.</p>
-<p><a href="http://en.wikipedia.org/wiki/WIMP_(computing)">With parens in the URL</a></p>
-<p>(With outer parens and <a href="/foo(bar)">parens in url</a>)</p>
-<p><a href="/foo(bar)" title="and a title">With parens in the URL</a></p>
-<p>(With outer parens and <a href="/foo(bar)" title="and a title">parens in url</a>)</p>
diff --git a/oldtests/Original/Links_inline_style.markdown b/oldtests/Original/Links_inline_style.markdown
deleted file mode 100644
index aba9658..0000000
--- a/oldtests/Original/Links_inline_style.markdown
+++ /dev/null
@@ -1,24 +0,0 @@
-Just a [URL](/url/).
-
-[URL and title](/url/ "title").
-
-[URL and title](/url/ "title preceded by two spaces").
-
-[URL and title](/url/ "title preceded by a tab").
-
-[URL and title](/url/ "title has spaces afterward" ).
-
-[URL wrapped in angle brackets](</url/>).
-
-[URL w/ angle brackets + title](</url/> "Here's the title").
-
-[Empty]().
-
-[With parens in the URL](http://en.wikipedia.org/wiki/WIMP_(computing))
-
-(With outer parens and [parens in url](/foo(bar)))
-
-
-[With parens in the URL](/foo(bar) "and a title")
-
-(With outer parens and [parens in url](/foo(bar) "and a title"))
diff --git a/oldtests/Original/Links_reference_style.html b/oldtests/Original/Links_reference_style.html
deleted file mode 100644
index 6d78b96..0000000
--- a/oldtests/Original/Links_reference_style.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<p>Foo <a href="/url/" title="Title">bar</a>.</p>
-<p>Foo <a href="/url/" title="Title">bar</a>.</p>
-<p>Foo <a href="/url/" title="Title">bar</a>.</p>
-<p>With <a href="/url/">embedded [brackets]</a>.</p>
-<p>Indented <a href="/url">once</a>.</p>
-<p>Indented <a href="/url">twice</a>.</p>
-<p>Indented <a href="/url">thrice</a>.</p>
-<p>Indented [four][] times.</p>
-<pre><code>[four]: /url
-</code></pre>
-<hr />
-<p><a href="foo">this</a> should work</p>
-<p>So should <a href="foo">this</a>.</p>
-<p>And <a href="foo">this</a>.</p>
-<p>And <a href="foo">this</a>.</p>
-<p>And <a href="foo">this</a>.</p>
-<p>But not [that] [].</p>
-<p>Nor [that][].</p>
-<p>Nor [that].</p>
-<p>[Something in brackets like <a href="foo">this</a> should work]</p>
-<p>[Same with <a href="foo">this</a>.]</p>
-<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p>
-<p>Backslashing should suppress [this] and [this].</p>
-<hr />
-<p>Here's one where the <a href="/url/">link
-breaks</a> across lines.</p>
-<p>Here's another where the <a href="/url/">link
-breaks</a> across lines, but with a line-ending space.</p>
diff --git a/oldtests/Original/Links_reference_style.markdown b/oldtests/Original/Links_reference_style.markdown
deleted file mode 100644
index 341ec88..0000000
--- a/oldtests/Original/Links_reference_style.markdown
+++ /dev/null
@@ -1,71 +0,0 @@
-Foo [bar] [1].
-
-Foo [bar][1].
-
-Foo [bar]
-[1].
-
-[1]: /url/ "Title"
-
-
-With [embedded [brackets]] [b].
-
-
-Indented [once][].
-
-Indented [twice][].
-
-Indented [thrice][].
-
-Indented [four][] times.
-
- [once]: /url
-
- [twice]: /url
-
- [thrice]: /url
-
- [four]: /url
-
-
-[b]: /url/
-
-* * *
-
-[this] [this] should work
-
-So should [this][this].
-
-And [this] [].
-
-And [this][].
-
-And [this].
-
-But not [that] [].
-
-Nor [that][].
-
-Nor [that].
-
-[Something in brackets like [this][] should work]
-
-[Same with [this].]
-
-In this case, [this](/somethingelse/) points to something else.
-
-Backslashing should suppress \[this] and [this\].
-
-[this]: foo
-
-
-* * *
-
-Here's one where the [link
-breaks] across lines.
-
-Here's another where the [link
-breaks] across lines, but with a line-ending space.
-
-
-[link breaks]: /url/
diff --git a/oldtests/Original/Links_shortcut_references.html b/oldtests/Original/Links_shortcut_references.html
deleted file mode 100644
index 8163ade..0000000
--- a/oldtests/Original/Links_shortcut_references.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<p>This is the <a href="/simple">simple case</a>.</p>
-<p>This one has a <a href="/foo">line
-break</a>.</p>
-<p>This one has a <a href="/foo">line
-break</a> with a line-ending space.</p>
-<p><a href="/that">this</a> and the <a href="/other">other</a></p>
diff --git a/oldtests/Original/Links_shortcut_references.markdown b/oldtests/Original/Links_shortcut_references.markdown
deleted file mode 100644
index 8c44c98..0000000
--- a/oldtests/Original/Links_shortcut_references.markdown
+++ /dev/null
@@ -1,20 +0,0 @@
-This is the [simple case].
-
-[simple case]: /simple
-
-
-
-This one has a [line
-break].
-
-This one has a [line
-break] with a line-ending space.
-
-[line break]: /foo
-
-
-[this] [that] and the [other]
-
-[this]: /this
-[that]: /that
-[other]: /other
diff --git a/oldtests/Original/Literal_quotes_in_titles.html b/oldtests/Original/Literal_quotes_in_titles.html
deleted file mode 100644
index 62e8641..0000000
--- a/oldtests/Original/Literal_quotes_in_titles.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
-<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
diff --git a/oldtests/Original/Literal_quotes_in_titles.markdown b/oldtests/Original/Literal_quotes_in_titles.markdown
deleted file mode 100644
index 29d0e42..0000000
--- a/oldtests/Original/Literal_quotes_in_titles.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-Foo [bar][].
-
-Foo [bar](/url/ "Title with "quotes" inside").
-
-
- [bar]: /url/ "Title with "quotes" inside"
-
diff --git a/oldtests/Original/Markdown_Documentation_Basics.html b/oldtests/Original/Markdown_Documentation_Basics.html
deleted file mode 100644
index 0dee67f..0000000
--- a/oldtests/Original/Markdown_Documentation_Basics.html
+++ /dev/null
@@ -1,242 +0,0 @@
-<h1>Markdown: Basics</h1>
-<ul id="ProjectSubmenu">
- <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
- <li><a class="selected" title="Markdown Basics">Basics</a></li>
- <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
- <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
- <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
-</ul>
-<h2>Getting the Gist of Markdown's Formatting Syntax</h2>
-<p>This page offers a brief overview of what it's like to use Markdown.
-The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for
-every feature, but Markdown should be very easy to pick up simply by
-looking at a few examples of it in action. The examples on this page
-are written in a before/after style, showing example syntax and the
-HTML output produced by Markdown.</p>
-<p>It's also helpful to simply try Markdown out; the <a href="/projects/markdown/dingus" title="Markdown Dingus">Dingus</a> is a
-web application that allows you type your own Markdown-formatted text
-and translate it to XHTML.</p>
-<p><strong>Note:</strong> This document is itself written using Markdown; you
-can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p>
-<h2>Paragraphs, Headers, Blockquotes</h2>
-<p>A paragraph is simply one or more consecutive lines of text, separated
-by one or more blank lines. (A blank line is any line that looks like a
-blank line -- a line containing nothing spaces or tabs is considered
-blank.) Normal paragraphs should not be intended with spaces or tabs.</p>
-<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>.
-Setext-style headers for <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> are created by
-&quot;underlining&quot; with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively.
-To create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the
-beginning of the line -- the number of hashes equals the resulting
-HTML header level.</p>
-<p>Blockquotes are indicated using email-style '<code>&gt;</code>' angle brackets.</p>
-<p>Markdown:</p>
-<pre><code>A First Level Header
-====================
-
-A Second Level Header
----------------------
-
-Now is the time for all good men to come to
-the aid of their country. This is just a
-regular paragraph.
-
-The quick brown fox jumped over the lazy
-dog's back.
-
-### Header 3
-
-&gt; This is a blockquote.
-&gt;
-&gt; This is the second paragraph in the blockquote.
-&gt;
-&gt; ## This is an H2 in a blockquote
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;h1&gt;A First Level Header&lt;/h1&gt;
-
-&lt;h2&gt;A Second Level Header&lt;/h2&gt;
-
-&lt;p&gt;Now is the time for all good men to come to
-the aid of their country. This is just a
-regular paragraph.&lt;/p&gt;
-
-&lt;p&gt;The quick brown fox jumped over the lazy
-dog's back.&lt;/p&gt;
-
-&lt;h3&gt;Header 3&lt;/h3&gt;
-
-&lt;blockquote&gt;
- &lt;p&gt;This is a blockquote.&lt;/p&gt;
-
- &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
-
- &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
-&lt;/blockquote&gt;
-</code></pre>
-<h3>Phrase Emphasis</h3>
-<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>
-<p>Markdown:</p>
-<pre><code>Some of these words *are emphasized*.
-Some of these words _are emphasized also_.
-
-Use two asterisks for **strong emphasis**.
-Or, if you prefer, __use two underscores instead__.
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
-Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
-
-&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
-Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
-</code></pre>
-<h2>Lists</h2>
-<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,
-<code>+</code>, and <code>-</code>) as list markers. These three markers are
-interchangable; this:</p>
-<pre><code>* Candy.
-* Gum.
-* Booze.
-</code></pre>
-<p>this:</p>
-<pre><code>+ Candy.
-+ Gum.
-+ Booze.
-</code></pre>
-<p>and this:</p>
-<pre><code>- Candy.
-- Gum.
-- Booze.
-</code></pre>
-<p>all produce the same output:</p>
-<pre><code>&lt;ul&gt;
-&lt;li&gt;Candy.&lt;/li&gt;
-&lt;li&gt;Gum.&lt;/li&gt;
-&lt;li&gt;Booze.&lt;/li&gt;
-&lt;/ul&gt;
-</code></pre>
-<p>Ordered (numbered) lists use regular numbers, followed by periods, as
-list markers:</p>
-<pre><code>1. Red
-2. Green
-3. Blue
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;ol&gt;
-&lt;li&gt;Red&lt;/li&gt;
-&lt;li&gt;Green&lt;/li&gt;
-&lt;li&gt;Blue&lt;/li&gt;
-&lt;/ol&gt;
-</code></pre>
-<p>If you put blank lines between items, you'll get <code>&lt;p&gt;</code> tags for the
-list item text. You can create multi-paragraph list items by indenting
-the paragraphs by 4 spaces or 1 tab:</p>
-<pre><code>* A list item.
-
- With multiple paragraphs.
-
-* Another item in the list.
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;ul&gt;
-&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
-&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
-&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
-&lt;/ul&gt;
-</code></pre>
-<h3>Links</h3>
-<p>Markdown supports two styles for creating links: <em>inline</em> and
-<em>reference</em>. With both styles, you use square brackets to delimit the
-text you want to turn into a link.</p>
-<p>Inline-style links use parentheses immediately after the link text.
-For example:</p>
-<pre><code>This is an [example link](http://example.com/).
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;This is an &lt;a href=&quot;http://example.com/&quot;&gt;
-example link&lt;/a&gt;.&lt;/p&gt;
-</code></pre>
-<p>Optionally, you may include a title attribute in the parentheses:</p>
-<pre><code>This is an [example link](http://example.com/ &quot;With a Title&quot;).
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;This is an &lt;a href=&quot;http://example.com/&quot; title=&quot;With a Title&quot;&gt;
-example link&lt;/a&gt;.&lt;/p&gt;
-</code></pre>
-<p>Reference-style links allow you to refer to your links by names, which
-you define elsewhere in your document:</p>
-<pre><code>I get 10 times more traffic from [Google][1] than from
-[Yahoo][2] or [MSN][3].
-
-[1]: http://google.com/ &quot;Google&quot;
-[2]: http://search.yahoo.com/ &quot;Yahoo Search&quot;
-[3]: http://search.msn.com/ &quot;MSN Search&quot;
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=&quot;http://google.com/&quot;
-title=&quot;Google&quot;&gt;Google&lt;/a&gt; than from &lt;a href=&quot;http://search.yahoo.com/&quot;
-title=&quot;Yahoo Search&quot;&gt;Yahoo&lt;/a&gt; or &lt;a href=&quot;http://search.msn.com/&quot;
-title=&quot;MSN Search&quot;&gt;MSN&lt;/a&gt;.&lt;/p&gt;
-</code></pre>
-<p>The title attribute is optional. Link names may contain letters,
-numbers and spaces, but are <em>not</em> case sensitive:</p>
-<pre><code>I start my morning with a cup of coffee and
-[The New York Times][NY Times].
-
-[ny times]: http://www.nytimes.com/
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;I start my morning with a cup of coffee and
-&lt;a href=&quot;http://www.nytimes.com/&quot;&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
-</code></pre>
-<h3>Images</h3>
-<p>Image syntax is very much like link syntax.</p>
-<p>Inline (titles are optional):</p>
-<pre><code>![alt text](/path/to/img.jpg &quot;Title&quot;)
-</code></pre>
-<p>Reference-style:</p>
-<pre><code>![alt text][id]
-
-[id]: /path/to/img.jpg &quot;Title&quot;
-</code></pre>
-<p>Both of the above examples produce the same output:</p>
-<pre><code>&lt;img src=&quot;/path/to/img.jpg&quot; alt=&quot;alt text&quot; title=&quot;Title&quot; /&gt;
-</code></pre>
-<h3>Code</h3>
-<p>In a regular paragraph, you can create code span by wrapping text in
-backtick quotes. Any ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> or
-<code>&gt;</code>) will automatically be translated into HTML entities. This makes
-it easy to use Markdown to write about HTML example code:</p>
-<pre><code>I strongly recommend against using any `&lt;blink&gt;` tags.
-
-I wish SmartyPants used named entities like `&amp;mdash;`
-instead of decimal-encoded entites like `&amp;#8212;`.
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;I strongly recommend against using any
-&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
-
-&lt;p&gt;I wish SmartyPants used named entities like
-&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
-entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
-</code></pre>
-<p>To specify an entire block of pre-formatted code, indent every line of
-the block by 4 spaces or 1 tab. Just like with code spans, <code>&amp;</code>, <code>&lt;</code>,
-and <code>&gt;</code> characters will be escaped automatically.</p>
-<p>Markdown:</p>
-<pre><code>If you want your page to validate under XHTML 1.0 Strict,
-you've got to put paragraph tags in your blockquotes:
-
- &lt;blockquote&gt;
- &lt;p&gt;For example.&lt;/p&gt;
- &lt;/blockquote&gt;
-</code></pre>
-<p>Output:</p>
-<pre><code>&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
-you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
-
-&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
- &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
-&amp;lt;/blockquote&amp;gt;
-&lt;/code&gt;&lt;/pre&gt;
-</code></pre>
diff --git a/oldtests/Original/Markdown_Documentation_Basics.markdown b/oldtests/Original/Markdown_Documentation_Basics.markdown
deleted file mode 100644
index 24eba65..0000000
--- a/oldtests/Original/Markdown_Documentation_Basics.markdown
+++ /dev/null
@@ -1,306 +0,0 @@
-Markdown: Basics
-================
-
-<ul id="ProjectSubmenu">
- <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
- <li><a class="selected" title="Markdown Basics">Basics</a></li>
- <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
- <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
- <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
-</ul>
-
-
-Getting the Gist of Markdown's Formatting Syntax
-------------------------------------------------
-
-This page offers a brief overview of what it's like to use Markdown.
-The [syntax page] [s] provides complete, detailed documentation for
-every feature, but Markdown should be very easy to pick up simply by
-looking at a few examples of it in action. The examples on this page
-are written in a before/after style, showing example syntax and the
-HTML output produced by Markdown.
-
-It's also helpful to simply try Markdown out; the [Dingus] [d] is a
-web application that allows you type your own Markdown-formatted text
-and translate it to XHTML.
-
-**Note:** This document is itself written using Markdown; you
-can [see the source for it by adding '.text' to the URL] [src].
-
- [s]: /projects/markdown/syntax "Markdown Syntax"
- [d]: /projects/markdown/dingus "Markdown Dingus"
- [src]: /projects/markdown/basics.text
-
-
-## Paragraphs, Headers, Blockquotes ##
-
-A paragraph is simply one or more consecutive lines of text, separated
-by one or more blank lines. (A blank line is any line that looks like a
-blank line -- a line containing nothing spaces or tabs is considered
-blank.) Normal paragraphs should not be intended with spaces or tabs.
-
-Markdown offers two styles of headers: *Setext* and *atx*.
-Setext-style headers for `<h1>` and `<h2>` are created by
-"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
-To create an atx-style header, you put 1-6 hash marks (`#`) at the
-beginning of the line -- the number of hashes equals the resulting
-HTML header level.
-
-Blockquotes are indicated using email-style '`>`' angle brackets.
-
-Markdown:
-
- A First Level Header
- ====================
-
- A Second Level Header
- ---------------------
-
- Now is the time for all good men to come to
- the aid of their country. This is just a
- regular paragraph.
-
- The quick brown fox jumped over the lazy
- dog's back.
-
- ### Header 3
-
- > This is a blockquote.
- >
- > This is the second paragraph in the blockquote.
- >
- > ## This is an H2 in a blockquote
-
-
-Output:
-
- <h1>A First Level Header</h1>
-
- <h2>A Second Level Header</h2>
-
- <p>Now is the time for all good men to come to
- the aid of their country. This is just a
- regular paragraph.</p>
-
- <p>The quick brown fox jumped over the lazy
- dog's back.</p>
-
- <h3>Header 3</h3>
-
- <blockquote>
- <p>This is a blockquote.</p>
-
- <p>This is the second paragraph in the blockquote.</p>
-
- <h2>This is an H2 in a blockquote</h2>
- </blockquote>
-
-
-
-### Phrase Emphasis ###
-
-Markdown uses asterisks and underscores to indicate spans of emphasis.
-
-Markdown:
-
- Some of these words *are emphasized*.
- Some of these words _are emphasized also_.
-
- Use two asterisks for **strong emphasis**.
- Or, if you prefer, __use two underscores instead__.
-
-Output:
-
- <p>Some of these words <em>are emphasized</em>.
- Some of these words <em>are emphasized also</em>.</p>
-
- <p>Use two asterisks for <strong>strong emphasis</strong>.
- Or, if you prefer, <strong>use two underscores instead</strong>.</p>
-
-
-
-## Lists ##
-
-Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
-`+`, and `-`) as list markers. These three markers are
-interchangable; this:
-
- * Candy.
- * Gum.
- * Booze.
-
-this:
-
- + Candy.
- + Gum.
- + Booze.
-
-and this:
-
- - Candy.
- - Gum.
- - Booze.
-
-all produce the same output:
-
- <ul>
- <li>Candy.</li>
- <li>Gum.</li>
- <li>Booze.</li>
- </ul>
-
-Ordered (numbered) lists use regular numbers, followed by periods, as
-list markers:
-
- 1. Red
- 2. Green
- 3. Blue
-
-Output:
-
- <ol>
- <li>Red</li>
- <li>Green</li>
- <li>Blue</li>
- </ol>
-
-If you put blank lines between items, you'll get `<p>` tags for the
-list item text. You can create multi-paragraph list items by indenting
-the paragraphs by 4 spaces or 1 tab:
-
- * A list item.
-
- With multiple paragraphs.
-
- * Another item in the list.
-
-Output:
-
- <ul>
- <li><p>A list item.</p>
- <p>With multiple paragraphs.</p></li>
- <li><p>Another item in the list.</p></li>
- </ul>
-
-
-
-### Links ###
-
-Markdown supports two styles for creating links: *inline* and
-*reference*. With both styles, you use square brackets to delimit the
-text you want to turn into a link.
-
-Inline-style links use parentheses immediately after the link text.
-For example:
-
- This is an [example link](http://example.com/).
-
-Output:
-
- <p>This is an <a href="http://example.com/">
- example link</a>.</p>
-
-Optionally, you may include a title attribute in the parentheses:
-
- This is an [example link](http://example.com/ "With a Title").
-
-Output:
-
- <p>This is an <a href="http://example.com/" title="With a Title">
- example link</a>.</p>
-
-Reference-style links allow you to refer to your links by names, which
-you define elsewhere in your document:
-
- I get 10 times more traffic from [Google][1] than from
- [Yahoo][2] or [MSN][3].
-
- [1]: http://google.com/ "Google"
- [2]: http://search.yahoo.com/ "Yahoo Search"
- [3]: http://search.msn.com/ "MSN Search"
-
-Output:
-
- <p>I get 10 times more traffic from <a href="http://google.com/"
- title="Google">Google</a> than from <a href="http://search.yahoo.com/"
- title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
- title="MSN Search">MSN</a>.</p>
-
-The title attribute is optional. Link names may contain letters,
-numbers and spaces, but are *not* case sensitive:
-
- I start my morning with a cup of coffee and
- [The New York Times][NY Times].
-
- [ny times]: http://www.nytimes.com/
-
-Output:
-
- <p>I start my morning with a cup of coffee and
- <a href="http://www.nytimes.com/">The New York Times</a>.</p>
-
-
-### Images ###
-
-Image syntax is very much like link syntax.
-
-Inline (titles are optional):
-
- ![alt text](/path/to/img.jpg "Title")
-
-Reference-style:
-
- ![alt text][id]
-
- [id]: /path/to/img.jpg "Title"
-
-Both of the above examples produce the same output:
-
- <img src="/path/to/img.jpg" alt="alt text" title="Title" />
-
-
-
-### Code ###
-
-In a regular paragraph, you can create code span by wrapping text in
-backtick quotes. Any ampersands (`&`) and angle brackets (`<` or
-`>`) will automatically be translated into HTML entities. This makes
-it easy to use Markdown to write about HTML example code:
-
- I strongly recommend against using any `<blink>` tags.
-
- I wish SmartyPants used named entities like `&mdash;`
- instead of decimal-encoded entites like `&#8212;`.
-
-Output:
-
- <p>I strongly recommend against using any
- <code>&lt;blink&gt;</code> tags.</p>
-
- <p>I wish SmartyPants used named entities like
- <code>&amp;mdash;</code> instead of decimal-encoded
- entites like <code>&amp;#8212;</code>.</p>
-
-
-To specify an entire block of pre-formatted code, indent every line of
-the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,
-and `>` characters will be escaped automatically.
-
-Markdown:
-
- If you want your page to validate under XHTML 1.0 Strict,
- you've got to put paragraph tags in your blockquotes:
-
- <blockquote>
- <p>For example.</p>
- </blockquote>
-
-Output:
-
- <p>If you want your page to validate under XHTML 1.0 Strict,
- you've got to put paragraph tags in your blockquotes:</p>
-
- <pre><code>&lt;blockquote&gt;
- &lt;p&gt;For example.&lt;/p&gt;
- &lt;/blockquote&gt;
- </code></pre>
diff --git a/oldtests/Original/Markdown_Documentation_Syntax.html b/oldtests/Original/Markdown_Documentation_Syntax.html
deleted file mode 100644
index f379dcf..0000000
--- a/oldtests/Original/Markdown_Documentation_Syntax.html
+++ /dev/null
@@ -1,708 +0,0 @@
-<h1>Markdown: Syntax</h1>
-<ul id="ProjectSubmenu">
- <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
- <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>
- <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>
- <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
- <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
-</ul>
-<ul>
-<li><a href="#overview">Overview</a>
-<ul>
-<li><a href="#philosophy">Philosophy</a></li>
-<li><a href="#html">Inline HTML</a></li>
-<li><a href="#autoescape">Automatic Escaping for Special Characters</a></li>
-</ul></li>
-<li><a href="#block">Block Elements</a>
-<ul>
-<li><a href="#p">Paragraphs and Line Breaks</a></li>
-<li><a href="#header">Headers</a></li>
-<li><a href="#blockquote">Blockquotes</a></li>
-<li><a href="#list">Lists</a></li>
-<li><a href="#precode">Code Blocks</a></li>
-<li><a href="#hr">Horizontal Rules</a></li>
-</ul></li>
-<li><a href="#span">Span Elements</a>
-<ul>
-<li><a href="#link">Links</a></li>
-<li><a href="#em">Emphasis</a></li>
-<li><a href="#code">Code</a></li>
-<li><a href="#img">Images</a></li>
-</ul></li>
-<li><a href="#misc">Miscellaneous</a>
-<ul>
-<li><a href="#backslash">Backslash Escapes</a></li>
-<li><a href="#autolink">Automatic Links</a></li>
-</ul></li>
-</ul>
-<p><strong>Note:</strong> This document is itself written using Markdown; you
-can <a href="/projects/markdown/syntax.text">see the source for it by adding '.text' to the URL</a>.</p>
-<hr />
-<h2 id="overview">Overview</h2>
-<h3 id="philosophy">Philosophy</h3>
-<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>
-<p>Readability, however, is emphasized above all else. A Markdown-formatted
-document should be publishable as-is, as plain text, without looking
-like it's been marked up with tags or formatting instructions. While
-Markdown's syntax has been influenced by several existing text-to-HTML
-filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>,
-<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of
-inspiration for Markdown's syntax is the format of plain text email.</p>
-<p>To this end, Markdown's syntax is comprised entirely of punctuation
-characters, which punctuation characters have been carefully chosen so
-as to look like what they mean. E.g., asterisks around a word actually
-look like *emphasis*. Markdown lists look like, well, lists. Even
-blockquotes look like quoted passages of text, assuming you've ever
-used email.</p>
-<h3 id="html">Inline HTML</h3>
-<p>Markdown's syntax is intended for one purpose: to be used as a
-format for <em>writing</em> for the web.</p>
-<p>Markdown is not a replacement for HTML, or even close to it. Its
-syntax is very small, corresponding only to a very small subset of
-HTML tags. The idea is <em>not</em> to create a syntax that makes it easier
-to insert HTML tags. In my opinion, HTML tags are already easy to
-insert. The idea for Markdown is to make it easy to read, write, and
-edit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em>
-format. Thus, Markdown's formatting syntax only addresses issues that
-can be conveyed in plain text.</p>
-<p>For any markup that is not covered by Markdown's syntax, you simply
-use HTML itself. There's no need to preface it or delimit it to
-indicate that you're switching from Markdown to HTML; you just use
-the tags.</p>
-<p>The only restrictions are that block-level HTML elements -- e.g. <code>&lt;div&gt;</code>,
-<code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. -- must be separated from surrounding
-content by blank lines, and the start and end tags of the block should
-not be indented with tabs or spaces. Markdown is smart enough not
-to add extra (unwanted) <code>&lt;p&gt;</code> tags around HTML block-level tags.</p>
-<p>For example, to add an HTML table to a Markdown article:</p>
-<pre><code>This is a regular paragraph.
-
-&lt;table&gt;
- &lt;tr&gt;
- &lt;td&gt;Foo&lt;/td&gt;
- &lt;/tr&gt;
-&lt;/table&gt;
-
-This is another regular paragraph.
-</code></pre>
-<p>Note that Markdown formatting syntax is not processed within block-level
-HTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an
-HTML block.</p>
-<p>Span-level HTML tags -- e.g. <code>&lt;span&gt;</code>, <code>&lt;cite&gt;</code>, or <code>&lt;del&gt;</code> -- can be
-used anywhere in a Markdown paragraph, list item, or header. If you
-want, you can even use HTML tags instead of Markdown formatting; e.g. if
-you'd prefer to use HTML <code>&lt;a&gt;</code> or <code>&lt;img&gt;</code> tags instead of Markdown's
-link or image syntax, go right ahead.</p>
-<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within
-span-level tags.</p>
-<h3 id="autoescape">Automatic Escaping for Special Characters</h3>
-<p>In HTML, there are two characters that demand special treatment: <code>&lt;</code>
-and <code>&amp;</code>. Left angle brackets are used to start tags; ampersands are
-used to denote HTML entities. If you want to use them as literal
-characters, you must escape them as entities, e.g. <code>&amp;lt;</code>, and
-<code>&amp;amp;</code>.</p>
-<p>Ampersands in particular are bedeviling for web writers. If you want to
-write about 'AT&amp;T', you need to write '<code>AT&amp;amp;T</code>'. You even need to
-escape ampersands within URLs. Thus, if you want to link to:</p>
-<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird
-</code></pre>
-<p>you need to encode the URL as:</p>
-<pre><code>http://images.google.com/images?num=30&amp;amp;q=larry+bird
-</code></pre>
-<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to
-forget, and is probably the single most common source of HTML validation
-errors in otherwise well-marked-up web sites.</p>
-<p>Markdown allows you to use these characters naturally, taking care of
-all the necessary escaping for you. If you use an ampersand as part of
-an HTML entity, it remains unchanged; otherwise it will be translated
-into <code>&amp;amp;</code>.</p>
-<p>So, if you want to include a copyright symbol in your article, you can write:</p>
-<pre><code>&amp;copy;
-</code></pre>
-<p>and Markdown will leave it alone. But if you write:</p>
-<pre><code>AT&amp;T
-</code></pre>
-<p>Markdown will translate it to:</p>
-<pre><code>AT&amp;amp;T
-</code></pre>
-<p>Similarly, because Markdown supports <a href="#html">inline HTML</a>, if you use
-angle brackets as delimiters for HTML tags, Markdown will treat them as
-such. But if you write:</p>
-<pre><code>4 &lt; 5
-</code></pre>
-<p>Markdown will translate it to:</p>
-<pre><code>4 &amp;lt; 5
-</code></pre>
-<p>However, inside Markdown code spans and blocks, angle brackets and
-ampersands are <em>always</em> encoded automatically. This makes it easy to use
-Markdown to write about HTML code. (As opposed to raw HTML, which is a
-terrible format for writing about HTML syntax, because every single <code>&lt;</code>
-and <code>&amp;</code> in your example code needs to be escaped.)</p>
-<hr />
-<h2 id="block">Block Elements</h2>
-<h3 id="p">Paragraphs and Line Breaks</h3>
-<p>A paragraph is simply one or more consecutive lines of text, separated
-by one or more blank lines. (A blank line is any line that looks like a
-blank line -- a line containing nothing but spaces or tabs is considered
-blank.) Normal paragraphs should not be intended with spaces or tabs.</p>
-<p>The implication of the &quot;one or more consecutive lines of text&quot; rule is
-that Markdown supports &quot;hard-wrapped&quot; text paragraphs. This differs
-significantly from most other text-to-HTML formatters (including Movable
-Type's &quot;Convert Line Breaks&quot; option) which translate every line break
-character in a paragraph into a <code>&lt;br /&gt;</code> tag.</p>
-<p>When you <em>do</em> want to insert a <code>&lt;br /&gt;</code> break tag using Markdown, you
-end a line with two or more spaces, then type return.</p>
-<p>Yes, this takes a tad more effort to create a <code>&lt;br /&gt;</code>, but a simplistic
-&quot;every line break is a <code>&lt;br /&gt;</code>&quot; rule wouldn't work for Markdown.
-Markdown's email-style <a href="#blockquote">blockquoting</a> and multi-paragraph <a href="#list">list items</a>
-work best -- and look better -- when you format them with hard breaks.</p>
-<h3 id="header">Headers</h3>
-<p>Markdown supports two styles of headers, <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a> and <a href="http://www.aaronsw.com/2002/atx/">atx</a>.</p>
-<p>Setext-style headers are &quot;underlined&quot; using equal signs (for first-level
-headers) and dashes (for second-level headers). For example:</p>
-<pre><code>This is an H1
-=============
-
-This is an H2
--------------
-</code></pre>
-<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p>
-<p>Atx-style headers use 1-6 hash characters at the start of the line,
-corresponding to header levels 1-6. For example:</p>
-<pre><code># This is an H1
-
-## This is an H2
-
-###### This is an H6
-</code></pre>
-<p>Optionally, you may &quot;close&quot; atx-style headers. This is purely
-cosmetic -- you can use this if you think it looks better. The
-closing hashes don't even need to match the number of hashes
-used to open the header. (The number of opening hashes
-determines the header level.) :</p>
-<pre><code># This is an H1 #
-
-## This is an H2 ##
-
-### This is an H3 ######
-</code></pre>
-<h3 id="blockquote">Blockquotes</h3>
-<p>Markdown uses email-style <code>&gt;</code> characters for blockquoting. If you're
-familiar with quoting passages of text in an email message, then you
-know how to create a blockquote in Markdown. It looks best if you hard
-wrap the text and put a <code>&gt;</code> before every line:</p>
-<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
-&gt; consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
-&gt; Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
-&gt;
-&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
-&gt; id sem consectetuer libero luctus adipiscing.
-</code></pre>
-<p>Markdown allows you to be lazy and only put the <code>&gt;</code> before the first
-line of a hard-wrapped paragraph:</p>
-<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
-consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
-Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
-
-&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
-id sem consectetuer libero luctus adipiscing.
-</code></pre>
-<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
-adding additional levels of <code>&gt;</code>:</p>
-<pre><code>&gt; This is the first level of quoting.
-&gt;
-&gt; &gt; This is nested blockquote.
-&gt;
-&gt; Back to the first level.
-</code></pre>
-<p>Blockquotes can contain other Markdown elements, including headers, lists,
-and code blocks:</p>
-<pre><code>&gt; ## This is a header.
-&gt;
-&gt; 1. This is the first list item.
-&gt; 2. This is the second list item.
-&gt;
-&gt; Here's some example code:
-&gt;
-&gt; return shell_exec(&quot;echo $input | $markdown_script&quot;);
-</code></pre>
-<p>Any decent text editor should make email-style quoting easy. For
-example, with BBEdit, you can make a selection and choose Increase
-Quote Level from the Text menu.</p>
-<h3 id="list">Lists</h3>
-<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>
-<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably
--- as list markers:</p>
-<pre><code>* Red
-* Green
-* Blue
-</code></pre>
-<p>is equivalent to:</p>
-<pre><code>+ Red
-+ Green
-+ Blue
-</code></pre>
-<p>and:</p>
-<pre><code>- Red
-- Green
-- Blue
-</code></pre>
-<p>Ordered lists use numbers followed by periods:</p>
-<pre><code>1. Bird
-2. McHale
-3. Parish
-</code></pre>
-<p>It's important to note that the actual numbers you use to mark the
-list have no effect on the HTML output Markdown produces. The HTML
-Markdown produces from the above list is:</p>
-<pre><code>&lt;ol&gt;
-&lt;li&gt;Bird&lt;/li&gt;
-&lt;li&gt;McHale&lt;/li&gt;
-&lt;li&gt;Parish&lt;/li&gt;
-&lt;/ol&gt;
-</code></pre>
-<p>If you instead wrote the list in Markdown like this:</p>
-<pre><code>1. Bird
-1. McHale
-1. Parish
-</code></pre>
-<p>or even:</p>
-<pre><code>3. Bird
-1. McHale
-8. Parish
-</code></pre>
-<p>you'd get the exact same HTML output. The point is, if you want to,
-you can use ordinal numbers in your ordered Markdown lists, so that
-the numbers in your source match the numbers in your published HTML.
-But if you want to be lazy, you don't have to.</p>
-<p>If you do use lazy list numbering, however, you should still start the
-list with the number 1. At some point in the future, Markdown may support
-starting ordered lists at an arbitrary number.</p>
-<p>List markers typically start at the left margin, but may be indented by
-up to three spaces. List markers must be followed by one or more spaces
-or a tab.</p>
-<p>To make lists look nice, you can wrap items with hanging indents:</p>
-<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
- viverra nec, fringilla in, laoreet vitae, risus.
-* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
- Suspendisse id sem consectetuer libero luctus adipiscing.
-</code></pre>
-<p>But if you want to be lazy, you don't have to:</p>
-<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
-Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
-viverra nec, fringilla in, laoreet vitae, risus.
-* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
-Suspendisse id sem consectetuer libero luctus adipiscing.
-</code></pre>
-<p>If list items are separated by blank lines, Markdown will wrap the
-items in <code>&lt;p&gt;</code> tags in the HTML output. For example, this input:</p>
-<pre><code>* Bird
-* Magic
-</code></pre>
-<p>will turn into:</p>
-<pre><code>&lt;ul&gt;
-&lt;li&gt;Bird&lt;/li&gt;
-&lt;li&gt;Magic&lt;/li&gt;
-&lt;/ul&gt;
-</code></pre>
-<p>But this:</p>
-<pre><code>* Bird
-
-* Magic
-</code></pre>
-<p>will turn into:</p>
-<pre><code>&lt;ul&gt;
-&lt;li&gt;&lt;p&gt;Bird&lt;/p&gt;&lt;/li&gt;
-&lt;li&gt;&lt;p&gt;Magic&lt;/p&gt;&lt;/li&gt;
-&lt;/ul&gt;
-</code></pre>
-<p>List items may consist of multiple paragraphs. Each subsequent
-paragraph in a list item must be intended by either 4 spaces
-or one tab:</p>
-<pre><code>1. This is a list item with two paragraphs. Lorem ipsum dolor
- sit amet, consectetuer adipiscing elit. Aliquam hendrerit
- mi posuere lectus.
-
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet
- vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
- sit amet velit.
-
-2. Suspendisse id sem consectetuer libero luctus adipiscing.
-</code></pre>
-<p>It looks nice if you indent every line of the subsequent
-paragraphs, but here again, Markdown will allow you to be
-lazy:</p>
-<pre><code>* This is a list item with two paragraphs.
-
- This is the second paragraph in the list item. You're
-only required to indent the first line. Lorem ipsum dolor
-sit amet, consectetuer adipiscing elit.
-
-* Another item in the same list.
-</code></pre>
-<p>To put a blockquote within a list item, the blockquote's <code>&gt;</code>
-delimiters need to be indented:</p>
-<pre><code>* A list item with a blockquote:
-
- &gt; This is a blockquote
- &gt; inside a list item.
-</code></pre>
-<p>To put a code block within a list item, the code block needs
-to be indented <em>twice</em> -- 8 spaces or two tabs:</p>
-<pre><code>* A list item with a code block:
-
- &lt;code goes here&gt;
-</code></pre>
-<p>It's worth noting that it's possible to trigger an ordered list by
-accident, by writing something like this:</p>
-<pre><code>1986. What a great season.
-</code></pre>
-<p>In other words, a <em>number-period-space</em> sequence at the beginning of a
-line. To avoid this, you can backslash-escape the period:</p>
-<pre><code>1986\. What a great season.
-</code></pre>
-<h3 id="precode">Code Blocks</h3>
-<p>Pre-formatted code blocks are used for writing about programming or
-markup source code. Rather than forming normal paragraphs, the lines
-of a code block are interpreted literally. Markdown wraps a code block
-in both <code>&lt;pre&gt;</code> and <code>&lt;code&gt;</code> tags.</p>
-<p>To produce a code block in Markdown, simply indent every line of the
-block by at least 4 spaces or 1 tab. For example, given this input:</p>
-<pre><code>This is a normal paragraph:
-
- This is a code block.
-</code></pre>
-<p>Markdown will generate:</p>
-<pre><code>&lt;p&gt;This is a normal paragraph:&lt;/p&gt;
-
-&lt;pre&gt;&lt;code&gt;This is a code block.
-&lt;/code&gt;&lt;/pre&gt;
-</code></pre>
-<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each
-line of the code block. For example, this:</p>
-<pre><code>Here is an example of AppleScript:
-
- tell application &quot;Foo&quot;
- beep
- end tell
-</code></pre>
-<p>will turn into:</p>
-<pre><code>&lt;p&gt;Here is an example of AppleScript:&lt;/p&gt;
-
-&lt;pre&gt;&lt;code&gt;tell application &quot;Foo&quot;
- beep
-end tell
-&lt;/code&gt;&lt;/pre&gt;
-</code></pre>
-<p>A code block continues until it reaches a line that is not indented
-(or the end of the article).</p>
-<p>Within a code block, ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> and <code>&gt;</code>)
-are automatically converted into HTML entities. This makes it very
-easy to include example HTML source code using Markdown -- just paste
-it and indent it, and Markdown will handle the hassle of encoding the
-ampersands and angle brackets. For example, this:</p>
-<pre><code> &lt;div class=&quot;footer&quot;&gt;
- &amp;copy; 2004 Foo Corporation
- &lt;/div&gt;
-</code></pre>
-<p>will turn into:</p>
-<pre><code>&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;footer&quot;&amp;gt;
- &amp;amp;copy; 2004 Foo Corporation
-&amp;lt;/div&amp;gt;
-&lt;/code&gt;&lt;/pre&gt;
-</code></pre>
-<p>Regular Markdown syntax is not processed within code blocks. E.g.,
-asterisks are just literal asterisks within a code block. This means
-it's also easy to use Markdown to write about Markdown's own syntax.</p>
-<h3 id="hr">Horizontal Rules</h3>
-<p>You can produce a horizontal rule tag (<code>&lt;hr /&gt;</code>) by placing three or
-more hyphens, asterisks, or underscores on a line by themselves. If you
-wish, you may use spaces between the hyphens or asterisks. Each of the
-following lines will produce a horizontal rule:</p>
-<pre><code>* * *
-
-***
-
-*****
-
-- - -
-
----------------------------------------
-
-_ _ _
-</code></pre>
-<hr />
-<h2 id="span">Span Elements</h2>
-<h3 id="link">Links</h3>
-<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>
-<p>In both styles, the link text is delimited by [square brackets].</p>
-<p>To create an inline link, use a set of regular parentheses immediately
-after the link text's closing square bracket. Inside the parentheses,
-put the URL where you want the link to point, along with an <em>optional</em>
-title for the link, surrounded in quotes. For example:</p>
-<pre><code>This is [an example](http://example.com/ &quot;Title&quot;) inline link.
-
-[This link](http://example.net/) has no title attribute.
-</code></pre>
-<p>Will produce:</p>
-<pre><code>&lt;p&gt;This is &lt;a href=&quot;http://example.com/&quot; title=&quot;Title&quot;&gt;
-an example&lt;/a&gt; inline link.&lt;/p&gt;
-
-&lt;p&gt;&lt;a href=&quot;http://example.net/&quot;&gt;This link&lt;/a&gt; has no
-title attribute.&lt;/p&gt;
-</code></pre>
-<p>If you're referring to a local resource on the same server, you can
-use relative paths:</p>
-<pre><code>See my [About](/about/) page for details.
-</code></pre>
-<p>Reference-style links use a second set of square brackets, inside
-which you place a label of your choosing to identify the link:</p>
-<pre><code>This is [an example][id] reference-style link.
-</code></pre>
-<p>You can optionally use a space to separate the sets of brackets:</p>
-<pre><code>This is [an example] [id] reference-style link.
-</code></pre>
-<p>Then, anywhere in the document, you define your link label like this,
-on a line by itself:</p>
-<pre><code>[id]: http://example.com/ &quot;Optional Title Here&quot;
-</code></pre>
-<p>That is:</p>
-<ul>
-<li>Square brackets containing the link identifier (optionally
-indented from the left margin using up to three spaces);</li>
-<li>followed by a colon;</li>
-<li>followed by one or more spaces (or tabs);</li>
-<li>followed by the URL for the link;</li>
-<li>optionally followed by a title attribute for the link, enclosed
-in double or single quotes.</li>
-</ul>
-<p>The link URL may, optionally, be surrounded by angle brackets:</p>
-<pre><code>[id]: &lt;http://example.com/&gt; &quot;Optional Title Here&quot;
-</code></pre>
-<p>You can put the title attribute on the next line and use extra spaces
-or tabs for padding, which tends to look better with longer URLs:</p>
-<pre><code>[id]: http://example.com/longish/path/to/resource/here
- &quot;Optional Title Here&quot;
-</code></pre>
-<p>Link definitions are only used for creating links during Markdown
-processing, and are stripped from your document in the HTML output.</p>
-<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p>
-<pre><code>[link text][a]
-[link text][A]
-</code></pre>
-<p>are equivalent.</p>
-<p>The <em>implicit link name</em> shortcut allows you to omit the name of the
-link, in which case the link text itself is used as the name.
-Just use an empty set of square brackets -- e.g., to link the word
-&quot;Google&quot; to the google.com web site, you could simply write:</p>
-<pre><code>[Google][]
-</code></pre>
-<p>And then define the link:</p>
-<pre><code>[Google]: http://google.com/
-</code></pre>
-<p>Because link names may contain spaces, this shortcut even works for
-multiple words in the link text:</p>
-<pre><code>Visit [Daring Fireball][] for more information.
-</code></pre>
-<p>And then define the link:</p>
-<pre><code>[Daring Fireball]: http://daringfireball.net/
-</code></pre>
-<p>Link definitions can be placed anywhere in your Markdown document. I
-tend to put them immediately after each paragraph in which they're
-used, but if you want, you can put them all at the end of your
-document, sort of like footnotes.</p>
-<p>Here's an example of reference links in action:</p>
-<pre><code>I get 10 times more traffic from [Google] [1] than from
-[Yahoo] [2] or [MSN] [3].
-
- [1]: http://google.com/ &quot;Google&quot;
- [2]: http://search.yahoo.com/ &quot;Yahoo Search&quot;
- [3]: http://search.msn.com/ &quot;MSN Search&quot;
-</code></pre>
-<p>Using the implicit link name shortcut, you could instead write:</p>
-<pre><code>I get 10 times more traffic from [Google][] than from
-[Yahoo][] or [MSN][].
-
- [google]: http://google.com/ &quot;Google&quot;
- [yahoo]: http://search.yahoo.com/ &quot;Yahoo Search&quot;
- [msn]: http://search.msn.com/ &quot;MSN Search&quot;
-</code></pre>
-<p>Both of the above examples will produce the following HTML output:</p>
-<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=&quot;http://google.com/&quot;
-title=&quot;Google&quot;&gt;Google&lt;/a&gt; than from
-&lt;a href=&quot;http://search.yahoo.com/&quot; title=&quot;Yahoo Search&quot;&gt;Yahoo&lt;/a&gt;
-or &lt;a href=&quot;http://search.msn.com/&quot; title=&quot;MSN Search&quot;&gt;MSN&lt;/a&gt;.&lt;/p&gt;
-</code></pre>
-<p>For comparison, here is the same paragraph written using
-Markdown's inline link style:</p>
-<pre><code>I get 10 times more traffic from [Google](http://google.com/ &quot;Google&quot;)
-than from [Yahoo](http://search.yahoo.com/ &quot;Yahoo Search&quot;) or
-[MSN](http://search.msn.com/ &quot;MSN Search&quot;).
-</code></pre>
-<p>The point of reference-style links is not that they're easier to
-write. The point is that with reference-style links, your document
-source is vastly more readable. Compare the above examples: using
-reference-style links, the paragraph itself is only 81 characters
-long; with inline-style links, it's 176 characters; and as raw HTML,
-it's 234 characters. In the raw HTML, there's more markup than there
-is text.</p>
-<p>With Markdown's reference-style links, a source document much more
-closely resembles the final output, as rendered in a browser. By
-allowing you to move the markup-related metadata out of the paragraph,
-you can add links without interrupting the narrative flow of your
-prose.</p>
-<h3 id="em">Emphasis</h3>
-<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of
-emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an
-HTML <code>&lt;em&gt;</code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML
-<code>&lt;strong&gt;</code> tag. E.g., this input:</p>
-<pre><code>*single asterisks*
-
-_single underscores_
-
-**double asterisks**
-
-__double underscores__
-</code></pre>
-<p>will produce:</p>
-<pre><code>&lt;em&gt;single asterisks&lt;/em&gt;
-
-&lt;em&gt;single underscores&lt;/em&gt;
-
-&lt;strong&gt;double asterisks&lt;/strong&gt;
-
-&lt;strong&gt;double underscores&lt;/strong&gt;
-</code></pre>
-<p>You can use whichever style you prefer; the lone restriction is that
-the same character must be used to open and close an emphasis span.</p>
-<p>Emphasis can be used in the middle of a word:</p>
-<pre><code>un*fucking*believable
-</code></pre>
-<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a
-literal asterisk or underscore.</p>
-<p>To produce a literal asterisk or underscore at a position where it
-would otherwise be used as an emphasis delimiter, you can backslash
-escape it:</p>
-<pre><code>\*this text is surrounded by literal asterisks\*
-</code></pre>
-<h3 id="code">Code</h3>
-<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).
-Unlike a pre-formatted code block, a code span indicates code within a
-normal paragraph. For example:</p>
-<pre><code>Use the `printf()` function.
-</code></pre>
-<p>will produce:</p>
-<pre><code>&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;
-</code></pre>
-<p>To include a literal backtick character within a code span, you can use
-multiple backticks as the opening and closing delimiters:</p>
-<pre><code>``There is a literal backtick (`) here.``
-</code></pre>
-<p>which will produce this:</p>
-<pre><code>&lt;p&gt;&lt;code&gt;There is a literal backtick (`) here.&lt;/code&gt;&lt;/p&gt;
-</code></pre>
-<p>The backtick delimiters surrounding a code span may include spaces --
-one after the opening, one before the closing. This allows you to place
-literal backtick characters at the beginning or end of a code span:</p>
-<pre><code>A single backtick in a code span: `` ` ``
-
-A backtick-delimited string in a code span: `` `foo` ``
-</code></pre>
-<p>will produce:</p>
-<pre><code>&lt;p&gt;A single backtick in a code span: &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
-
-&lt;p&gt;A backtick-delimited string in a code span: &lt;code&gt;`foo`&lt;/code&gt;&lt;/p&gt;
-</code></pre>
-<p>With a code span, ampersands and angle brackets are encoded as HTML
-entities automatically, which makes it easy to include example HTML
-tags. Markdown will turn this:</p>
-<pre><code>Please don't use any `&lt;blink&gt;` tags.
-</code></pre>
-<p>into:</p>
-<pre><code>&lt;p&gt;Please don't use any &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
-</code></pre>
-<p>You can write this:</p>
-<pre><code>`&amp;#8212;` is the decimal-encoded equivalent of `&amp;mdash;`.
-</code></pre>
-<p>to produce:</p>
-<pre><code>&lt;p&gt;&lt;code&gt;&amp;amp;#8212;&lt;/code&gt; is the decimal-encoded
-equivalent of &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;.&lt;/p&gt;
-</code></pre>
-<h3 id="img">Images</h3>
-<p>Admittedly, it's fairly difficult to devise a &quot;natural&quot; syntax for
-placing images into a plain text document format.</p>
-<p>Markdown uses an image syntax that is intended to resemble the syntax
-for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p>
-<p>Inline image syntax looks like this:</p>
-<pre><code>![Alt text](/path/to/img.jpg)
-
-![Alt text](/path/to/img.jpg &quot;Optional title&quot;)
-</code></pre>
-<p>That is:</p>
-<ul>
-<li>An exclamation mark: <code>!</code>;</li>
-<li>followed by a set of square brackets, containing the <code>alt</code>
-attribute text for the image;</li>
-<li>followed by a set of parentheses, containing the URL or path to
-the image, and an optional <code>title</code> attribute enclosed in double
-or single quotes.</li>
-</ul>
-<p>Reference-style image syntax looks like this:</p>
-<pre><code>![Alt text][id]
-</code></pre>
-<p>Where &quot;id&quot; is the name of a defined image reference. Image references
-are defined using syntax identical to link references:</p>
-<pre><code>[id]: url/to/image &quot;Optional title attribute&quot;
-</code></pre>
-<p>As of this writing, Markdown has no syntax for specifying the
-dimensions of an image; if this is important to you, you can simply
-use regular HTML <code>&lt;img&gt;</code> tags.</p>
-<hr />
-<h2 id="misc">Miscellaneous</h2>
-<h3 id="autolink">Automatic Links</h3>
-<p>Markdown supports a shortcut style for creating &quot;automatic&quot; links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p>
-<pre><code>&lt;http://example.com/&gt;
-</code></pre>
-<p>Markdown will turn this into:</p>
-<pre><code>&lt;a href=&quot;http://example.com/&quot;&gt;http://example.com/&lt;/a&gt;
-</code></pre>
-<p>Automatic links for email addresses work similarly, except that
-Markdown will also perform a bit of randomized decimal and hex
-entity-encoding to help obscure your address from address-harvesting
-spambots. For example, Markdown will turn this:</p>
-<pre><code>&lt;address@example.com&gt;
-</code></pre>
-<p>into something like this:</p>
-<pre><code>&lt;a href=&quot;&amp;#x6D;&amp;#x61;i&amp;#x6C;&amp;#x74;&amp;#x6F;:&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;
-&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;
-&amp;#109;&quot;&gt;&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;
-&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;&amp;#109;&lt;/a&gt;
-</code></pre>
-<p>which will render in a browser as a clickable link to &quot;address@example.com&quot;.</p>
-<p>(This sort of entity-encoding trick will indeed fool many, if not
-most, address-harvesting bots, but it definitely won't fool all of
-them. It's better than nothing, but an address published in this way
-will probably eventually start receiving spam.)</p>
-<h3 id="backslash">Backslash Escapes</h3>
-<p>Markdown allows you to use backslash escapes to generate literal
-characters which would otherwise have special meaning in Markdown's
-formatting syntax. For example, if you wanted to surround a word with
-literal asterisks (instead of an HTML <code>&lt;em&gt;</code> tag), you can backslashes
-before the asterisks, like this:</p>
-<pre><code>\*literal asterisks\*
-</code></pre>
-<p>Markdown provides backslash escapes for the following characters:</p>
-<pre><code>\ backslash
-` backtick
-* asterisk
-_ underscore
-{} curly braces
-[] square brackets
-() parentheses
-# hash mark
-+ plus sign
-- minus sign (hyphen)
-. dot
-! exclamation mark
-</code></pre>
diff --git a/oldtests/Original/Markdown_Documentation_Syntax.markdown b/oldtests/Original/Markdown_Documentation_Syntax.markdown
deleted file mode 100644
index 57360a1..0000000
--- a/oldtests/Original/Markdown_Documentation_Syntax.markdown
+++ /dev/null
@@ -1,888 +0,0 @@
-Markdown: Syntax
-================
-
-<ul id="ProjectSubmenu">
- <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
- <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>
- <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>
- <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
- <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
-</ul>
-
-
-* [Overview](#overview)
- * [Philosophy](#philosophy)
- * [Inline HTML](#html)
- * [Automatic Escaping for Special Characters](#autoescape)
-* [Block Elements](#block)
- * [Paragraphs and Line Breaks](#p)
- * [Headers](#header)
- * [Blockquotes](#blockquote)
- * [Lists](#list)
- * [Code Blocks](#precode)
- * [Horizontal Rules](#hr)
-* [Span Elements](#span)
- * [Links](#link)
- * [Emphasis](#em)
- * [Code](#code)
- * [Images](#img)
-* [Miscellaneous](#misc)
- * [Backslash Escapes](#backslash)
- * [Automatic Links](#autolink)
-
-
-**Note:** This document is itself written using Markdown; you
-can [see the source for it by adding '.text' to the URL][src].
-
- [src]: /projects/markdown/syntax.text
-
-* * *
-
-<h2 id="overview">Overview</h2>
-
-<h3 id="philosophy">Philosophy</h3>
-
-Markdown is intended to be as easy-to-read and easy-to-write as is feasible.
-
-Readability, however, is emphasized above all else. A Markdown-formatted
-document should be publishable as-is, as plain text, without looking
-like it's been marked up with tags or formatting instructions. While
-Markdown's syntax has been influenced by several existing text-to-HTML
-filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4],
-[Grutatext] [5], and [EtText] [6] -- the single biggest source of
-inspiration for Markdown's syntax is the format of plain text email.
-
- [1]: http://docutils.sourceforge.net/mirror/setext.html
- [2]: http://www.aaronsw.com/2002/atx/
- [3]: http://textism.com/tools/textile/
- [4]: http://docutils.sourceforge.net/rst.html
- [5]: http://www.triptico.com/software/grutatxt.html
- [6]: http://ettext.taint.org/doc/
-
-To this end, Markdown's syntax is comprised entirely of punctuation
-characters, which punctuation characters have been carefully chosen so
-as to look like what they mean. E.g., asterisks around a word actually
-look like \*emphasis\*. Markdown lists look like, well, lists. Even
-blockquotes look like quoted passages of text, assuming you've ever
-used email.
-
-
-
-<h3 id="html">Inline HTML</h3>
-
-Markdown's syntax is intended for one purpose: to be used as a
-format for *writing* for the web.
-
-Markdown is not a replacement for HTML, or even close to it. Its
-syntax is very small, corresponding only to a very small subset of
-HTML tags. The idea is *not* to create a syntax that makes it easier
-to insert HTML tags. In my opinion, HTML tags are already easy to
-insert. The idea for Markdown is to make it easy to read, write, and
-edit prose. HTML is a *publishing* format; Markdown is a *writing*
-format. Thus, Markdown's formatting syntax only addresses issues that
-can be conveyed in plain text.
-
-For any markup that is not covered by Markdown's syntax, you simply
-use HTML itself. There's no need to preface it or delimit it to
-indicate that you're switching from Markdown to HTML; you just use
-the tags.
-
-The only restrictions are that block-level HTML elements -- e.g. `<div>`,
-`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding
-content by blank lines, and the start and end tags of the block should
-not be indented with tabs or spaces. Markdown is smart enough not
-to add extra (unwanted) `<p>` tags around HTML block-level tags.
-
-For example, to add an HTML table to a Markdown article:
-
- This is a regular paragraph.
-
- <table>
- <tr>
- <td>Foo</td>
- </tr>
- </table>
-
- This is another regular paragraph.
-
-Note that Markdown formatting syntax is not processed within block-level
-HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an
-HTML block.
-
-Span-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be
-used anywhere in a Markdown paragraph, list item, or header. If you
-want, you can even use HTML tags instead of Markdown formatting; e.g. if
-you'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's
-link or image syntax, go right ahead.
-
-Unlike block-level HTML tags, Markdown syntax *is* processed within
-span-level tags.
-
-
-<h3 id="autoescape">Automatic Escaping for Special Characters</h3>
-
-In HTML, there are two characters that demand special treatment: `<`
-and `&`. Left angle brackets are used to start tags; ampersands are
-used to denote HTML entities. If you want to use them as literal
-characters, you must escape them as entities, e.g. `&lt;`, and
-`&amp;`.
-
-Ampersands in particular are bedeviling for web writers. If you want to
-write about 'AT&T', you need to write '`AT&amp;T`'. You even need to
-escape ampersands within URLs. Thus, if you want to link to:
-
- http://images.google.com/images?num=30&q=larry+bird
-
-you need to encode the URL as:
-
- http://images.google.com/images?num=30&amp;q=larry+bird
-
-in your anchor tag `href` attribute. Needless to say, this is easy to
-forget, and is probably the single most common source of HTML validation
-errors in otherwise well-marked-up web sites.
-
-Markdown allows you to use these characters naturally, taking care of
-all the necessary escaping for you. If you use an ampersand as part of
-an HTML entity, it remains unchanged; otherwise it will be translated
-into `&amp;`.
-
-So, if you want to include a copyright symbol in your article, you can write:
-
- &copy;
-
-and Markdown will leave it alone. But if you write:
-
- AT&T
-
-Markdown will translate it to:
-
- AT&amp;T
-
-Similarly, because Markdown supports [inline HTML](#html), if you use
-angle brackets as delimiters for HTML tags, Markdown will treat them as
-such. But if you write:
-
- 4 < 5
-
-Markdown will translate it to:
-
- 4 &lt; 5
-
-However, inside Markdown code spans and blocks, angle brackets and
-ampersands are *always* encoded automatically. This makes it easy to use
-Markdown to write about HTML code. (As opposed to raw HTML, which is a
-terrible format for writing about HTML syntax, because every single `<`
-and `&` in your example code needs to be escaped.)
-
-
-* * *
-
-
-<h2 id="block">Block Elements</h2>
-
-
-<h3 id="p">Paragraphs and Line Breaks</h3>
-
-A paragraph is simply one or more consecutive lines of text, separated
-by one or more blank lines. (A blank line is any line that looks like a
-blank line -- a line containing nothing but spaces or tabs is considered
-blank.) Normal paragraphs should not be intended with spaces or tabs.
-
-The implication of the "one or more consecutive lines of text" rule is
-that Markdown supports "hard-wrapped" text paragraphs. This differs
-significantly from most other text-to-HTML formatters (including Movable
-Type's "Convert Line Breaks" option) which translate every line break
-character in a paragraph into a `<br />` tag.
-
-When you *do* want to insert a `<br />` break tag using Markdown, you
-end a line with two or more spaces, then type return.
-
-Yes, this takes a tad more effort to create a `<br />`, but a simplistic
-"every line break is a `<br />`" rule wouldn't work for Markdown.
-Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l]
-work best -- and look better -- when you format them with hard breaks.
-
- [bq]: #blockquote
- [l]: #list
-
-
-
-<h3 id="header">Headers</h3>
-
-Markdown supports two styles of headers, [Setext] [1] and [atx] [2].
-
-Setext-style headers are "underlined" using equal signs (for first-level
-headers) and dashes (for second-level headers). For example:
-
- This is an H1
- =============
-
- This is an H2
- -------------
-
-Any number of underlining `=`'s or `-`'s will work.
-
-Atx-style headers use 1-6 hash characters at the start of the line,
-corresponding to header levels 1-6. For example:
-
- # This is an H1
-
- ## This is an H2
-
- ###### This is an H6
-
-Optionally, you may "close" atx-style headers. This is purely
-cosmetic -- you can use this if you think it looks better. The
-closing hashes don't even need to match the number of hashes
-used to open the header. (The number of opening hashes
-determines the header level.) :
-
- # This is an H1 #
-
- ## This is an H2 ##
-
- ### This is an H3 ######
-
-
-<h3 id="blockquote">Blockquotes</h3>
-
-Markdown uses email-style `>` characters for blockquoting. If you're
-familiar with quoting passages of text in an email message, then you
-know how to create a blockquote in Markdown. It looks best if you hard
-wrap the text and put a `>` before every line:
-
- > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
- >
- > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- > id sem consectetuer libero luctus adipiscing.
-
-Markdown allows you to be lazy and only put the `>` before the first
-line of a hard-wrapped paragraph:
-
- > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
- consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
-
- > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
- id sem consectetuer libero luctus adipiscing.
-
-Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
-adding additional levels of `>`:
-
- > This is the first level of quoting.
- >
- > > This is nested blockquote.
- >
- > Back to the first level.
-
-Blockquotes can contain other Markdown elements, including headers, lists,
-and code blocks:
-
- > ## This is a header.
- >
- > 1. This is the first list item.
- > 2. This is the second list item.
- >
- > Here's some example code:
- >
- > return shell_exec("echo $input | $markdown_script");
-
-Any decent text editor should make email-style quoting easy. For
-example, with BBEdit, you can make a selection and choose Increase
-Quote Level from the Text menu.
-
-
-<h3 id="list">Lists</h3>
-
-Markdown supports ordered (numbered) and unordered (bulleted) lists.
-
-Unordered lists use asterisks, pluses, and hyphens -- interchangably
--- as list markers:
-
- * Red
- * Green
- * Blue
-
-is equivalent to:
-
- + Red
- + Green
- + Blue
-
-and:
-
- - Red
- - Green
- - Blue
-
-Ordered lists use numbers followed by periods:
-
- 1. Bird
- 2. McHale
- 3. Parish
-
-It's important to note that the actual numbers you use to mark the
-list have no effect on the HTML output Markdown produces. The HTML
-Markdown produces from the above list is:
-
- <ol>
- <li>Bird</li>
- <li>McHale</li>
- <li>Parish</li>
- </ol>
-
-If you instead wrote the list in Markdown like this:
-
- 1. Bird
- 1. McHale
- 1. Parish
-
-or even:
-
- 3. Bird
- 1. McHale
- 8. Parish
-
-you'd get the exact same HTML output. The point is, if you want to,
-you can use ordinal numbers in your ordered Markdown lists, so that
-the numbers in your source match the numbers in your published HTML.
-But if you want to be lazy, you don't have to.
-
-If you do use lazy list numbering, however, you should still start the
-list with the number 1. At some point in the future, Markdown may support
-starting ordered lists at an arbitrary number.
-
-List markers typically start at the left margin, but may be indented by
-up to three spaces. List markers must be followed by one or more spaces
-or a tab.
-
-To make lists look nice, you can wrap items with hanging indents:
-
- * Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
- viverra nec, fringilla in, laoreet vitae, risus.
- * Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
- Suspendisse id sem consectetuer libero luctus adipiscing.
-
-But if you want to be lazy, you don't have to:
-
- * Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
- Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
- viverra nec, fringilla in, laoreet vitae, risus.
- * Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
- Suspendisse id sem consectetuer libero luctus adipiscing.
-
-If list items are separated by blank lines, Markdown will wrap the
-items in `<p>` tags in the HTML output. For example, this input:
-
- * Bird
- * Magic
-
-will turn into:
-
- <ul>
- <li>Bird</li>
- <li>Magic</li>
- </ul>
-
-But this:
-
- * Bird
-
- * Magic
-
-will turn into:
-
- <ul>
- <li><p>Bird</p></li>
- <li><p>Magic</p></li>
- </ul>
-
-List items may consist of multiple paragraphs. Each subsequent
-paragraph in a list item must be intended by either 4 spaces
-or one tab:
-
- 1. This is a list item with two paragraphs. Lorem ipsum dolor
- sit amet, consectetuer adipiscing elit. Aliquam hendrerit
- mi posuere lectus.
-
- Vestibulum enim wisi, viverra nec, fringilla in, laoreet
- vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
- sit amet velit.
-
- 2. Suspendisse id sem consectetuer libero luctus adipiscing.
-
-It looks nice if you indent every line of the subsequent
-paragraphs, but here again, Markdown will allow you to be
-lazy:
-
- * This is a list item with two paragraphs.
-
- This is the second paragraph in the list item. You're
- only required to indent the first line. Lorem ipsum dolor
- sit amet, consectetuer adipiscing elit.
-
- * Another item in the same list.
-
-To put a blockquote within a list item, the blockquote's `>`
-delimiters need to be indented:
-
- * A list item with a blockquote:
-
- > This is a blockquote
- > inside a list item.
-
-To put a code block within a list item, the code block needs
-to be indented *twice* -- 8 spaces or two tabs:
-
- * A list item with a code block:
-
- <code goes here>
-
-
-It's worth noting that it's possible to trigger an ordered list by
-accident, by writing something like this:
-
- 1986. What a great season.
-
-In other words, a *number-period-space* sequence at the beginning of a
-line. To avoid this, you can backslash-escape the period:
-
- 1986\. What a great season.
-
-
-
-<h3 id="precode">Code Blocks</h3>
-
-Pre-formatted code blocks are used for writing about programming or
-markup source code. Rather than forming normal paragraphs, the lines
-of a code block are interpreted literally. Markdown wraps a code block
-in both `<pre>` and `<code>` tags.
-
-To produce a code block in Markdown, simply indent every line of the
-block by at least 4 spaces or 1 tab. For example, given this input:
-
- This is a normal paragraph:
-
- This is a code block.
-
-Markdown will generate:
-
- <p>This is a normal paragraph:</p>
-
- <pre><code>This is a code block.
- </code></pre>
-
-One level of indentation -- 4 spaces or 1 tab -- is removed from each
-line of the code block. For example, this:
-
- Here is an example of AppleScript:
-
- tell application "Foo"
- beep
- end tell
-
-will turn into:
-
- <p>Here is an example of AppleScript:</p>
-
- <pre><code>tell application "Foo"
- beep
- end tell
- </code></pre>
-
-A code block continues until it reaches a line that is not indented
-(or the end of the article).
-
-Within a code block, ampersands (`&`) and angle brackets (`<` and `>`)
-are automatically converted into HTML entities. This makes it very
-easy to include example HTML source code using Markdown -- just paste
-it and indent it, and Markdown will handle the hassle of encoding the
-ampersands and angle brackets. For example, this:
-
- <div class="footer">
- &copy; 2004 Foo Corporation
- </div>
-
-will turn into:
-
- <pre><code>&lt;div class="footer"&gt;
- &amp;copy; 2004 Foo Corporation
- &lt;/div&gt;
- </code></pre>
-
-Regular Markdown syntax is not processed within code blocks. E.g.,
-asterisks are just literal asterisks within a code block. This means
-it's also easy to use Markdown to write about Markdown's own syntax.
-
-
-
-<h3 id="hr">Horizontal Rules</h3>
-
-You can produce a horizontal rule tag (`<hr />`) by placing three or
-more hyphens, asterisks, or underscores on a line by themselves. If you
-wish, you may use spaces between the hyphens or asterisks. Each of the
-following lines will produce a horizontal rule:
-
- * * *
-
- ***
-
- *****
-
- - - -
-
- ---------------------------------------
-
- _ _ _
-
-
-* * *
-
-<h2 id="span">Span Elements</h2>
-
-<h3 id="link">Links</h3>
-
-Markdown supports two style of links: *inline* and *reference*.
-
-In both styles, the link text is delimited by [square brackets].
-
-To create an inline link, use a set of regular parentheses immediately
-after the link text's closing square bracket. Inside the parentheses,
-put the URL where you want the link to point, along with an *optional*
-title for the link, surrounded in quotes. For example:
-
- This is [an example](http://example.com/ "Title") inline link.
-
- [This link](http://example.net/) has no title attribute.
-
-Will produce:
-
- <p>This is <a href="http://example.com/" title="Title">
- an example</a> inline link.</p>
-
- <p><a href="http://example.net/">This link</a> has no
- title attribute.</p>
-
-If you're referring to a local resource on the same server, you can
-use relative paths:
-
- See my [About](/about/) page for details.
-
-Reference-style links use a second set of square brackets, inside
-which you place a label of your choosing to identify the link:
-
- This is [an example][id] reference-style link.
-
-You can optionally use a space to separate the sets of brackets:
-
- This is [an example] [id] reference-style link.
-
-Then, anywhere in the document, you define your link label like this,
-on a line by itself:
-
- [id]: http://example.com/ "Optional Title Here"
-
-That is:
-
-* Square brackets containing the link identifier (optionally
- indented from the left margin using up to three spaces);
-* followed by a colon;
-* followed by one or more spaces (or tabs);
-* followed by the URL for the link;
-* optionally followed by a title attribute for the link, enclosed
- in double or single quotes.
-
-The link URL may, optionally, be surrounded by angle brackets:
-
- [id]: <http://example.com/> "Optional Title Here"
-
-You can put the title attribute on the next line and use extra spaces
-or tabs for padding, which tends to look better with longer URLs:
-
- [id]: http://example.com/longish/path/to/resource/here
- "Optional Title Here"
-
-Link definitions are only used for creating links during Markdown
-processing, and are stripped from your document in the HTML output.
-
-Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:
-
- [link text][a]
- [link text][A]
-
-are equivalent.
-
-The *implicit link name* shortcut allows you to omit the name of the
-link, in which case the link text itself is used as the name.
-Just use an empty set of square brackets -- e.g., to link the word
-"Google" to the google.com web site, you could simply write:
-
- [Google][]
-
-And then define the link:
-
- [Google]: http://google.com/
-
-Because link names may contain spaces, this shortcut even works for
-multiple words in the link text:
-
- Visit [Daring Fireball][] for more information.
-
-And then define the link:
-
- [Daring Fireball]: http://daringfireball.net/
-
-Link definitions can be placed anywhere in your Markdown document. I
-tend to put them immediately after each paragraph in which they're
-used, but if you want, you can put them all at the end of your
-document, sort of like footnotes.
-
-Here's an example of reference links in action:
-
- I get 10 times more traffic from [Google] [1] than from
- [Yahoo] [2] or [MSN] [3].
-
- [1]: http://google.com/ "Google"
- [2]: http://search.yahoo.com/ "Yahoo Search"
- [3]: http://search.msn.com/ "MSN Search"
-
-Using the implicit link name shortcut, you could instead write:
-
- I get 10 times more traffic from [Google][] than from
- [Yahoo][] or [MSN][].
-
- [google]: http://google.com/ "Google"
- [yahoo]: http://search.yahoo.com/ "Yahoo Search"
- [msn]: http://search.msn.com/ "MSN Search"
-
-Both of the above examples will produce the following HTML output:
-
- <p>I get 10 times more traffic from <a href="http://google.com/"
- title="Google">Google</a> than from
- <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
- or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
-
-For comparison, here is the same paragraph written using
-Markdown's inline link style:
-
- I get 10 times more traffic from [Google](http://google.com/ "Google")
- than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
- [MSN](http://search.msn.com/ "MSN Search").
-
-The point of reference-style links is not that they're easier to
-write. The point is that with reference-style links, your document
-source is vastly more readable. Compare the above examples: using
-reference-style links, the paragraph itself is only 81 characters
-long; with inline-style links, it's 176 characters; and as raw HTML,
-it's 234 characters. In the raw HTML, there's more markup than there
-is text.
-
-With Markdown's reference-style links, a source document much more
-closely resembles the final output, as rendered in a browser. By
-allowing you to move the markup-related metadata out of the paragraph,
-you can add links without interrupting the narrative flow of your
-prose.
-
-
-<h3 id="em">Emphasis</h3>
-
-Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
-emphasis. Text wrapped with one `*` or `_` will be wrapped with an
-HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML
-`<strong>` tag. E.g., this input:
-
- *single asterisks*
-
- _single underscores_
-
- **double asterisks**
-
- __double underscores__
-
-will produce:
-
- <em>single asterisks</em>
-
- <em>single underscores</em>
-
- <strong>double asterisks</strong>
-
- <strong>double underscores</strong>
-
-You can use whichever style you prefer; the lone restriction is that
-the same character must be used to open and close an emphasis span.
-
-Emphasis can be used in the middle of a word:
-
- un*fucking*believable
-
-But if you surround an `*` or `_` with spaces, it'll be treated as a
-literal asterisk or underscore.
-
-To produce a literal asterisk or underscore at a position where it
-would otherwise be used as an emphasis delimiter, you can backslash
-escape it:
-
- \*this text is surrounded by literal asterisks\*
-
-
-
-<h3 id="code">Code</h3>
-
-To indicate a span of code, wrap it with backtick quotes (`` ` ``).
-Unlike a pre-formatted code block, a code span indicates code within a
-normal paragraph. For example:
-
- Use the `printf()` function.
-
-will produce:
-
- <p>Use the <code>printf()</code> function.</p>
-
-To include a literal backtick character within a code span, you can use
-multiple backticks as the opening and closing delimiters:
-
- ``There is a literal backtick (`) here.``
-
-which will produce this:
-
- <p><code>There is a literal backtick (`) here.</code></p>
-
-The backtick delimiters surrounding a code span may include spaces --
-one after the opening, one before the closing. This allows you to place
-literal backtick characters at the beginning or end of a code span:
-
- A single backtick in a code span: `` ` ``
-
- A backtick-delimited string in a code span: `` `foo` ``
-
-will produce:
-
- <p>A single backtick in a code span: <code>`</code></p>
-
- <p>A backtick-delimited string in a code span: <code>`foo`</code></p>
-
-With a code span, ampersands and angle brackets are encoded as HTML
-entities automatically, which makes it easy to include example HTML
-tags. Markdown will turn this:
-
- Please don't use any `<blink>` tags.
-
-into:
-
- <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
-
-You can write this:
-
- `&#8212;` is the decimal-encoded equivalent of `&mdash;`.
-
-to produce:
-
- <p><code>&amp;#8212;</code> is the decimal-encoded
- equivalent of <code>&amp;mdash;</code>.</p>
-
-
-
-<h3 id="img">Images</h3>
-
-Admittedly, it's fairly difficult to devise a "natural" syntax for
-placing images into a plain text document format.
-
-Markdown uses an image syntax that is intended to resemble the syntax
-for links, allowing for two styles: *inline* and *reference*.
-
-Inline image syntax looks like this:
-
- ![Alt text](/path/to/img.jpg)
-
- ![Alt text](/path/to/img.jpg "Optional title")
-
-That is:
-
-* An exclamation mark: `!`;
-* followed by a set of square brackets, containing the `alt`
- attribute text for the image;
-* followed by a set of parentheses, containing the URL or path to
- the image, and an optional `title` attribute enclosed in double
- or single quotes.
-
-Reference-style image syntax looks like this:
-
- ![Alt text][id]
-
-Where "id" is the name of a defined image reference. Image references
-are defined using syntax identical to link references:
-
- [id]: url/to/image "Optional title attribute"
-
-As of this writing, Markdown has no syntax for specifying the
-dimensions of an image; if this is important to you, you can simply
-use regular HTML `<img>` tags.
-
-
-* * *
-
-
-<h2 id="misc">Miscellaneous</h2>
-
-<h3 id="autolink">Automatic Links</h3>
-
-Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:
-
- <http://example.com/>
-
-Markdown will turn this into:
-
- <a href="http://example.com/">http://example.com/</a>
-
-Automatic links for email addresses work similarly, except that
-Markdown will also perform a bit of randomized decimal and hex
-entity-encoding to help obscure your address from address-harvesting
-spambots. For example, Markdown will turn this:
-
- <address@example.com>
-
-into something like this:
-
- <a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
- &#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
- &#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
- &#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
-
-which will render in a browser as a clickable link to "address@example.com".
-
-(This sort of entity-encoding trick will indeed fool many, if not
-most, address-harvesting bots, but it definitely won't fool all of
-them. It's better than nothing, but an address published in this way
-will probably eventually start receiving spam.)
-
-
-
-<h3 id="backslash">Backslash Escapes</h3>
-
-Markdown allows you to use backslash escapes to generate literal
-characters which would otherwise have special meaning in Markdown's
-formatting syntax. For example, if you wanted to surround a word with
-literal asterisks (instead of an HTML `<em>` tag), you can backslashes
-before the asterisks, like this:
-
- \*literal asterisks\*
-
-Markdown provides backslash escapes for the following characters:
-
- \ backslash
- ` backtick
- * asterisk
- _ underscore
- {} curly braces
- [] square brackets
- () parentheses
- # hash mark
- + plus sign
- - minus sign (hyphen)
- . dot
- ! exclamation mark
-
diff --git a/oldtests/Original/Nested_blockquotes.html b/oldtests/Original/Nested_blockquotes.html
deleted file mode 100644
index 02efc59..0000000
--- a/oldtests/Original/Nested_blockquotes.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<blockquote>
-<p>foo</p>
-<blockquote>
-<p>bar</p>
-</blockquote>
-<p>foo</p>
-</blockquote>
diff --git a/oldtests/Original/Nested_blockquotes.markdown b/oldtests/Original/Nested_blockquotes.markdown
deleted file mode 100644
index ed3c624..0000000
--- a/oldtests/Original/Nested_blockquotes.markdown
+++ /dev/null
@@ -1,5 +0,0 @@
-> foo
->
-> > bar
->
-> foo
diff --git a/oldtests/Original/Ordered_and_unordered_lists.html b/oldtests/Original/Ordered_and_unordered_lists.html
deleted file mode 100644
index 78d752e..0000000
--- a/oldtests/Original/Ordered_and_unordered_lists.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<h2>Unordered</h2>
-<p>Asterisks tight:</p>
-<ul>
-<li>asterisk 1</li>
-<li>asterisk 2</li>
-<li>asterisk 3</li>
-</ul>
-<p>Asterisks loose:</p>
-<ul>
-<li><p>asterisk 1</p></li>
-<li><p>asterisk 2</p></li>
-<li><p>asterisk 3</p></li>
-</ul>
-<hr />
-<p>Pluses tight:</p>
-<ul>
-<li>Plus 1</li>
-<li>Plus 2</li>
-<li>Plus 3</li>
-</ul>
-<p>Pluses loose:</p>
-<ul>
-<li><p>Plus 1</p></li>
-<li><p>Plus 2</p></li>
-<li><p>Plus 3</p></li>
-</ul>
-<hr />
-<p>Minuses tight:</p>
-<ul>
-<li>Minus 1</li>
-<li>Minus 2</li>
-<li>Minus 3</li>
-</ul>
-<p>Minuses loose:</p>
-<ul>
-<li><p>Minus 1</p></li>
-<li><p>Minus 2</p></li>
-<li><p>Minus 3</p></li>
-</ul>
-<h2>Ordered</h2>
-<p>Tight:</p>
-<ol>
-<li>First</li>
-<li>Second</li>
-<li>Third</li>
-</ol>
-<p>and:</p>
-<ol>
-<li>One</li>
-<li>Two</li>
-<li>Three</li>
-</ol>
-<p>Loose using tabs:</p>
-<ol>
-<li><p>First</p></li>
-<li><p>Second</p></li>
-<li><p>Third</p></li>
-</ol>
-<p>and using spaces:</p>
-<ol>
-<li><p>One</p></li>
-<li><p>Two</p></li>
-<li><p>Three</p></li>
-</ol>
-<p>Multiple paragraphs:</p>
-<ol>
-<li><p>Item 1, graf one.</p>
-<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's
-back.</p></li>
-<li><p>Item 2.</p></li>
-<li><p>Item 3.</p></li>
-</ol>
-<h2>Nested</h2>
-<ul>
-<li>Tab
-<ul>
-<li>Tab
-<ul>
-<li>Tab</li>
-</ul></li>
-</ul></li>
-</ul>
-<p>Here's another:</p>
-<ol>
-<li>First</li>
-<li>Second:
-<ul>
-<li>Fee</li>
-<li>Fie</li>
-<li>Foe</li>
-</ul></li>
-<li>Third</li>
-</ol>
-<p>Same thing but with paragraphs:</p>
-<ol>
-<li><p>First</p></li>
-<li><p>Second:</p>
-<ul>
-<li>Fee</li>
-<li>Fie</li>
-<li>Foe</li>
-</ul></li>
-<li><p>Third</p></li>
-</ol>
-<p>This was an error in Markdown 1.0.1:</p>
-<ul>
-<li><p>this</p>
-<ul>
-<li>sub</li>
-</ul>
-<p>that</p></li>
-</ul>
diff --git a/oldtests/Original/Ordered_and_unordered_lists.markdown b/oldtests/Original/Ordered_and_unordered_lists.markdown
deleted file mode 100644
index 7f3b497..0000000
--- a/oldtests/Original/Ordered_and_unordered_lists.markdown
+++ /dev/null
@@ -1,131 +0,0 @@
-## Unordered
-
-Asterisks tight:
-
-* asterisk 1
-* asterisk 2
-* asterisk 3
-
-
-Asterisks loose:
-
-* asterisk 1
-
-* asterisk 2
-
-* asterisk 3
-
-* * *
-
-Pluses tight:
-
-+ Plus 1
-+ Plus 2
-+ Plus 3
-
-
-Pluses loose:
-
-+ Plus 1
-
-+ Plus 2
-
-+ Plus 3
-
-* * *
-
-
-Minuses tight:
-
-- Minus 1
-- Minus 2
-- Minus 3
-
-
-Minuses loose:
-
-- Minus 1
-
-- Minus 2
-
-- Minus 3
-
-
-## Ordered
-
-Tight:
-
-1. First
-2. Second
-3. Third
-
-and:
-
-1. One
-2. Two
-3. Three
-
-
-Loose using tabs:
-
-1. First
-
-2. Second
-
-3. Third
-
-and using spaces:
-
-1. One
-
-2. Two
-
-3. Three
-
-Multiple paragraphs:
-
-1. Item 1, graf one.
-
- Item 2. graf two. The quick brown fox jumped over the lazy dog's
- back.
-
-2. Item 2.
-
-3. Item 3.
-
-
-
-## Nested
-
-* Tab
- * Tab
- * Tab
-
-Here's another:
-
-1. First
-2. Second:
- * Fee
- * Fie
- * Foe
-3. Third
-
-Same thing but with paragraphs:
-
-1. First
-
-2. Second:
- * Fee
- * Fie
- * Foe
-
-3. Third
-
-
-This was an error in Markdown 1.0.1:
-
-* this
-
- * sub
-
- that
diff --git a/oldtests/Original/README b/oldtests/Original/README
deleted file mode 100644
index 5143258..0000000
--- a/oldtests/Original/README
+++ /dev/null
@@ -1,15 +0,0 @@
-These are from John Gruber's original markdown test suite, via
-Michel Fortin's mdtest.
-
-The html files have been modified slightly in ways that do not affect the
-semantics. For example, entities are used for quotes in text, and
-blank lines are omitted between block-level tags.
-
-Trailing blank spaces are removed from lines in raw HTML blocks.
-
-The one (insignificant) semantic change is switching the order
-of emph and strong tags in the output for ***strong and emph***.
-
-We have removed Hard-wrapped_paragraphs_with_list-like_lines tests,
-because the new implementation no longer requires a blank line
-before a list.
diff --git a/oldtests/Original/Strong_and_em_together.html b/oldtests/Original/Strong_and_em_together.html
deleted file mode 100644
index 2629594..0000000
--- a/oldtests/Original/Strong_and_em_together.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<p><strong><em>This is strong and em.</em></strong></p>
-<p>So is <strong><em>this</em></strong> word.</p>
-<p><strong><em>This is strong and em.</em></strong></p>
-<p>So is <strong><em>this</em></strong> word.</p>
diff --git a/oldtests/Original/Strong_and_em_together.markdown b/oldtests/Original/Strong_and_em_together.markdown
deleted file mode 100644
index 95ee690..0000000
--- a/oldtests/Original/Strong_and_em_together.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-***This is strong and em.***
-
-So is ***this*** word.
-
-___This is strong and em.___
-
-So is ___this___ word.
diff --git a/oldtests/Original/Tabs.html b/oldtests/Original/Tabs.html
deleted file mode 100644
index 5389bdf..0000000
--- a/oldtests/Original/Tabs.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<ul>
-<li><p>this is a list item
-indented with tabs</p></li>
-<li><p>this is a list item
-indented with spaces</p></li>
-</ul>
-<p>Code:</p>
-<pre><code>this code block is indented by one tab
-</code></pre>
-<p>And:</p>
-<pre><code> this code block is indented by two tabs
-</code></pre>
-<p>And:</p>
-<pre><code>+ this is an example list item
- indented with tabs
-
-+ this is an example list item
- indented with spaces
-</code></pre>
diff --git a/oldtests/Original/Tabs.markdown b/oldtests/Original/Tabs.markdown
deleted file mode 100644
index 589d113..0000000
--- a/oldtests/Original/Tabs.markdown
+++ /dev/null
@@ -1,21 +0,0 @@
-+ this is a list item
- indented with tabs
-
-+ this is a list item
- indented with spaces
-
-Code:
-
- this code block is indented by one tab
-
-And:
-
- this code block is indented by two tabs
-
-And:
-
- + this is an example list item
- indented with tabs
-
- + this is an example list item
- indented with spaces
diff --git a/oldtests/Original/Tidyness.html b/oldtests/Original/Tidyness.html
deleted file mode 100644
index f2a8ce7..0000000
--- a/oldtests/Original/Tidyness.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<blockquote>
-<p>A list within a blockquote:</p>
-<ul>
-<li>asterisk 1</li>
-<li>asterisk 2</li>
-<li>asterisk 3</li>
-</ul>
-</blockquote>
diff --git a/oldtests/Original/Tidyness.markdown b/oldtests/Original/Tidyness.markdown
deleted file mode 100644
index 5f18b8d..0000000
--- a/oldtests/Original/Tidyness.markdown
+++ /dev/null
@@ -1,5 +0,0 @@
-> A list within a blockquote:
->
-> * asterisk 1
-> * asterisk 2
-> * asterisk 3
diff --git a/oldtests/Tabs/TabConversionUnicode.html b/oldtests/Tabs/TabConversionUnicode.html
deleted file mode 100644
index f596f6a..0000000
--- a/oldtests/Tabs/TabConversionUnicode.html
+++ /dev/null
@@ -1 +0,0 @@
-<p><code>То лпой</code> is a Russian word with a tab inside.</p>
diff --git a/oldtests/Tabs/TabConversionUnicode.markdown b/oldtests/Tabs/TabConversionUnicode.markdown
deleted file mode 100644
index 0bd7b52..0000000
--- a/oldtests/Tabs/TabConversionUnicode.markdown
+++ /dev/null
@@ -1 +0,0 @@
-`То лпой` is a Russian word with a tab inside.
diff --git a/spec.txt b/spec.txt
index fce8792..e3cf027 100644
--- a/spec.txt
+++ b/spec.txt
@@ -2,8 +2,8 @@
title: CommonMark Spec
author:
- John MacFarlane
-version: 2
-date: 2014-09-19
+version: 0.3
+date: 2014-10-24
...
# Introduction
@@ -192,10 +192,10 @@ In the examples, the `→` character is used to represent tabs.
# Preprocessing
A [line](#line) <a id="line"></a>
-is a sequence of zero or more characters followed by a line
-ending (CR, LF, or CRLF) or by the end of
-file.
+is a sequence of zero or more [characters](#character) followed by a
+line ending (CR, LF, or CRLF) or by the end of file.
+A [character](#character)<a id="character"></a> is a unicode code point.
This spec does not specify an encoding; it thinks of lines as composed
of characters rather than bytes. A conforming parser may be limited
to a certain encoding.
@@ -662,7 +662,10 @@ ATX headers can be empty:
A [setext header](#setext-header) <a id="setext-header"></a>
consists of a line of text, containing at least one nonspace character,
with no more than 3 spaces indentation, followed by a [setext header
-underline](#setext-header-underline). A [setext header
+underline](#setext-header-underline). The line of text must be
+one that, were it not followed by the setext header underline,
+would be interpreted as part of a paragraph: it cannot be a code
+block, header, blockquote, horizontal rule, or list. A [setext header
underline](#setext-header-underline) <a id="setext-header-underline"></a>
is a sequence of `=` characters or a sequence of `-` characters, with no
more than 3 spaces indentation and any number of trailing
@@ -863,6 +866,56 @@ Setext headers cannot be empty:
<p>====</p>
.
+Setext header text lines must not be interpretable as block
+constructs other than paragraphs. So, the line of dashes
+in these examples gets interpreted as a horizontal rule:
+
+.
+---
+---
+.
+<hr />
+<hr />
+.
+
+.
+- foo
+-----
+.
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+.
+
+.
+ foo
+---
+.
+<pre><code>foo
+</code></pre>
+<hr />
+.
+
+.
+> foo
+-----
+.
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+.
+
+If you want a header with `> foo` as its literal text, you can
+use backslash escapes:
+
+.
+\> foo
+------
+.
+<h2>&gt; foo</h2>
+.
## Indented code blocks
@@ -1355,8 +1408,8 @@ name is one of the following (case-insensitive):
`output`, `col`, `p`, `colgroup`, `pre`, `dd`, `progress`, `div`,
`section`, `dl`, `table`, `td`, `dt`, `tbody`, `embed`, `textarea`,
`fieldset`, `tfoot`, `figcaption`, `th`, `figure`, `thead`, `footer`,
-`footer`, `tr`, `form`, `ul`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`,
-`video`, `script`, `style`.
+`tr`, `form`, `ul`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `video`,
+`script`, `style`.
An [HTML block](#html-block) <a id="html-block"></a> begins with an
[HTML block tag](#html-block-tag), [HTML comment](#html-comment),
@@ -1447,11 +1500,11 @@ A processing instruction:
.
<?php
- echo 'foo'
+ echo '>';
?>
.
<?php
- echo 'foo'
+ echo '>';
?>
.
@@ -2010,7 +2063,7 @@ The following rules define [block quotes](#block-quote):
<a id="block-quote"></a>
1. **Basic case.** If a string of lines *Ls* constitute a sequence
- of blocks *Bs*, then the result of appending a [block quote
+ of blocks *Bs*, then the result of prepending a [block quote
marker](#block-quote-marker) to the beginning of each line in *Ls*
is a [block quote](#block-quote) containing *Bs*.
@@ -3005,6 +3058,21 @@ A list item may be empty:
</ul>
.
+A list item can contain a header:
+
+.
+- # Foo
+- Bar
+ ---
+ baz
+.
+<ul>
+<li><h1>Foo</h1></li>
+<li><h2>Bar</h2>
+<p>baz</p></li>
+</ul>
+.
+
### Motivation
John Gruber's Markdown spec says the following about list items:
@@ -3214,7 +3282,7 @@ A list is [loose](#loose) if it any of its constituent list items are
separated by blank lines, or if any of its constituent list items
directly contain two block-level elements with a blank line between
them. Otherwise a list is [tight](#tight). (The difference in HTML output
-is that paragraphs in a loose with are wrapped in `<p>` tags, while
+is that paragraphs in a loose list are wrapped in `<p>` tags, while
paragraphs in a tight list are not.)
Changing the bullet or ordered list delimiter starts a new list:
@@ -3686,9 +3754,9 @@ raw HTML:
.
.
-<http://google.com?find=\*>
+<http://example.com?find=\*>
.
-<p><a href="http://google.com?find=%5C*">http://google.com?find=\*</a></p>
+<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
.
.
@@ -3727,21 +3795,25 @@ foo
## Entities
-With the goal of making this standard as HTML-agnostic as possible, all HTML valid HTML Entities in any
-context are recognized as such and converted into their actual values (i.e. the UTF8 characters representing
-the entity itself) before they are stored in the AST.
+With the goal of making this standard as HTML-agnostic as possible, all
+valid HTML entities in any context are recognized as such and
+converted into unicode characters before they are stored in the AST.
-This allows implementations that target HTML output to trivially escape the entities when generating HTML,
-and simplifies the job of implementations targetting other languages, as these will only need to handle the
-UTF8 chars and need not be HTML-entity aware.
+This allows implementations that target HTML output to trivially escape
+the entities when generating HTML, and simplifies the job of
+implementations targetting other languages, as these will only need to
+handle the unicode chars and need not be HTML-entity aware.
[Named entities](#name-entities) <a id="named-entities"></a> consist of `&`
-+ any of the valid HTML5 entity names + `;`. The [following document](http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json)
-is used as an authoritative source of the valid entity names and their corresponding codepoints.
++ any of the valid HTML5 entity names + `;`. The
+[following document](http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json)
+is used as an authoritative source of the valid entity names and their
+corresponding codepoints.
-Conforming implementations that target Markdown don't need to generate entities for all the valid
-named entities that exist, with the exception of `"` (`&quot;`), `&` (`&amp;`), `<` (`&lt;`) and `>` (`&gt;`),
-which always need to be written as entities for security reasons.
+Conforming implementations that target HTML don't need to generate
+entities for all the valid named entities that exist, with the exception
+of `"` (`&quot;`), `&` (`&amp;`), `<` (`&lt;`) and `>` (`&gt;`), which
+always need to be written as entities for security reasons.
.
&nbsp; &amp; &copy; &AElig; &Dcaron; &frac34; &HilbertSpace; &DifferentialD; &ClockwiseContourIntegral;
@@ -3750,9 +3822,10 @@ which always need to be written as entities for security reasons.
.
[Decimal entities](#decimal-entities) <a id="decimal-entities"></a>
-consist of `&#` + a string of 1--8 arabic digits + `;`. Again, these entities need to be recognised
-and tranformed into their corresponding UTF8 codepoints. Invalid Unicode codepoints will be written
-as the "unknown codepoint" character (`0xFFFD`)
+consist of `&#` + a string of 1--8 arabic digits + `;`. Again, these
+entities need to be recognised and tranformed into their corresponding
+UTF8 codepoints. Invalid Unicode codepoints will be written as the
+"unknown codepoint" character (`0xFFFD`)
.
&#35; &#1234; &#992; &#98765432;
@@ -3779,7 +3852,8 @@ Here are some nonentities:
.
Although HTML5 does accept some entities without a trailing semicolon
-(such as `&copy`), these are not recognized as entities here, because it makes the grammar too ambiguous:
+(such as `&copy`), these are not recognized as entities here, because it
+makes the grammar too ambiguous:
.
&copy
@@ -3787,7 +3861,8 @@ Although HTML5 does accept some entities without a trailing semicolon
<p>&amp;copy</p>
.
-Strings that are not on the list of HTML5 named entities are not recognized as entities either:
+Strings that are not on the list of HTML5 named entities are not
+recognized as entities either:
.
&MadeUpEntity;
@@ -4035,7 +4110,7 @@ for efficient parsing strategies that do not backtrack:
(a) it is not part of a sequence of four or more unescaped `*`s,
(b) it is not followed by whitespace, and
(c) either it is not followed by a `*` character or it is
- followed immediately by strong emphasis.
+ followed immediately by emphasis or strong emphasis.
2. A single `_` character [can open emphasis](#can-open-emphasis) iff
@@ -4043,7 +4118,7 @@ for efficient parsing strategies that do not backtrack:
(b) it is not followed by whitespace,
(c) it is not preceded by an ASCII alphanumeric character, and
(d) either it is not followed by a `_` character or it is
- followed immediately by strong emphasis.
+ followed immediately by emphasis or strong emphasis.
3. A single `*` character [can close emphasis](#can-close-emphasis)
<a id="can-close-emphasis"></a> iff
@@ -4088,16 +4163,42 @@ for efficient parsing strategies that do not backtrack:
(c) it is not followed by an ASCII alphanumeric character.
9. Emphasis begins with a delimiter that [can open
- emphasis](#can-open-emphasis) and includes inlines parsed
- sequentially until a delimiter that [can close
+ emphasis](#can-open-emphasis) and ends with a delimiter that [can close
emphasis](#can-close-emphasis), and that uses the same
- character (`_` or `*`) as the opening delimiter, is reached.
+ character (`_` or `*`) as the opening delimiter. The inlines
+ between the open delimiter and the closing delimiter are the
+ contents of the emphasis inline.
10. Strong emphasis begins with a delimiter that [can open strong
- emphasis](#can-open-strong-emphasis) and includes inlines parsed
- sequentially until a delimiter that [can close strong
- emphasis](#can-close-strong-emphasis), and that uses the
- same character (`_` or `*`) as the opening delimiter, is reached.
+ emphasis](#can-open-strong-emphasis) and ends with a delimiter that
+ [can close strong emphasis](#can-close-strong-emphasis), and that uses the
+ same character (`_` or `*`) as the opening delimiter. The inlines
+ between the open delimiter and the closing delimiter are the
+ contents of the strong emphasis inline.
+
+Where rules 1--10 above are compatible with multiple parsings,
+the following principles resolve ambiguity:
+
+11. An interpretation `<strong>...</strong>` is always preferred to
+ `<em><em>...</em></em>`.
+
+12. An interpretation `<strong><em>...</em></strong>` is always
+ preferred to `<em><strong>..</strong></em>`.
+
+13. Earlier closings are preferred to later closings. Thus,
+ when two potential emphasis or strong emphasis spans overlap,
+ the first takes precedence: for example, `*foo _bar* baz_`
+ is parsed as `<em>foo _bar</em> baz_` rather than
+ `*foo <em>bar* baz</em>`. For the same reason,
+ `**foo*bar**` is parsed as `<em><em>foo</em>bar</em>*`
+ rather than `<strong>foo*bar</strong>`.
+
+14. Inline code spans, links, images, and HTML tags group more tightly
+ than emphasis. So, when there is a choice between an interpretation
+ that contains one of these elements and one that does not, the
+ former always wins. Thus, for example, `*[foo*](bar)` is
+ parsed as `*<a href="bar">foo*</a>` rather than as
+ `<em>[foo</em>](bar)`.
These rules can be illustrated through a series of examples.
@@ -4345,6 +4446,32 @@ __this is a double underscore (`__`)__
<p><strong>this is a double underscore (<code>__</code>)</strong></p>
.
+Or use the other emphasis character:
+
+.
+*_*
+.
+<p><em>_</em></p>
+.
+
+.
+_*_
+.
+<p><em>*</em></p>
+.
+
+.
+*__*
+.
+<p><em>__</em></p>
+.
+
+.
+_**_
+.
+<p><em>**</em></p>
+.
+
`*` delimiters allow intra-word emphasis; `_` delimiters do not:
.
@@ -4520,6 +4647,36 @@ __foo _bar_ baz__
<p><strong>foo <em>bar</em> baz</strong></p>
.
+.
+**foo, *bar*, baz**
+.
+<p><strong>foo, <em>bar</em>, baz</strong></p>
+.
+
+.
+__foo, _bar_, baz__
+.
+<p><strong>foo, <em>bar</em>, baz</strong></p>
+.
+
+But note:
+
+.
+*foo**bar**baz*
+.
+<p><em>foo</em><em>bar</em><em>baz</em></p>
+.
+
+.
+**foo*bar*baz**
+.
+<p><em><em>foo</em>bar</em>baz**</p>
+.
+
+The difference is that in the two preceding cases,
+the internal delimiters [can close emphasis](#can-close-emphasis),
+while in the cases with spaces, they cannot.
+
Note that you cannot nest emphasis directly inside emphasis
using the same delimeter, or strong emphasis directly inside
strong emphasis:
@@ -4601,7 +4758,7 @@ However, a string of four or more `****` can never close emphasis:
<p>*foo****</p>
.
-Note that there are some asymmetries here:
+We retain symmetry in these cases:
.
*foo**
@@ -4609,7 +4766,7 @@ Note that there are some asymmetries here:
**foo*
.
<p><em>foo</em>*</p>
-<p>**foo*</p>
+<p>*<em>foo</em></p>
.
.
@@ -4618,18 +4775,12 @@ Note that there are some asymmetries here:
**foo* bar*
.
<p><em>foo <em>bar</em></em></p>
-<p>**foo* bar*</p>
+<p><em><em>foo</em> bar</em></p>
.
More cases with mismatched delimiters:
.
-**foo* bar*
-.
-<p>**foo* bar*</p>
-.
-
-.
*bar***
.
<p><em>bar</em>**</p>
@@ -4638,7 +4789,7 @@ More cases with mismatched delimiters:
.
***foo*
.
-<p>***foo*</p>
+<p>**<em>foo</em></p>
.
.
@@ -4650,7 +4801,7 @@ More cases with mismatched delimiters:
.
***foo**
.
-<p>***foo**</p>
+<p>*<strong>foo</strong></p>
.
.
@@ -4659,6 +4810,46 @@ More cases with mismatched delimiters:
<p>***foo <em>bar</em></p>
.
+The following cases illustrate rule 13:
+
+.
+*foo _bar* baz_
+.
+<p><em>foo _bar</em> baz_</p>
+.
+
+.
+**foo bar* baz**
+.
+<p><em><em>foo bar</em> baz</em>*</p>
+.
+
+The following cases illustrate rule 14:
+
+.
+*[foo*](bar)
+.
+<p>*<a href="bar">foo*</a></p>
+.
+
+.
+*![foo*](bar)
+.
+<p>*<img src="bar" alt="foo*" /></p>
+.
+
+.
+*<img src="foo" title="*"/>
+.
+<p>*<img src="foo" title="*"/></p>
+.
+
+.
+*a`a*`
+.
+<p>*a<code>a*</code></p>
+.
+
## Links
A link contains a [link label](#link-label) (the visible text),
@@ -4817,9 +5008,10 @@ in Markdown:
<p><a href="foo):">link</a></p>
.
-URL-escaping and should be left alone inside the destination, as all URL-escaped characters
-are also valid URL characters. HTML entities in the destination will be parsed into their UTF8
-codepoints, as usual, and optionally URL-escaped when written as HTML.
+URL-escaping should be left alone inside the destination, as all
+URL-escaped characters are also valid URL characters. HTML entities in
+the destination will be parsed into their UTF-8 codepoints, as usual, and
+optionally URL-escaped when written as HTML.
.
[link](foo%20b&auml;)
@@ -5504,9 +5696,9 @@ spec](http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-m
Examples of email autolinks:
.
-<foo@bar.baz.com>
+<foo@bar.example.com>
.
-<p><a href="mailto:foo@bar.baz.com">foo@bar.baz.com</a></p>
+<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
.
.
@@ -5548,15 +5740,15 @@ These are not autolinks:
.
.
-http://google.com
+http://example.com
.
-<p>http://google.com</p>
+<p>http://example.com</p>
.
.
-foo@bar.baz.com
+foo@bar.example.com
.
-<p>foo@bar.baz.com</p>
+<p>foo@bar.example.com</p>
.
## Raw HTML
diff --git a/src/blocks.c b/src/blocks.c
index 5b38116..ae106d2 100644
--- a/src/blocks.c
+++ b/src/blocks.c
@@ -4,7 +4,7 @@
#include <stdbool.h>
#include <ctype.h>
-#include "stmd.h"
+#include "cmark.h"
#include "utf8.h"
#include "scanners.h"
#include "inlines.h"
@@ -19,15 +19,15 @@ static node_block* make_block(int tag, int start_line, int start_column)
{
node_block* e;
- e = malloc(sizeof(node_block));
- memset(e, 0x0, sizeof(*e));
-
- e->tag = tag;
- e->open = true;
- e->start_line = start_line;
- e->start_column = start_column;
- e->end_line = start_line;
- strbuf_init(&e->string_content, 32);
+ e = calloc(1, sizeof(*e));
+ if(e != NULL) {
+ e->tag = tag;
+ e->open = true;
+ e->start_line = start_line;
+ e->start_column = start_column;
+ e->end_line = start_line;
+ strbuf_init(&e->string_content, 32);
+ }
return e;
}
@@ -47,13 +47,13 @@ bool is_blank(strbuf *s, int offset)
{
while (offset < s->size) {
switch (s->ptr[offset]) {
- case '\n':
- return true;
- case ' ':
- offset++;
- break;
- default:
- return false;
+ case '\n':
+ return true;
+ case ' ':
+ offset++;
+ break;
+ default:
+ return false;
}
}
@@ -63,17 +63,17 @@ bool is_blank(strbuf *s, int offset)
static inline bool can_contain(int parent_type, int child_type)
{
return ( parent_type == BLOCK_DOCUMENT ||
- parent_type == BLOCK_BQUOTE ||
- parent_type == BLOCK_LIST_ITEM ||
- (parent_type == BLOCK_LIST && child_type == BLOCK_LIST_ITEM) );
+ parent_type == BLOCK_BQUOTE ||
+ parent_type == BLOCK_LIST_ITEM ||
+ (parent_type == BLOCK_LIST && child_type == BLOCK_LIST_ITEM) );
}
static inline bool accepts_lines(int block_type)
{
return (block_type == BLOCK_PARAGRAPH ||
- block_type == BLOCK_ATX_HEADER ||
- block_type == BLOCK_INDENTED_CODE ||
- block_type == BLOCK_FENCED_CODE);
+ block_type == BLOCK_ATX_HEADER ||
+ block_type == BLOCK_INDENTED_CODE ||
+ block_type == BLOCK_FENCED_CODE);
}
static void add_line(node_block* node_block, chunk *ch, int offset)
@@ -87,7 +87,7 @@ static void remove_trailing_blank_lines(strbuf *ln)
int i;
for (i = ln->size - 1; i >= 0; --i) {
- char c = ln->ptr[i];
+ unsigned char c = ln->ptr[i];
if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
break;
@@ -156,77 +156,77 @@ static void finalize(node_block* b, int line_number)
}
switch (b->tag) {
- case BLOCK_PARAGRAPH:
- pos = 0;
- while (strbuf_at(&b->string_content, 0) == '[' &&
- (pos = parse_reference_inline(&b->string_content, b->top->as.document.refmap))) {
-
- strbuf_drop(&b->string_content, pos);
- }
- if (is_blank(&b->string_content, 0)) {
- b->tag = BLOCK_REFERENCE_DEF;
- }
- break;
+ case BLOCK_PARAGRAPH:
+ pos = 0;
+ while (strbuf_at(&b->string_content, 0) == '[' &&
+ (pos = parse_reference_inline(&b->string_content, b->top->as.document.refmap))) {
- case BLOCK_INDENTED_CODE:
- remove_trailing_blank_lines(&b->string_content);
- strbuf_putc(&b->string_content, '\n');
- break;
-
- case BLOCK_FENCED_CODE:
- // first line of contents becomes info
- firstlinelen = strbuf_strchr(&b->string_content, '\n', 0);
-
- strbuf_init(&b->as.code.info, 0);
- houdini_unescape_html_f(
- &b->as.code.info,
- b->string_content.ptr,
- firstlinelen
+ strbuf_drop(&b->string_content, pos);
+ }
+ if (is_blank(&b->string_content, 0)) {
+ b->tag = BLOCK_REFERENCE_DEF;
+ }
+ break;
+
+ case BLOCK_INDENTED_CODE:
+ remove_trailing_blank_lines(&b->string_content);
+ strbuf_putc(&b->string_content, '\n');
+ break;
+
+ case BLOCK_FENCED_CODE:
+ // first line of contents becomes info
+ firstlinelen = strbuf_strchr(&b->string_content, '\n', 0);
+
+ strbuf_init(&b->as.code.info, 0);
+ houdini_unescape_html_f(
+ &b->as.code.info,
+ b->string_content.ptr,
+ firstlinelen
);
- strbuf_drop(&b->string_content, firstlinelen + 1);
+ strbuf_drop(&b->string_content, firstlinelen + 1);
- strbuf_trim(&b->as.code.info);
- strbuf_unescape(&b->as.code.info);
- break;
+ strbuf_trim(&b->as.code.info);
+ strbuf_unescape(&b->as.code.info);
+ break;
- case BLOCK_LIST: // determine tight/loose status
- b->as.list.tight = true; // tight by default
- item = b->children;
+ case BLOCK_LIST: // determine tight/loose status
+ b->as.list.tight = true; // tight by default
+ item = b->children;
- while (item) {
- // check for non-final non-empty list item ending with blank line:
- if (item->last_line_blank && item->next) {
+ while (item) {
+ // check for non-final non-empty list item ending with blank line:
+ if (item->last_line_blank && item->next) {
+ b->as.list.tight = false;
+ break;
+ }
+ // recurse into children of list item, to see if there are
+ // spaces between them:
+ subitem = item->children;
+ while (subitem) {
+ if (ends_with_blank_line(subitem) &&
+ (item->next || subitem->next)) {
b->as.list.tight = false;
break;
}
- // recurse into children of list item, to see if there are
- // spaces between them:
- subitem = item->children;
- while (subitem) {
- if (ends_with_blank_line(subitem) &&
- (item->next || subitem->next)) {
- b->as.list.tight = false;
- break;
- }
- subitem = subitem->next;
- }
- if (!(b->as.list.tight)) {
- break;
- }
- item = item->next;
+ subitem = subitem->next;
+ }
+ if (!(b->as.list.tight)) {
+ break;
}
+ item = item->next;
+ }
- break;
+ break;
- default:
- break;
+ default:
+ break;
}
}
// Add a node_block as child of another. Return pointer to child.
static node_block* add_child(node_block* parent,
- int block_type, int start_line, int start_column)
+ int block_type, int start_line, int start_column)
{
assert(parent);
@@ -253,7 +253,7 @@ static node_block* add_child(node_block* parent,
}
// Free a node_block list and any children.
-void stmd_free_nodes(node_block *e)
+void cmark_free_nodes(node_block *e)
{
node_block * next;
while (e != NULL) {
@@ -265,7 +265,7 @@ void stmd_free_nodes(node_block *e)
} else if (e->tag == BLOCK_DOCUMENT) {
reference_map_free(e->as.document.refmap);
}
- stmd_free_nodes(e->children);
+ cmark_free_nodes(e->children);
free(e);
e = next;
}
@@ -276,14 +276,14 @@ void stmd_free_nodes(node_block *e)
void process_inlines(node_block* cur, reference_map *refmap)
{
switch (cur->tag) {
- case BLOCK_PARAGRAPH:
- case BLOCK_ATX_HEADER:
- case BLOCK_SETEXT_HEADER:
- cur->inline_content = parse_inlines(&cur->string_content, refmap);
- break;
-
- default:
- break;
+ case BLOCK_PARAGRAPH:
+ case BLOCK_ATX_HEADER:
+ case BLOCK_SETEXT_HEADER:
+ cur->inline_content = parse_inlines(&cur->string_content, refmap);
+ break;
+
+ default:
+ break;
}
node_block *child = cur->children;
@@ -310,14 +310,17 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr)
if (!isspace(peek_at(input, pos))) {
return 0;
}
- data = malloc(sizeof(struct ListData));
- data->marker_offset = 0; // will be adjusted later
- data->list_type = bullet;
- data->bullet_char = c;
- data->start = 1;
- data->delimiter = period;
- data->tight = false;
-
+ data = calloc(1, sizeof(*data));
+ if(data == NULL) {
+ return 0;
+ } else {
+ data->marker_offset = 0; // will be adjusted later
+ data->list_type = bullet;
+ data->bullet_char = c;
+ data->start = 1;
+ data->delimiter = period;
+ data->tight = false;
+ }
} else if (isdigit(c)) {
int start = 0;
@@ -332,13 +335,17 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr)
if (!isspace(peek_at(input, pos))) {
return 0;
}
- data = malloc(sizeof(struct ListData));
- data->marker_offset = 0; // will be adjusted later
- data->list_type = ordered;
- data->bullet_char = 0;
- data->start = start;
- data->delimiter = (c == '.' ? period : parens);
- data->tight = false;
+ data = calloc(1, sizeof(*data));
+ if(data == NULL) {
+ return 0;
+ } else {
+ data->marker_offset = 0; // will be adjusted later
+ data->list_type = ordered;
+ data->bullet_char = 0;
+ data->start = start;
+ data->delimiter = (c == '.' ? period : parens);
+ data->tight = false;
+ }
} else {
return 0;
}
@@ -355,9 +362,9 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr)
static int lists_match(struct ListData *list_data, struct ListData *item_data)
{
return (list_data->list_type == item_data->list_type &&
- list_data->delimiter == item_data->delimiter &&
- // list_data->marker_offset == item_data.marker_offset &&
- list_data->bullet_char == item_data->bullet_char);
+ list_data->delimiter == item_data->delimiter &&
+ // list_data->marker_offset == item_data.marker_offset &&
+ list_data->bullet_char == item_data->bullet_char);
}
static node_block *finalize_document(node_block *document, int linenum)
@@ -373,7 +380,7 @@ static node_block *finalize_document(node_block *document, int linenum)
return document;
}
-extern node_block *stmd_parse_file(FILE *f)
+extern node_block *cmark_parse_file(FILE *f)
{
strbuf line = GH_BUF_INIT;
unsigned char buffer[4096];
@@ -391,7 +398,7 @@ extern node_block *stmd_parse_file(FILE *f)
return finalize_document(document, linenum);
}
-extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len)
+extern node_block *cmark_parse_document(const unsigned char *buffer, size_t len)
{
strbuf line = GH_BUF_INIT;
int linenum = 1;
@@ -453,6 +460,10 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
int indent;
chunk input;
+ // Add a newline to the end if not present:
+ if (line->ptr[line->size - 1] != '\n') {
+ strbuf_putc(line, '\n');
+ }
input.data = line->ptr;
input.len = line->size;
@@ -486,7 +497,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
} else if (container->tag == BLOCK_LIST_ITEM) {
if (indent >= container->as.list.marker_offset +
- container->as.list.padding) {
+ container->as.list.padding) {
offset += container->as.list.marker_offset +
container->as.list.padding;
} else if (blank) {
@@ -506,7 +517,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
}
} else if (container->tag == BLOCK_ATX_HEADER ||
- container->tag == BLOCK_SETEXT_HEADER) {
+ container->tag == BLOCK_SETEXT_HEADER) {
// a header can never contain more than one line
all_matched = false;
@@ -550,7 +561,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
// unless last matched container is code node_block, try new container starts:
while (container->tag != BLOCK_FENCED_CODE && container->tag != BLOCK_INDENTED_CODE &&
- container->tag != BLOCK_HTML) {
+ container->tag != BLOCK_HTML) {
first_nonspace = offset;
while (peek_at(&input, first_nonspace) == ' ')
@@ -603,17 +614,17 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
// note, we don't adjust offset because the tag is part of the text
} else if (container->tag == BLOCK_PARAGRAPH &&
- (lev = scan_setext_header_line(&input, first_nonspace)) &&
- // check that there is only one line in the paragraph:
- strbuf_strrchr(&container->string_content, '\n',
- strbuf_len(&container->string_content) - 2) < 0) {
+ (lev = scan_setext_header_line(&input, first_nonspace)) &&
+ // check that there is only one line in the paragraph:
+ strbuf_strrchr(&container->string_content, '\n',
+ strbuf_len(&container->string_content) - 2) < 0) {
container->tag = BLOCK_SETEXT_HEADER;
container->as.header.level = lev;
offset = input.len - 1;
} else if (!(container->tag == BLOCK_PARAGRAPH && !all_matched) &&
- (matched = scan_hrule(&input, first_nonspace))) {
+ (matched = scan_hrule(&input, first_nonspace))) {
// it's only now that we know the line is not part of a setext header:
container = add_child(container, BLOCK_HRULE, line_number, first_nonspace + 1);
@@ -646,16 +657,16 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
data->marker_offset = indent;
if (container->tag != BLOCK_LIST ||
- !lists_match(&container->as.list, data)) {
+ !lists_match(&container->as.list, data)) {
container = add_child(container, BLOCK_LIST, line_number,
- first_nonspace + 1);
+ first_nonspace + 1);
memcpy(&container->as.list, data, sizeof(*data));
}
// add the list item
container = add_child(container, BLOCK_LIST_ITEM, line_number,
- first_nonspace + 1);
+ first_nonspace + 1);
/* TODO: static */
memcpy(&container->as.list, data, sizeof(*data));
free(data);
@@ -684,11 +695,11 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
// lists or breaking out of lists. we also don't set last_line_blank
// on an empty list item.
container->last_line_blank = (blank &&
- container->tag != BLOCK_BQUOTE &&
- container->tag != BLOCK_FENCED_CODE &&
- !(container->tag == BLOCK_LIST_ITEM &&
- container->children == NULL &&
- container->start_line == line_number));
+ container->tag != BLOCK_BQUOTE &&
+ container->tag != BLOCK_FENCED_CODE &&
+ !(container->tag == BLOCK_LIST_ITEM &&
+ container->children == NULL &&
+ container->start_line == line_number));
node_block *cont = container;
while (cont->parent) {
@@ -697,10 +708,10 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
}
if (cur != last_matched_container &&
- container == last_matched_container &&
- !blank &&
- cur->tag == BLOCK_PARAGRAPH &&
- strbuf_len(&cur->string_content) > 0) {
+ container == last_matched_container &&
+ !blank &&
+ cur->tag == BLOCK_PARAGRAPH &&
+ strbuf_len(&cur->string_content) > 0) {
add_line(cur, &input, offset);
@@ -721,7 +732,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
matched = 0;
if (indent <= 3 &&
- peek_at(&input, first_nonspace) == container->as.code.fence_char) {
+ peek_at(&input, first_nonspace) == container->as.code.fence_char) {
int fence_len = scan_close_code_fence(&input, first_nonspace);
if (fence_len > container->as.code.fence_length)
matched = 1;
@@ -767,4 +778,3 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr)
*curptr = container;
}
}
-
diff --git a/src/buffer.c b/src/buffer.c
index 7c2b86b..1cdcae8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -15,10 +15,14 @@
unsigned char strbuf__initbuf[1];
unsigned char strbuf__oom[1];
-#define ENSURE_SIZE(b, d) \
- if ((d) > buf->asize && strbuf_grow(b, (d)) < 0)\
+#define ENSURE_SIZE(b, d) \
+ if ((d) > buf->asize && strbuf_grow(b, (d)) < 0) \
return -1;
+#ifndef MIN
+#define MIN(x,y) ((x<y) ? x : y)
+#endif
+
void strbuf_init(strbuf *buf, int initial_size)
{
buf->asize = 0;
@@ -111,8 +115,8 @@ int strbuf_set(strbuf *buf, const unsigned char *data, int len)
int strbuf_sets(strbuf *buf, const char *string)
{
return strbuf_set(buf,
- (const unsigned char *)string,
- string ? strlen(string) : 0);
+ (const unsigned char *)string,
+ string ? strlen(string) : 0);
}
int strbuf_putc(strbuf *buf, int c)
@@ -155,7 +159,7 @@ int strbuf_vprintf(strbuf *buf, const char *format, va_list ap)
(char *)buf->ptr + buf->size,
buf->asize - buf->size,
format, args
- );
+ );
if (len < 0) {
free(buf->ptr);
@@ -351,4 +355,3 @@ extern void strbuf_unescape(strbuf *buf)
strbuf_truncate(buf, w);
}
-
diff --git a/src/chunk.h b/src/chunk.h
index f37a2f3..015bbf9 100644
--- a/src/chunk.h
+++ b/src/chunk.h
@@ -59,10 +59,11 @@ static inline unsigned char *chunk_to_cstr(chunk *c)
{
unsigned char *str;
- str = malloc(c->len + 1);
- memcpy(str, c->data, c->len);
- str[c->len] = 0;
-
+ str = calloc(c->len + 1, sizeof(*str));
+ if(str != NULL) {
+ memcpy(str, c->data, c->len);
+ str[c->len] = 0;
+ }
return str;
}
diff --git a/src/stmd.h b/src/cmark.h
index c6473a6..ff2f9a2 100644
--- a/src/stmd.h
+++ b/src/cmark.h
@@ -56,7 +56,7 @@ struct ListData {
struct FencedCodeData {
int fence_length;
int fence_offset;
- char fence_char;
+ unsigned char fence_char;
strbuf info;
};
@@ -104,12 +104,12 @@ struct node_block {
typedef struct node_block node_block;
-node_block *stmd_parse_document(const unsigned char *buffer, size_t len);
-node_block *stmd_parse_file(FILE *f);
+node_block *cmark_parse_document(const unsigned char *buffer, size_t len);
+node_block *cmark_parse_file(FILE *f);
-void stmd_free_nodes(node_block *e);
+void cmark_free_nodes(node_block *e);
-void stmd_debug_print(node_block *root);
-void stmd_render_html(strbuf *html, node_block *root);
+void cmark_debug_print(node_block *root);
+void cmark_render_html(strbuf *html, node_block *root);
#endif
diff --git a/src/html/html.c b/src/html/html.c
index ab6fc35..fde1cb4 100644
--- a/src/html/html.c
+++ b/src/html/html.c
@@ -4,7 +4,7 @@
#include <string.h>
#include <assert.h>
-#include "stmd.h"
+#include "cmark.h"
#include "debug.h"
#include "html/houdini.h"
@@ -222,7 +222,7 @@ static void blocks_to_html(strbuf *html, node_block *b, bool tight)
}
}
-void stmd_render_html(strbuf *html, node_block *root)
+void cmark_render_html(strbuf *html, node_block *root)
{
blocks_to_html(html, root, false);
}
diff --git a/src/inlines.c b/src/inlines.c
index 71d75e9..7a7f08a 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -4,17 +4,25 @@
#include <stdbool.h>
#include <ctype.h>
-#include "stmd.h"
+#include "cmark.h"
#include "html/houdini.h"
#include "utf8.h"
#include "scanners.h"
#include "inlines.h"
+typedef struct InlineStack {
+ struct InlineStack *previous;
+ node_inl *first_inline;
+ int delim_count;
+ unsigned char delim_char;
+} inline_stack;
+
typedef struct Subject {
chunk input;
int pos;
int label_nestlevel;
reference_map *refmap;
+ inline_stack *emphasis_openers;
} subject;
static node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap);
@@ -31,8 +39,10 @@ static unsigned char *bufdup(const unsigned char *buf)
if (buf) {
int len = strlen((char *)buf);
- new = malloc(len + 1);
- memcpy(new, buf, len + 1);
+ new = calloc(len + 1, sizeof(*new));
+ if(new != NULL) {
+ memcpy(new, buf, len + 1);
+ }
}
return new;
@@ -40,12 +50,14 @@ static unsigned char *bufdup(const unsigned char *buf)
static inline node_inl *make_link_(node_inl *label, unsigned char *url, unsigned char *title)
{
- node_inl* e = (node_inl*) malloc(sizeof(node_inl));
- e->tag = INL_LINK;
- e->content.linkable.label = label;
- e->content.linkable.url = url;
- e->content.linkable.title = title;
- e->next = NULL;
+ node_inl* e = calloc(1, sizeof(*e));
+ if(e != NULL) {
+ e->tag = INL_LINK;
+ e->content.linkable.label = label;
+ e->content.linkable.url = url;
+ e->content.linkable.title = title;
+ e->next = NULL;
+ }
return e;
}
@@ -67,29 +79,35 @@ inline static node_inl* make_link(node_inl* label, chunk url, chunk title)
inline static node_inl* make_inlines(int t, node_inl* contents)
{
- node_inl* e = (node_inl*) malloc(sizeof(node_inl));
- e->tag = t;
- e->content.inlines = contents;
- e->next = NULL;
+ node_inl * e = calloc(1, sizeof(*e));
+ if(e != NULL) {
+ e->tag = t;
+ e->content.inlines = contents;
+ e->next = NULL;
+ }
return e;
}
// Create an inline with a literal string value.
inline static node_inl* make_literal(int t, chunk s)
{
- node_inl* e = (node_inl*) malloc(sizeof(node_inl));
- e->tag = t;
- e->content.literal = s;
- e->next = NULL;
+ node_inl * e = calloc(1, sizeof(*e));
+ if(e != NULL) {
+ e->tag = t;
+ e->content.literal = s;
+ e->next = NULL;
+ }
return e;
}
// Create an inline with no value.
inline static node_inl* make_simple(int t)
{
- node_inl* e = (node_inl*) malloc(sizeof(node_inl));
- e->tag = t;
- e->next = NULL;
+ node_inl* e = calloc(1, sizeof(*e));
+ if(e != NULL) {
+ e->tag = t;
+ e->next = NULL;
+ }
return e;
}
@@ -108,26 +126,26 @@ extern void free_inlines(node_inl* e)
node_inl * next;
while (e != NULL) {
switch (e->tag){
- case INL_STRING:
- case INL_RAW_HTML:
- case INL_CODE:
- chunk_free(&e->content.literal);
- break;
- case INL_LINEBREAK:
- case INL_SOFTBREAK:
- break;
- case INL_LINK:
- case INL_IMAGE:
- free(e->content.linkable.url);
- free(e->content.linkable.title);
- free_inlines(e->content.linkable.label);
- break;
- case INL_EMPH:
- case INL_STRONG:
- free_inlines(e->content.inlines);
- break;
- default:
- break;
+ case INL_STRING:
+ case INL_RAW_HTML:
+ case INL_CODE:
+ chunk_free(&e->content.literal);
+ break;
+ case INL_LINEBREAK:
+ case INL_SOFTBREAK:
+ break;
+ case INL_LINK:
+ case INL_IMAGE:
+ free(e->content.linkable.url);
+ free(e->content.linkable.title);
+ free_inlines(e->content.linkable.label);
+ break;
+ case INL_EMPH:
+ case INL_STRONG:
+ free_inlines(e->content.inlines);
+ break;
+ default:
+ break;
}
next = e->next;
free(e);
@@ -158,6 +176,7 @@ static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap)
e->pos = 0;
e->label_nestlevel = 0;
e->refmap = refmap;
+ e->emphasis_openers = NULL;
chunk_rtrim(&e->input);
}
@@ -170,6 +189,7 @@ static void subject_from_chunk(subject *e, chunk *chunk, reference_map *refmap)
e->pos = 0;
e->label_nestlevel = 0;
e->refmap = refmap;
+ e->emphasis_openers = NULL;
chunk_rtrim(&e->input);
}
@@ -221,7 +241,7 @@ inline static chunk take_while(subject* subj, int (*f)(int))
static int scan_to_closing_backticks(subject* subj, int openticklength)
{
// read non backticks
- char c;
+ unsigned char c;
while ((c = peek_char(subj)) && c != '`') {
advance(subj);
}
@@ -262,12 +282,11 @@ static node_inl* handle_backticks(subject *subj)
}
// Scan ***, **, or * and return number scanned, or 0.
-// Don't advance position.
-static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close)
+// Advances position.
+static int scan_delims(subject* subj, unsigned char c, bool * can_open, bool * can_close)
{
int numdelims = 0;
- char char_before, char_after;
- int startpos = subj->pos;
+ unsigned char char_before, char_after;
char_before = subj->pos == 0 ? '\n' : peek_at(subj, subj->pos - 1);
while (peek_char(subj) == c) {
@@ -281,135 +300,109 @@ static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close)
*can_open = *can_open && !isalnum(char_before);
*can_close = *can_close && !isalnum(char_after);
}
- subj->pos = startpos;
return numdelims;
}
+static void free_openers(subject* subj, inline_stack* istack)
+{
+ inline_stack * tempstack;
+ while (subj->emphasis_openers != istack) {
+ tempstack = subj->emphasis_openers;
+ subj->emphasis_openers = subj->emphasis_openers->previous;
+ free(tempstack);
+ }
+}
+
// Parse strong/emph or a fallback.
// Assumes the subject has '_' or '*' at the current position.
-static node_inl* handle_strong_emph(subject* subj, char c)
+static node_inl* handle_strong_emph(subject* subj, unsigned char c, node_inl **last)
{
bool can_open, can_close;
- node_inl * result = NULL;
- node_inl ** last = malloc(sizeof(node_inl *));
- node_inl * new;
- node_inl * il;
- node_inl * first_head = NULL;
- node_inl * first_close = NULL;
- int first_close_delims = 0;
int numdelims;
-
- *last = NULL;
+ int useDelims;
+ inline_stack * istack;
+ node_inl * inl;
+ node_inl * emph;
+ node_inl * inl_text;
numdelims = scan_delims(subj, c, &can_open, &can_close);
- subj->pos += numdelims;
-
- new = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims));
- *last = new;
- first_head = new;
- result = new;
-
- if (!can_open || numdelims == 0) {
- goto done;
- }
-
- switch (numdelims) {
- case 1:
- while (true) {
- numdelims = scan_delims(subj, c, &can_open, &can_close);
- if (numdelims >= 1 && can_close) {
- subj->pos += 1;
- first_head->tag = INL_EMPH;
- chunk_free(&first_head->content.literal);
- first_head->content.inlines = first_head->next;
- first_head->next = NULL;
- goto done;
- } else {
- if (!parse_inline(subj, last)) {
- goto done;
- }
- }
- }
- break;
- case 2:
- while (true) {
- numdelims = scan_delims(subj, c, &can_open, &can_close);
- if (numdelims >= 2 && can_close) {
- subj->pos += 2;
- first_head->tag = INL_STRONG;
- chunk_free(&first_head->content.literal);
- first_head->content.inlines = first_head->next;
- first_head->next = NULL;
- goto done;
- } else {
- if (!parse_inline(subj, last)) {
- goto done;
- }
- }
- }
- break;
- case 3:
- while (true) {
- numdelims = scan_delims(subj, c, &can_open, &can_close);
- if (can_close && numdelims >= 1 && numdelims <= 3 &&
- numdelims != first_close_delims) {
- new = make_str(chunk_dup(&subj->input, subj->pos, numdelims));
- append_inlines(*last, new);
- *last = new;
- if (first_close_delims == 1 && numdelims > 2) {
- numdelims = 2;
- } else if (first_close_delims == 2) {
- numdelims = 1;
- } else if (numdelims == 3) {
- // If we opened with ***, we interpret it as ** followed by *
- // giving us <strong><em>
- numdelims = 1;
- }
- subj->pos += numdelims;
- if (first_close) {
- first_head->tag = first_close_delims == 1 ? INL_STRONG : INL_EMPH;
- chunk_free(&first_head->content.literal);
- first_head->content.inlines =
- make_inlines(first_close_delims == 1 ? INL_EMPH : INL_STRONG,
- first_head->next);
-
- il = first_head->next;
- while (il->next && il->next != first_close) {
- il = il->next;
- }
- il->next = NULL;
-
- first_head->content.inlines->next = first_close->next;
-
- il = first_head->content.inlines;
- while (il->next && il->next != *last) {
- il = il->next;
- }
- il->next = NULL;
- free_inlines(*last);
-
- first_close->next = NULL;
- free_inlines(first_close);
- first_head->next = NULL;
- goto done;
- } else {
- first_close = *last;
- first_close_delims = numdelims;
- }
- } else {
- if (!parse_inline(subj, last)) {
- goto done;
- }
- }
- }
- break;
- default:
- goto done;
+
+ if (can_close)
+ {
+ // walk the stack and find a matching opener, if there is one
+ istack = subj->emphasis_openers;
+ while (true)
+ {
+ if (istack == NULL)
+ goto cannotClose;
+
+ if (istack->delim_char == c)
+ break;
+
+ istack = istack->previous;
+ }
+
+ // calculate the actual number of delimeters used from this closer
+ useDelims = istack->delim_count;
+ if (useDelims == 3) useDelims = numdelims == 3 ? 1 : numdelims;
+ else if (useDelims > numdelims) useDelims = 1;
+
+ if (istack->delim_count == useDelims)
+ {
+ // the opener is completely used up - remove the stack entry and reuse the inline element
+ inl = istack->first_inline;
+ inl->tag = useDelims == 1 ? INL_EMPH : INL_STRONG;
+ chunk_free(&inl->content.literal);
+ inl->content.inlines = inl->next;
+ inl->next = NULL;
+
+ // remove this opener and all later ones from stack:
+ free_openers(subj, istack->previous);
+ *last = inl;
+ }
+ else
+ {
+ // the opener will only partially be used - stack entry remains (truncated) and a new inline is added.
+ inl = istack->first_inline;
+ istack->delim_count -= useDelims;
+ inl->content.literal.len = istack->delim_count;
+
+ emph = useDelims == 1 ? make_emph(inl->next) : make_strong(inl->next);
+ inl->next = emph;
+
+ // remove all later openers from stack:
+ free_openers(subj, istack);
+
+ *last = emph;
+ }
+
+ // if the closer was not fully used, move back a char or two and try again.
+ if (useDelims < numdelims)
+ {
+ subj->pos = subj->pos - numdelims + useDelims;
+ return handle_strong_emph(subj, c, last);
+ }
+
+ return NULL; // make_str(chunk_literal(""));
+ }
+
+cannotClose:
+ inl_text = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims));
+
+ if (can_open)
+ {
+ istack = (inline_stack*)malloc(sizeof(inline_stack));
+ if (istack == NULL) {
+ return NULL;
+ }
+ istack->delim_count = numdelims;
+ istack->delim_char = c;
+ istack->first_inline = inl_text;
+ istack->previous = subj->emphasis_openers;
+ subj->emphasis_openers = istack;
}
-done:
- free(last);
- return result;
+ return inl_text;
}
// Parse backslash-escape or just a backslash, returning an inline.
@@ -438,9 +431,9 @@ static node_inl* handle_entity(subject* subj)
advance(subj);
len = houdini_unescape_ent(&ent,
- subj->input.data + subj->pos,
- subj->input.len - subj->pos
- );
+ subj->input.data + subj->pos,
+ subj->input.len - subj->pos
+ );
if (len == 0)
return make_str(chunk_literal("&"));
@@ -513,8 +506,8 @@ unsigned char *clean_title(chunk *title)
// remove surrounding quotes if any:
if ((first == '\'' && last == '\'') ||
- (first == '(' && last == ')') ||
- (first == '"' && last == '"')) {
+ (first == '(' && last == ')') ||
+ (first == '"' && last == '"')) {
houdini_unescape_html_f(&buf, title->data + 1, title->len - 2);
} else {
houdini_unescape_html_f(&buf, title->data, title->len);
@@ -542,7 +535,7 @@ static node_inl* handle_pointy_brace(subject* subj)
return make_autolink(
make_str_with_entities(&contents),
contents, 0
- );
+ );
}
// next try to match an email autolink
@@ -552,9 +545,9 @@ static node_inl* handle_pointy_brace(subject* subj)
subj->pos += matchlen;
return make_autolink(
- make_str_with_entities(&contents),
- contents, 1
- );
+ make_str_with_entities(&contents),
+ contents, 1
+ );
}
// finally, try to match an html tag
@@ -595,33 +588,33 @@ static int link_label(subject* subj, chunk *raw_label)
}
advance(subj); // advance past [
- char c;
+ unsigned char c;
while ((c = peek_char(subj)) && (c != ']' || nestlevel > 0)) {
switch (c) {
- case '`':
- tmp = handle_backticks(subj);
- free_inlines(tmp);
- break;
- case '<':
- tmp = handle_pointy_brace(subj);
- free_inlines(tmp);
- break;
- case '[': // nested []
- nestlevel++;
- advance(subj);
- break;
- case ']': // nested []
- nestlevel--;
- advance(subj);
- break;
- case '\\':
- advance(subj);
- if (ispunct(peek_char(subj))) {
- advance(subj);
- }
- break;
- default:
+ case '`':
+ tmp = handle_backticks(subj);
+ free_inlines(tmp);
+ break;
+ case '<':
+ tmp = handle_pointy_brace(subj);
+ free_inlines(tmp);
+ break;
+ case '[': // nested []
+ nestlevel++;
+ advance(subj);
+ break;
+ case ']': // nested []
+ nestlevel--;
+ advance(subj);
+ break;
+ case '\\':
+ advance(subj);
+ if (ispunct(peek_char(subj))) {
advance(subj);
+ }
+ break;
+ default:
+ advance(subj);
}
}
if (c == ']') {
@@ -657,8 +650,8 @@ static node_inl* handle_left_bracket(subject* subj)
if (found_label) {
if (peek_char(subj) == '(' &&
- ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
- ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {
+ ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
+ ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {
// try to parse an explicit link:
starturl = subj->pos + 1 + sps; // after (
@@ -684,8 +677,8 @@ static node_inl* handle_left_bracket(subject* subj)
subj->pos = endlabel;
lab = parse_chunk_inlines(&rawlabel, subj->refmap);
result = append_inlines(make_str(chunk_literal("[")),
- append_inlines(lab,
- make_str(chunk_literal("]"))));
+ append_inlines(lab,
+ make_str(chunk_literal("]"))));
return result;
}
} else {
@@ -714,7 +707,7 @@ static node_inl* handle_left_bracket(subject* subj)
subj->pos = endlabel;
lab = parse_chunk_inlines(&rawlabel, subj->refmap);
result = append_inlines(make_str(chunk_literal("[")),
- append_inlines(lab, make_str(chunk_literal("]"))));
+ append_inlines(lab, make_str(chunk_literal("]"))));
}
return result;
}
@@ -736,8 +729,8 @@ static node_inl* handle_newline(subject *subj)
advance(subj);
}
if (nlpos > 1 &&
- peek_at(subj, nlpos - 1) == ' ' &&
- peek_at(subj, nlpos - 2) == ' ') {
+ peek_at(subj, nlpos - 1) == ' ' &&
+ peek_at(subj, nlpos - 2) == ' ') {
return make_linebreak();
} else {
return make_softbreak();
@@ -754,9 +747,22 @@ extern node_inl* parse_inlines_while(subject* subj, int (*f)(subject*))
{
node_inl* result = NULL;
node_inl** last = &result;
+ node_inl* first = NULL;
while ((*f)(subj) && parse_inline(subj, last)) {
+ if (!first) {
+ first = *last;
+ }
+ }
+
+ inline_stack* istack = subj->emphasis_openers;
+ inline_stack* temp;
+ while (istack != NULL) {
+ temp = istack->previous;
+ free(istack);
+ istack = temp;
}
- return result;
+
+ return first;
}
node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap)
@@ -812,69 +818,62 @@ static int parse_inline(subject* subj, node_inl ** last)
return 0;
}
switch(c){
- case '\n':
- new = handle_newline(subj);
- break;
- case '`':
- new = handle_backticks(subj);
- break;
- case '\\':
- new = handle_backslash(subj);
- break;
- case '&':
- new = handle_entity(subj);
- break;
- case '<':
- new = handle_pointy_brace(subj);
- break;
- case '_':
- if (subj->pos > 0) {
- unsigned char prev = peek_at(subj, subj->pos - 1);
- if (isalnum(prev) || prev == '_') {
- new = make_str(chunk_literal("_"));
- advance(subj);
- break;
- }
- }
-
- new = handle_strong_emph(subj, '_');
- break;
- case '*':
- new = handle_strong_emph(subj, '*');
- break;
- case '[':
+ case '\n':
+ new = handle_newline(subj);
+ break;
+ case '`':
+ new = handle_backticks(subj);
+ break;
+ case '\\':
+ new = handle_backslash(subj);
+ break;
+ case '&':
+ new = handle_entity(subj);
+ break;
+ case '<':
+ new = handle_pointy_brace(subj);
+ break;
+ case '_':
+ new = handle_strong_emph(subj, '_', last);
+ break;
+ case '*':
+ new = handle_strong_emph(subj, '*', last);
+ break;
+ case '[':
+ new = handle_left_bracket(subj);
+ break;
+ case '!':
+ advance(subj);
+ if (peek_char(subj) == '[') {
new = handle_left_bracket(subj);
- break;
- case '!':
- advance(subj);
- if (peek_char(subj) == '[') {
- new = handle_left_bracket(subj);
- if (new != NULL && new->tag == INL_LINK) {
- new->tag = INL_IMAGE;
- } else {
- new = append_inlines(make_str(chunk_literal("!")), new);
- }
+ if (new != NULL && new->tag == INL_LINK) {
+ new->tag = INL_IMAGE;
} else {
- new = make_str(chunk_literal("!"));
- }
- break;
- default:
- endpos = subject_find_special_char(subj);
- contents = chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
- subj->pos = endpos;
-
- // if we're at a newline, strip trailing spaces.
- if (peek_char(subj) == '\n') {
- chunk_rtrim(&contents);
+ new = append_inlines(make_str(chunk_literal("!")), new);
}
+ } else {
+ new = make_str(chunk_literal("!"));
+ }
+ break;
+ default:
+ endpos = subject_find_special_char(subj);
+ contents = chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
+ subj->pos = endpos;
+
+ // if we're at a newline, strip trailing spaces.
+ if (peek_char(subj) == '\n') {
+ chunk_rtrim(&contents);
+ }
- new = make_str(contents);
+ new = make_str(contents);
}
if (*last == NULL) {
*last = new;
- } else {
+ } else if (new) {
append_inlines(*last, new);
+ *last = new;
}
+
return 1;
}
@@ -890,8 +889,8 @@ void spnl(subject* subj)
{
bool seen_newline = false;
while (peek_char(subj) == ' ' ||
- (!seen_newline &&
- (seen_newline = peek_char(subj) == '\n'))) {
+ (!seen_newline &&
+ (seen_newline = peek_char(subj) == '\n'))) {
advance(subj);
}
}
@@ -958,4 +957,3 @@ int parse_reference_inline(strbuf *input, reference_map *refmap)
reference_create(refmap, &lab, &url, &title);
return subj.pos;
}
-
diff --git a/src/main.c b/src/main.c
index 76a0e12..b2404f6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,12 +1,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include "stmd.h"
+#include "cmark.h"
#include "debug.h"
void print_usage()
{
- printf("Usage: stmd [FILE*]\n");
+ printf("Usage: cmark [FILE*]\n");
printf("Options: --help, -h Print usage information\n");
printf(" --ast Print AST instead of HTML\n");
printf(" --version Print version\n");
@@ -17,9 +17,9 @@ static void print_document(node_block *document, bool ast)
strbuf html = GH_BUF_INIT;
if (ast) {
- stmd_debug_print(document);
+ cmark_debug_print(document);
} else {
- stmd_render_html(&html, document);
+ cmark_render_html(&html, document);
printf("%s", html.ptr);
strbuf_free(&html);
}
@@ -34,11 +34,11 @@ int main(int argc, char *argv[])
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--version") == 0) {
- printf("stmd %s", VERSION);
+ printf("cmark %s", VERSION);
printf(" - CommonMark converter (c) 2014 John MacFarlane\n");
exit(0);
} else if ((strcmp(argv[i], "--help") == 0) ||
- (strcmp(argv[i], "-h") == 0)) {
+ (strcmp(argv[i], "-h") == 0)) {
print_usage();
exit(0);
} else if (strcmp(argv[i], "--ast") == 0) {
@@ -52,26 +52,25 @@ int main(int argc, char *argv[])
}
if (numfps == 0) {
- document = stmd_parse_file(stdin);
+ document = cmark_parse_file(stdin);
print_document(document, ast);
- stmd_free_nodes(document);
+ cmark_free_nodes(document);
} else {
for (i = 0; i < numfps; i++) {
FILE *fp = fopen(argv[files[i]], "r");
if (fp == NULL) {
fprintf(stderr, "Error opening file %s: %s\n",
- argv[files[i]], strerror(errno));
+ argv[files[i]], strerror(errno));
exit(1);
}
- document = stmd_parse_file(fp);
+ document = cmark_parse_file(fp);
print_document(document, ast);
- stmd_free_nodes(document);
+ cmark_free_nodes(document);
fclose(fp);
}
}
return 0;
}
-
diff --git a/src/print.c b/src/print.c
index 83f8daa..be3bced 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,7 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include "stmd.h"
+#include "cmark.h"
#include "debug.h"
static void print_str(const unsigned char *s, int len)
@@ -16,17 +16,17 @@ static void print_str(const unsigned char *s, int len)
unsigned char c = s[i];
switch (c) {
- case '\n':
- printf("\\n");
- break;
- case '"':
- printf("\\\"");
- break;
- case '\\':
- printf("\\\\");
- break;
- default:
- putchar((int)c);
+ case '\n':
+ printf("\\n");
+ break;
+ case '"':
+ printf("\\\"");
+ break;
+ case '\\':
+ printf("\\\\");
+ break;
+ default:
+ putchar((int)c);
}
}
putchar('"');
@@ -116,13 +116,13 @@ static void print_blocks(node_block* b, int indent)
data = &(b->as.list);
if (data->list_type == ordered) {
printf("list (type=ordered tight=%s start=%d delim=%s)\n",
- (data->tight ? "true" : "false"),
- data->start,
- (data->delimiter == parens ? "parens" : "period"));
+ (data->tight ? "true" : "false"),
+ data->start,
+ (data->delimiter == parens ? "parens" : "period"));
} else {
printf("list (type=bullet tight=%s bullet_char=%c)\n",
- (data->tight ? "true" : "false"),
- data->bullet_char);
+ (data->tight ? "true" : "false"),
+ data->bullet_char);
}
print_blocks(b->children, indent + 2);
break;
@@ -148,7 +148,7 @@ static void print_blocks(node_block* b, int indent)
break;
case BLOCK_FENCED_CODE:
printf("fenced_code length=%d info=",
- b->as.code.fence_length);
+ b->as.code.fence_length);
print_str(b->as.code.info.ptr, -1);
putchar(' ');
print_str(b->string_content.ptr, -1);
@@ -170,7 +170,7 @@ static void print_blocks(node_block* b, int indent)
}
}
-void stmd_debug_print(node_block *root)
+void cmark_debug_print(node_block *root)
{
print_blocks(root, 0);
}
diff --git a/src/references.c b/src/references.c
index 3e54b48..04b9025 100644
--- a/src/references.c
+++ b/src/references.c
@@ -1,4 +1,4 @@
-#include "stmd.h"
+#include "cmark.h"
#include "utf8.h"
#include "references.h"
#include "inlines.h"
@@ -16,10 +16,12 @@ refhash(const unsigned char *link_ref)
static void reference_free(reference *ref)
{
- free(ref->label);
- free(ref->url);
- free(ref->title);
- free(ref);
+ if(ref != NULL) {
+ free(ref->label);
+ free(ref->url);
+ free(ref->title);
+ free(ref);
+ }
}
// normalize reference: collapse internal whitespace to single space,
@@ -31,6 +33,9 @@ static unsigned char *normalize_reference(chunk *ref)
strbuf normalized = GH_BUF_INIT;
unsigned char *result;
+ if(ref == NULL)
+ return NULL;
+
if (ref->len == 0)
return NULL;
@@ -55,7 +60,7 @@ static void add_reference(reference_map *map, reference* ref)
while (t) {
if (t->hash == ref->hash &&
- !strcmp((char *)t->label, (char *)ref->label)) {
+ !strcmp((char *)t->label, (char *)ref->label)) {
reference_free(ref);
return;
}
@@ -75,14 +80,16 @@ extern void reference_create(reference_map *map, chunk *label, chunk *url, chunk
if (reflabel == NULL)
return;
- ref = malloc(sizeof(reference));
- ref->label = reflabel;
- ref->hash = refhash(ref->label);
- ref->url = clean_url(url);
- ref->title = clean_title(title);
- ref->next = NULL;
+ ref = calloc(1, sizeof(*ref));
+ if(ref != NULL) {
+ ref->label = reflabel;
+ ref->hash = refhash(ref->label);
+ ref->url = clean_url(url);
+ ref->title = clean_title(title);
+ ref->next = NULL;
- add_reference(map, ref);
+ add_reference(map, ref);
+ }
}
// Returns reference if refmap contains a reference with matching
@@ -92,10 +99,10 @@ reference* reference_lookup(reference_map *map, chunk *label)
reference *ref = NULL;
unsigned char *norm;
unsigned int hash;
-
+
if (map == NULL)
return NULL;
-
+
norm = normalize_reference(label);
if (norm == NULL)
return NULL;
@@ -105,7 +112,7 @@ reference* reference_lookup(reference_map *map, chunk *label)
while (ref) {
if (ref->hash == hash &&
- !strcmp((char *)ref->label, (char *)norm))
+ !strcmp((char *)ref->label, (char *)norm))
break;
ref = ref->next;
}
@@ -118,6 +125,9 @@ void reference_map_free(reference_map *map)
{
unsigned int i;
+ if(map == NULL)
+ return;
+
for (i = 0; i < REFMAP_SIZE; ++i) {
reference *ref = map->table[i];
reference *next;
@@ -134,8 +144,5 @@ void reference_map_free(reference_map *map)
reference_map *reference_map_new(void)
{
- reference_map *map = malloc(sizeof(reference_map));
- memset(map, 0x0, sizeof(reference_map));
- return map;
+ return calloc(1, sizeof(reference_map));
}
-
diff --git a/src/scanners.h b/src/scanners.h
index 785d424..86dbcf5 100644
--- a/src/scanners.h
+++ b/src/scanners.h
@@ -1,4 +1,4 @@
-#include "stmd.h"
+#include "cmark.h"
extern int _scan_autolink_uri(const unsigned char *p);
extern int _scan_autolink_email(const unsigned char *p);
diff --git a/src/scanners.re b/src/scanners.re
index 28aba9d..5ec1bf3 100644
--- a/src/scanners.re
+++ b/src/scanners.re
@@ -36,7 +36,7 @@
htmlcomment = "!--" ([^-\x00]+ | [-][^-\x00]+)* "-->";
- processinginstruction = "?" ([^?>\x00]+ | [?][^>\x00])* "?>";
+ processinginstruction = "?" ([^?>\x00]+ | [?][^>\x00] | [>])* "?>";
declaration = "!" [A-Z]+ spacechar+ [^>\x00]* ">";
diff --git a/src/utf8.c b/src/utf8.c
index 6b34831..8a786b7 100644
--- a/src/utf8.c
+++ b/src/utf8.c
@@ -103,24 +103,24 @@ int utf8proc_iterate(const uint8_t *str, int str_len, int32_t *dst)
return -1;
switch (length) {
- case 1:
- uc = str[0];
- break;
- case 2:
- uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
- if (uc < 0x80) uc = -1;
- break;
- case 3:
- uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
- + (str[2] & 0x3F);
- if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
- (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
- break;
- case 4:
- uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
- + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
- if (uc < 0x10000 || uc >= 0x110000) uc = -1;
- break;
+ case 1:
+ uc = str[0];
+ break;
+ case 2:
+ uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
+ if (uc < 0x80) uc = -1;
+ break;
+ case 3:
+ uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
+ + (str[2] & 0x3F);
+ if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
+ (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
+ break;
+ case 4:
+ uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
+ + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
+ if (uc < 0x10000 || uc >= 0x110000) uc = -1;
+ break;
}
if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
@@ -173,7 +173,7 @@ void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len)
{
int32_t c;
-#define bufpush(x) \
+#define bufpush(x) \
utf8proc_encode_char(x, dest)
while (len > 0) {
@@ -190,4 +190,3 @@ void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len)
len -= char_len;
}
}
-
diff --git a/src/utf8.h b/src/utf8.h
index c971250..496eae9 100644
--- a/src/utf8.h
+++ b/src/utf8.h
@@ -1,5 +1,5 @@
-#ifndef _H_STMD_UTF8_
-#define _H_STMD_UTF8_
+#ifndef _H_cmark_UTF8_
+#define _H_cmark_UTF8_
#include <stdint.h>
#include "buffer.h"
diff --git a/template.html b/template.html
index fb7fbe4..0eaf299 100644
--- a/template.html
+++ b/template.html
@@ -36,7 +36,8 @@ pre {
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
-code { font-family: monospace; }
+code { font-family: monospace; background-color: #D3E1E4; }
+pre > code { background-color: transparent; }
div.example > pre { float:left; width: 48%; }
div.example > pre.markdown { clear:left; }
pre.tree { font-weight: bold; color: #777; }