Showing preview only (631K chars total). Download the full file or copy to clipboard to get everything.
Repository: evilstreak/markdown-js
Branch: master
Commit: 14344a8f0eb1
Files: 786
Total size: 466.7 KB
Directory structure:
gitextract_2zijr1dr/
├── .gitignore
├── .travis.yml
├── Changes.md
├── Gruntfile.js
├── README.md
├── bin/
│ └── md2html.js
├── bower.json
├── inc/
│ ├── footer-node.js
│ ├── footer-web.js
│ ├── header.js
│ └── tasks/
│ └── build_markdown.js
├── lib/
│ └── index.js
├── package.json
├── seed.yml
├── src/
│ ├── core.js
│ ├── dialects/
│ │ ├── dialect_helpers.js
│ │ ├── gruber.js
│ │ └── maruku.js
│ ├── markdown.js
│ ├── markdown_helpers.js
│ ├── parser.js
│ └── render_tree.js
└── test/
├── features/
│ ├── blockquotes/
│ │ ├── contains_code.json
│ │ ├── contains_code.text
│ │ ├── lazy_wrapping.json
│ │ ├── lazy_wrapping.text
│ │ ├── leading_paras.json
│ │ ├── leading_paras.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── simple.json
│ │ ├── simple.text
│ │ ├── spaceless.json
│ │ ├── spaceless.text
│ │ ├── spaces_before.json
│ │ ├── spaces_before.text
│ │ ├── threequotes.json
│ │ └── threequotes.text
│ ├── code/
│ │ ├── blank_lines.json
│ │ ├── blank_lines.text
│ │ ├── block.json
│ │ ├── block.text
│ │ ├── embedded_backtick.json
│ │ ├── embedded_backtick.text
│ │ ├── horizontal_rules.json
│ │ ├── horizontal_rules.text
│ │ ├── in_lists.json
│ │ ├── in_lists.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inline_multiline.json
│ │ ├── inline_multiline.text
│ │ ├── trailing_para.json
│ │ ├── trailing_para.text
│ │ ├── with_greater_than.json
│ │ └── with_greater_than.text
│ ├── definition_lists/
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── long.json
│ │ ├── long.text
│ │ ├── multiple_definitions.json
│ │ ├── multiple_definitions.text
│ │ ├── multiple_terms.json
│ │ ├── multiple_terms.text
│ │ ├── tight.json
│ │ └── tight.text
│ ├── emphasis/
│ │ ├── multiple_lines.json
│ │ ├── multiple_lines.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── simple.json
│ │ └── simple.text
│ ├── headers/
│ │ ├── atx.json
│ │ ├── atx.text
│ │ ├── atx_closing_hashes.json
│ │ ├── atx_closing_hashes.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── setext.json
│ │ ├── setext.text
│ │ ├── trailing_paras.json
│ │ └── trailing_paras.text
│ ├── horizontal_rules/
│ │ ├── abutting_blocks.json
│ │ ├── abutting_blocks.text
│ │ ├── dashes.json
│ │ ├── dashes.text
│ │ ├── front_matter.json
│ │ ├── front_matter.text
│ │ ├── leading_spaces.json
│ │ ├── leading_spaces.text
│ │ ├── long.json
│ │ ├── long.text
│ │ ├── long_loose.json
│ │ ├── long_loose.text
│ │ ├── loose_dashes.json
│ │ ├── loose_dashes.text
│ │ ├── loose_stars.json
│ │ ├── loose_stars.text
│ │ ├── loose_underscores.json
│ │ ├── loose_underscores.text
│ │ ├── stars.json
│ │ ├── stars.text
│ │ ├── underscores.json
│ │ └── underscores.text
│ ├── images/
│ │ ├── basic.json
│ │ ├── basic.text
│ │ ├── crotcheted_url.json
│ │ ├── crotcheted_url.text
│ │ ├── crotcheted_url_with_title.json
│ │ ├── crotcheted_url_with_title.text
│ │ ├── empty.json
│ │ ├── empty.text
│ │ ├── incomplete_image.json
│ │ ├── incomplete_image.text
│ │ ├── inside_link.json
│ │ ├── inside_link.text
│ │ ├── ref.json
│ │ ├── ref.text
│ │ ├── spaces_in_href.json
│ │ ├── spaces_in_href.text
│ │ ├── spaces_round_title.json
│ │ ├── spaces_round_title.text
│ │ ├── title.json
│ │ └── title.text
│ ├── linebreaks/
│ │ ├── simple.json
│ │ └── simple.text
│ ├── links/
│ │ ├── apostrophe.json
│ │ ├── apostrophe.text
│ │ ├── autolink_email.json
│ │ ├── autolink_email.text
│ │ ├── autolink_in_code.json
│ │ ├── autolink_in_code.text
│ │ ├── autolink_url.json
│ │ ├── autolink_url.text
│ │ ├── broken_brackets.json
│ │ ├── broken_brackets.text
│ │ ├── broken_link.json
│ │ ├── broken_link.text
│ │ ├── case_insensitive.json
│ │ ├── case_insensitive.text
│ │ ├── escaped_broken_link.json
│ │ ├── escaped_broken_link.text
│ │ ├── implicit.json
│ │ ├── implicit.text
│ │ ├── in_blockquotes.json
│ │ ├── in_blockquotes.text
│ │ ├── in_brackets.json
│ │ ├── in_brackets.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inline_with_newline.json
│ │ ├── inline_with_newline.text
│ │ ├── inline_with_title.json
│ │ ├── inline_with_title.text
│ │ ├── missing_references.json
│ │ ├── missing_references.text
│ │ ├── no_closing.json
│ │ ├── no_closing.text
│ │ ├── parens_escaped_inline.json
│ │ ├── parens_escaped_inline.text
│ │ ├── parens_inline.json
│ │ ├── parens_inline.text
│ │ ├── parens_reference.json
│ │ ├── parens_reference.text
│ │ ├── ref_reuse.json
│ │ ├── ref_reuse.text
│ │ ├── ref_with_image_ref.json
│ │ ├── ref_with_image_ref.text
│ │ ├── reference.json
│ │ ├── reference.text
│ │ ├── reference_missing.json
│ │ ├── reference_missing.text
│ │ ├── reference_with_newline.json
│ │ ├── reference_with_newline.text
│ │ ├── reference_with_newline_and_space.json
│ │ ├── reference_with_newline_and_space.text
│ │ ├── reference_with_quote.json
│ │ ├── reference_with_quote.text
│ │ ├── reference_with_space.json
│ │ ├── reference_with_space.text
│ │ ├── spaces_in_url.json
│ │ └── spaces_in_url.text
│ ├── lists/
│ │ ├── bullet_types.json
│ │ ├── bullet_types.text
│ │ ├── hr_abutting.json
│ │ ├── hr_abutting.text
│ │ ├── hr_inside.json
│ │ ├── hr_inside.text
│ │ ├── lazy_wrapping.json
│ │ ├── lazy_wrapping.text
│ │ ├── leading_whitespace.json
│ │ ├── leading_whitespace.text
│ │ ├── loose.json
│ │ ├── loose.text
│ │ ├── loose_with_inline.json
│ │ ├── loose_with_inline.text
│ │ ├── multiline_inline.json
│ │ ├── multiline_inline.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── nested_para.json
│ │ ├── nested_para.text
│ │ ├── numeric.json
│ │ ├── numeric.text
│ │ ├── quote_inside.json
│ │ ├── quote_inside.text
│ │ ├── references.json
│ │ ├── references.text
│ │ ├── tight.json
│ │ └── tight.text
│ ├── meta/
│ │ ├── attribute.json
│ │ ├── attribute.text
│ │ ├── class.json
│ │ ├── class.text
│ │ ├── code.json
│ │ ├── code.text
│ │ ├── document.json
│ │ ├── document.text
│ │ ├── id.json
│ │ ├── id.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inner_whitespace.json
│ │ ├── inner_whitespace.text
│ │ ├── leading_whitespace.json
│ │ ├── leading_whitespace.text
│ │ ├── list.json
│ │ ├── list.text
│ │ ├── list.todo
│ │ ├── multiple_classes.json
│ │ ├── multiple_classes.text
│ │ ├── quoted.json
│ │ └── quoted.text
│ └── tables/
│ ├── align.json
│ ├── align.text
│ ├── compact.json
│ ├── compact.text
│ ├── inline_formatting.json
│ ├── inline_formatting.text
│ ├── pipe_escape.json
│ ├── pipe_escape.text
│ ├── simple_leading.json
│ ├── simple_leading.text
│ ├── simple_no_leading.json
│ ├── simple_no_leading.text
│ ├── spaces_tolerance.json
│ └── spaces_tolerance.text
├── features.t.js
├── fixtures/
│ ├── Markdown-from-MDTest1.1.mdtest/
│ │ ├── Amps_and_angle_encoding.json
│ │ ├── Amps_and_angle_encoding.text
│ │ ├── Amps_and_angle_encoding.xhtml
│ │ ├── Auto_links.json
│ │ ├── Auto_links.text
│ │ ├── Auto_links.xhtml
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Backslash_escapes.xhtml
│ │ ├── Blockquotes_with_code_blocks.json
│ │ ├── Blockquotes_with_code_blocks.text
│ │ ├── Blockquotes_with_code_blocks.xhtml
│ │ ├── Code_Blocks.json
│ │ ├── Code_Blocks.text
│ │ ├── Code_Blocks.xhtml
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_Spans.xhtml
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.json
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.text
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.xhtml
│ │ ├── Horizontal_rules.json
│ │ ├── Horizontal_rules.text
│ │ ├── Horizontal_rules.xhtml
│ │ ├── Images.json
│ │ ├── Images.text
│ │ ├── Images.xhtml
│ │ ├── Inline_HTML_(Advanced).json
│ │ ├── Inline_HTML_(Advanced).text
│ │ ├── Inline_HTML_(Advanced).xhtml
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Links_inline_style.xhtml
│ │ ├── Links_reference_style.json
│ │ ├── Links_reference_style.text
│ │ ├── Links_reference_style.xhtml
│ │ ├── Links_shortcut_references.json
│ │ ├── Links_shortcut_references.text
│ │ ├── Links_shortcut_references.xhtml
│ │ ├── Literal_quotes_in_titles.json
│ │ ├── Literal_quotes_in_titles.text
│ │ ├── Literal_quotes_in_titles.xhtml
│ │ ├── Markdown_Documentation_-_Basics.json
│ │ ├── Markdown_Documentation_-_Basics.text
│ │ ├── Markdown_Documentation_-_Basics.xhtml
│ │ ├── Markdown_Documentation_-_Syntax.json
│ │ ├── Markdown_Documentation_-_Syntax.text
│ │ ├── Markdown_Documentation_-_Syntax.xhtml
│ │ ├── Nested_blockquotes.json
│ │ ├── Nested_blockquotes.text
│ │ ├── Nested_blockquotes.xhtml
│ │ ├── Ordered_and_unordered_lists.json
│ │ ├── Ordered_and_unordered_lists.text
│ │ ├── Ordered_and_unordered_lists.xhtml
│ │ ├── Strong_and_em_together.json
│ │ ├── Strong_and_em_together.text
│ │ ├── Strong_and_em_together.xhtml
│ │ ├── Tabs.json
│ │ ├── Tabs.text
│ │ ├── Tabs.xhtml
│ │ ├── Tidyness.json
│ │ ├── Tidyness.text
│ │ └── Tidyness.xhtml
│ ├── PHP_Markdown-from-MDTest1.1.mdtest/
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Backslash_escapes.xhtml
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_Spans.xhtml
│ │ ├── Code_block_in_a_list_item.json
│ │ ├── Code_block_in_a_list_item.text
│ │ ├── Code_block_in_a_list_item.xhtml
│ │ ├── Email_auto_links.json
│ │ ├── Email_auto_links.text
│ │ ├── Email_auto_links.xhtml
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Emphasis.xhtml
│ │ ├── Headers.json
│ │ ├── Headers.text
│ │ ├── Headers.xhtml
│ │ ├── Horizontal_Rules.json
│ │ ├── Horizontal_Rules.text
│ │ ├── Horizontal_Rules.xhtml
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_(Span).json
│ │ ├── Inline_HTML_(Span).text
│ │ ├── Inline_HTML_(Span).xhtml
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── Ins_and_del.json
│ │ ├── Ins_and_del.text
│ │ ├── Ins_and_del.xhtml
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Links_inline_style.xhtml
│ │ ├── MD5_Hashes.json
│ │ ├── MD5_Hashes.text
│ │ ├── MD5_Hashes.xhtml
│ │ ├── Nesting.json
│ │ ├── Nesting.text
│ │ ├── Nesting.xhtml
│ │ ├── PHP-Specific_Bugs.json
│ │ ├── PHP-Specific_Bugs.text
│ │ ├── PHP-Specific_Bugs.xhtml
│ │ ├── Parens_in_URL.json
│ │ ├── Parens_in_URL.text
│ │ ├── Parens_in_URL.xhtml
│ │ ├── Tight_blocks.json
│ │ ├── Tight_blocks.text
│ │ └── Tight_blocks.xhtml
│ ├── README
│ ├── Text-Markdown.mdtest/
│ │ ├── CoreDumps5.8.json
│ │ ├── CoreDumps5.8.text
│ │ ├── CoreDumps5.8.xhtml
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Emphasis.xhtml
│ │ ├── HTML-Comment-encoding.json
│ │ ├── HTML-Comment-encoding.text
│ │ ├── HTML-Comment-encoding.xhtml
│ │ ├── HTML5-attributes.html
│ │ ├── HTML5-attributes.json
│ │ ├── HTML5-attributes.text
│ │ ├── Links_brackets.json
│ │ ├── Links_brackets.text
│ │ ├── Links_brackets.xhtml
│ │ ├── Links_multiline_bugs_1.html
│ │ ├── Links_multiline_bugs_1.json
│ │ ├── Links_multiline_bugs_1.text
│ │ ├── Links_multiline_bugs_2.html
│ │ ├── Links_multiline_bugs_2.json
│ │ ├── Links_multiline_bugs_2.text
│ │ ├── Links_reference_style.json
│ │ ├── Links_reference_style.text
│ │ ├── Links_reference_style.xhtml
│ │ ├── Lists-multilevel-md5-edgecase.json
│ │ ├── Lists-multilevel-md5-edgecase.text
│ │ ├── Lists-multilevel-md5-edgecase.xhtml
│ │ ├── PHP-ASP_tags.json
│ │ ├── PHP-ASP_tags.text
│ │ ├── PHP-ASP_tags.xhtml
│ │ ├── Unicode.json
│ │ ├── Unicode.text
│ │ └── Unicode.xhtml
│ ├── docs-maruku-unittest/
│ │ ├── abbreviations.html
│ │ ├── abbreviations.json
│ │ ├── abbreviations.text
│ │ ├── alt.html
│ │ ├── alt.json
│ │ ├── alt.text
│ │ ├── blank.html
│ │ ├── blank.json
│ │ ├── blank.text
│ │ ├── blanks_in_code.html
│ │ ├── blanks_in_code.json
│ │ ├── blanks_in_code.text
│ │ ├── bug_def.html
│ │ ├── bug_def.json
│ │ ├── bug_def.text
│ │ ├── bug_table.html
│ │ ├── bug_table.json
│ │ ├── bug_table.text
│ │ ├── code.html
│ │ ├── code.json
│ │ ├── code.text
│ │ ├── code2.html
│ │ ├── code2.json
│ │ ├── code2.text
│ │ ├── code3.html
│ │ ├── code3.json
│ │ ├── code3.text
│ │ ├── convert.pl
│ │ ├── data_loss.html
│ │ ├── data_loss.json
│ │ ├── data_loss.text
│ │ ├── easy.html
│ │ ├── easy.json
│ │ ├── easy.text
│ │ ├── email.html
│ │ ├── email.json
│ │ ├── email.text
│ │ ├── entities.html
│ │ ├── entities.json
│ │ ├── entities.text
│ │ ├── escaping.html
│ │ ├── escaping.json
│ │ ├── escaping.text
│ │ ├── extra_dl.html
│ │ ├── extra_dl.json
│ │ ├── extra_dl.text
│ │ ├── extra_header_id.html
│ │ ├── extra_header_id.json
│ │ ├── extra_header_id.text
│ │ ├── extra_table1.html
│ │ ├── extra_table1.json
│ │ ├── extra_table1.text
│ │ ├── footnotes.html
│ │ ├── footnotes.json
│ │ ├── footnotes.text
│ │ ├── headers.html
│ │ ├── headers.json
│ │ ├── headers.text
│ │ ├── hex_entities.html
│ │ ├── hex_entities.json
│ │ ├── hex_entities.text
│ │ ├── hrule.html
│ │ ├── hrule.json
│ │ ├── hrule.text
│ │ ├── html2.html
│ │ ├── html2.json
│ │ ├── html2.text
│ │ ├── html3.html
│ │ ├── html3.json
│ │ ├── html3.text
│ │ ├── html4.html
│ │ ├── html4.json
│ │ ├── html4.text
│ │ ├── html5.html
│ │ ├── html5.json
│ │ ├── html5.text
│ │ ├── ie.html
│ │ ├── ie.json
│ │ ├── ie.text
│ │ ├── images.html
│ │ ├── images.json
│ │ ├── images.text
│ │ ├── images2.html
│ │ ├── images2.json
│ │ ├── images2.text
│ │ ├── inline_html.html
│ │ ├── inline_html.json
│ │ ├── inline_html.text
│ │ ├── inline_html2.html
│ │ ├── inline_html2.json
│ │ ├── inline_html2.text
│ │ ├── links.html
│ │ ├── links.json
│ │ ├── links.text
│ │ ├── list1.html
│ │ ├── list1.json
│ │ ├── list1.text
│ │ ├── list2.html
│ │ ├── list2.json
│ │ ├── list2.text
│ │ ├── list3.html
│ │ ├── list3.json
│ │ ├── list3.text
│ │ ├── list4.html
│ │ ├── list4.json
│ │ ├── list4.text
│ │ ├── lists.html
│ │ ├── lists.json
│ │ ├── lists.text
│ │ ├── lists11.html
│ │ ├── lists11.json
│ │ ├── lists11.text
│ │ ├── lists6.html
│ │ ├── lists6.json
│ │ ├── lists6.text
│ │ ├── lists7.html
│ │ ├── lists7.json
│ │ ├── lists7.text
│ │ ├── lists7b.html
│ │ ├── lists7b.json
│ │ ├── lists7b.text
│ │ ├── lists8.html
│ │ ├── lists8.json
│ │ ├── lists8.text
│ │ ├── lists9.html
│ │ ├── lists9.json
│ │ ├── lists9.text
│ │ ├── lists_after_paragraph.html
│ │ ├── lists_after_paragraph.json
│ │ ├── lists_after_paragraph.text
│ │ ├── lists_ol.html
│ │ ├── lists_ol.json
│ │ ├── lists_ol.text
│ │ ├── loss.html
│ │ ├── loss.json
│ │ ├── loss.text
│ │ ├── misc_sw.html
│ │ ├── misc_sw.json
│ │ ├── misc_sw.text
│ │ ├── olist.html
│ │ ├── olist.json
│ │ ├── olist.text
│ │ ├── one.html
│ │ ├── one.json
│ │ ├── one.text
│ │ ├── paragraph.html
│ │ ├── paragraph.json
│ │ ├── paragraph.text
│ │ ├── paragraphs.html
│ │ ├── paragraphs.json
│ │ ├── paragraphs.text
│ │ ├── smartypants.html
│ │ ├── smartypants.json
│ │ ├── smartypants.text
│ │ ├── syntax_hl.html
│ │ ├── syntax_hl.json
│ │ ├── syntax_hl.text
│ │ ├── table_attributes.html
│ │ ├── table_attributes.json
│ │ ├── table_attributes.text
│ │ ├── test.html
│ │ ├── test.json
│ │ ├── test.text
│ │ ├── wrapping.html
│ │ ├── wrapping.json
│ │ ├── wrapping.text
│ │ ├── xml.html
│ │ ├── xml.json
│ │ ├── xml.text
│ │ ├── xml2.html
│ │ ├── xml2.json
│ │ ├── xml2.text
│ │ ├── xml3.html
│ │ ├── xml3.json
│ │ ├── xml3.text
│ │ ├── xml_instruction.html
│ │ ├── xml_instruction.json
│ │ └── xml_instruction.text
│ ├── docs-php-markdown/
│ │ ├── Backslash_escapes.html
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Code_Spans.html
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_block_in_a_list_item.html
│ │ ├── Code_block_in_a_list_item.json
│ │ ├── Code_block_in_a_list_item.text
│ │ ├── Headers.html
│ │ ├── Headers.json
│ │ ├── Headers.text
│ │ ├── Images_(Untitled).html
│ │ ├── Images_(Untitled).json
│ │ ├── Images_(Untitled).text
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── PHP-Specific_Bugs.html
│ │ ├── PHP-Specific_Bugs.json
│ │ ├── PHP-Specific_Bugs.text
│ │ ├── Tight_blocks.html
│ │ ├── Tight_blocks.json
│ │ └── Tight_blocks.text
│ ├── docs-php-markdown-extra/
│ │ ├── Abbr.html
│ │ ├── Abbr.json
│ │ ├── Abbr.text
│ │ ├── Definition_Lists.html
│ │ ├── Definition_Lists.json
│ │ ├── Definition_Lists.text
│ │ ├── Emphasis.html
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Footnotes.html
│ │ ├── Footnotes.json
│ │ ├── Footnotes.text
│ │ ├── Inline_HTML_with_Markdown_content.html
│ │ ├── Inline_HTML_with_Markdown_content.json
│ │ ├── Inline_HTML_with_Markdown_content.text
│ │ ├── Tables.html
│ │ ├── Tables.json
│ │ └── Tables.text
│ ├── docs-php-markdown-todo/
│ │ ├── Email_auto_links.html
│ │ ├── Email_auto_links.json
│ │ ├── Email_auto_links.text
│ │ ├── Emphasis.html
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Inline_HTML_(Span).html
│ │ ├── Inline_HTML_(Span).json
│ │ ├── Inline_HTML_(Span).text
│ │ ├── Ins_and_del.json
│ │ ├── Ins_and_del.text
│ │ ├── Ins_and_del.xhtml
│ │ ├── Links_inline_style.html
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Nesting.html
│ │ ├── Nesting.json
│ │ ├── Nesting.text
│ │ ├── Parens_in_URL.html
│ │ ├── Parens_in_URL.json
│ │ └── Parens_in_URL.text
│ └── docs-pythonmarkdown2-tm-cases-pass/
│ ├── auto_link.html
│ ├── auto_link.json
│ ├── auto_link.text
│ ├── auto_link_safe_mode.html
│ ├── auto_link_safe_mode.json
│ ├── auto_link_safe_mode.opts
│ ├── auto_link_safe_mode.text
│ ├── basic_safe_mode.html
│ ├── basic_safe_mode.json
│ ├── basic_safe_mode.opts
│ ├── basic_safe_mode.text
│ ├── basic_safe_mode_escape.html
│ ├── basic_safe_mode_escape.json
│ ├── basic_safe_mode_escape.opts
│ ├── basic_safe_mode_escape.text
│ ├── blockquote.html
│ ├── blockquote.json
│ ├── blockquote.text
│ ├── blockquote_with_pre.html
│ ├── blockquote_with_pre.json
│ ├── blockquote_with_pre.text
│ ├── code_block_with_tabs.html
│ ├── code_block_with_tabs.json
│ ├── code_block_with_tabs.text
│ ├── code_safe_emphasis.html
│ ├── code_safe_emphasis.json
│ ├── code_safe_emphasis.opts
│ ├── code_safe_emphasis.text
│ ├── codeblock.html
│ ├── codeblock.json
│ ├── codeblock.text
│ ├── codespans.html
│ ├── codespans.json
│ ├── codespans.text
│ ├── codespans_safe_mode.html
│ ├── codespans_safe_mode.json
│ ├── codespans_safe_mode.opts
│ ├── codespans_safe_mode.text
│ ├── emacs_head_vars.html
│ ├── emacs_head_vars.json
│ ├── emacs_head_vars.text
│ ├── emacs_tail_vars.html
│ ├── emacs_tail_vars.json
│ ├── emacs_tail_vars.text
│ ├── emphasis.html
│ ├── emphasis.json
│ ├── emphasis.text
│ ├── escapes.html
│ ├── escapes.json
│ ├── escapes.text
│ ├── footnotes.html
│ ├── footnotes.json
│ ├── footnotes.opts
│ ├── footnotes.text
│ ├── footnotes_letters.html
│ ├── footnotes_letters.json
│ ├── footnotes_letters.opts
│ ├── footnotes_letters.text
│ ├── footnotes_markup.html
│ ├── footnotes_markup.json
│ ├── footnotes_markup.opts
│ ├── footnotes_markup.text
│ ├── footnotes_safe_mode_escape.html
│ ├── footnotes_safe_mode_escape.json
│ ├── footnotes_safe_mode_escape.opts
│ ├── footnotes_safe_mode_escape.text
│ ├── header.html
│ ├── header.json
│ ├── header.text
│ ├── hr.html
│ ├── hr.json
│ ├── hr.text
│ ├── img_in_link.html
│ ├── img_in_link.json
│ ├── img_in_link.text
│ ├── inline_links.html
│ ├── inline_links.json
│ ├── inline_links.text
│ ├── issue2_safe_mode_borks_markup.html
│ ├── issue2_safe_mode_borks_markup.json
│ ├── issue2_safe_mode_borks_markup.opts
│ ├── issue2_safe_mode_borks_markup.text
│ ├── link_defn_alt_title_delims.html
│ ├── link_defn_alt_title_delims.json
│ ├── link_defn_alt_title_delims.text
│ ├── link_patterns.html
│ ├── link_patterns.json
│ ├── link_patterns.opts
│ ├── link_patterns.text
│ ├── link_patterns_double_hit.html
│ ├── link_patterns_double_hit.json
│ ├── link_patterns_double_hit.opts
│ ├── link_patterns_double_hit.text
│ ├── link_patterns_edge_cases.html
│ ├── link_patterns_edge_cases.json
│ ├── link_patterns_edge_cases.opts
│ ├── link_patterns_edge_cases.text
│ ├── lists.html
│ ├── lists.json
│ ├── lists.text
│ ├── mismatched_footnotes.html
│ ├── mismatched_footnotes.json
│ ├── mismatched_footnotes.opts
│ ├── mismatched_footnotes.text
│ ├── missing_link_defn.html
│ ├── missing_link_defn.json
│ ├── missing_link_defn.text
│ ├── nested_list.html
│ ├── nested_list.json
│ ├── nested_list.text
│ ├── nested_list_safe_mode.html
│ ├── nested_list_safe_mode.json
│ ├── nested_list_safe_mode.opts
│ ├── nested_list_safe_mode.text
│ ├── parens_in_url_4.html
│ ├── parens_in_url_4.json
│ ├── parens_in_url_4.text
│ ├── raw_html.html
│ ├── raw_html.json
│ ├── raw_html.text
│ ├── ref_links.html
│ ├── ref_links.json
│ ├── ref_links.text
│ ├── sublist-para.html
│ ├── sublist-para.json
│ ├── sublist-para.text
│ ├── syntax_color.html
│ ├── syntax_color.json
│ ├── syntax_color.opts
│ ├── syntax_color.text
│ ├── tricky_anchors.html
│ ├── tricky_anchors.json
│ ├── tricky_anchors.text
│ ├── underline_in_autolink.html
│ ├── underline_in_autolink.json
│ └── underline_in_autolink.text
├── html_renderer.t.js
├── interface.t.js
├── regressions.t.js
└── render_tree.t.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.*.swp
.DS_Store
/node_modules/
/npm-debug.log
dist
lib/markdown.js
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "0.10"
- "0.11"
================================================
FILE: Changes.md
================================================
# Changelog for markdown
## vNEXT - ???
- **Big change**: Drop official support for Node 0.8
- Use JSHint to validate code style and fix numerous warnings it flagged up
([#65]) Thanks [XhmikosR](https://github.com/XhmikosR)!
- Fix (yet more! gah) global variable leaks ([#99])
- Fix content tight between two `hr`'s disappearing ([#106])
- Use [Grunt](http://gruntjs.com/) to build tailored versions including allowing
customizing of what dialects are included ([#113] - [Robin Ward](https://github.com/eviltrout))
- Add in a bower.json for easier use in non-node environments ([#184])
- Lots of small other fixes
## v0.5.0 - 2013-07-26
There might be other bug fixes then the ones listed - I've been a bit lax at
updating the changes file, sorry :(
- Fix "undefined" appearing in output for some cases with blockquotes
- Fix (multiple) global variable leaks. Ooops
- Allow spaces in img/link paths ([#48])
- Handle windows line endings ([#58])
- Fix IE8 issues ([#68], [#86], [#97])
- Fix images inside links mistakenly requiring a title attribute to parse
correctly ([#71])
- Add explicit text of the license to the readme ([#74])
- Style tweaks by [XhmikosR](https://github.com/XhmikosR) ([#81], [#82], [#83])
- Build now tested by TravisCI thanks to [sebs](https://github.com/sebs) ([#85])
- Fix "cuddled" header parsing ([#94])
- Add support for tables to Maruku dialect ([#66]) Thanks [redsun82](https://github.com/redsun82)!
## v0.4.0 - 2012-06-09
- Improve link parsing when multiple on a line ([#5])
- `npm test` will now run the entire test suite cleanly
(switch tests over to [node-tap](https://github.com/isaacs/node-tap)) ([#21])
- Fix blockquote merging/implicit conversion between string/String ([#24], [#44])
- Allow inline elements to appear inside link text ([#27])
- Fix to correctly render self-closing tags ([#28], [#35], [#40])
- Actually render image references ([#36])
- Make it work in IE7/8 ([#37])
- Improve link parsing when link is inside parenthesis ([#38])
- Fix JSLint warnings ([#42])
- `md2html` can now process stdin ([#43])
- Fix for anchors enclosed by parenthesis ([#46])
[#5]: https://github.com/evilstreak/markdown-js/issues/5
[#21]: https://github.com/evilstreak/markdown-js/issues/21
[#24]: https://github.com/evilstreak/markdown-js/issues/24
[#27]: https://github.com/evilstreak/markdown-js/issues/27
[#28]: https://github.com/evilstreak/markdown-js/issues/28
[#35]: https://github.com/evilstreak/markdown-js/issues/35
[#36]: https://github.com/evilstreak/markdown-js/issues/36
[#37]: https://github.com/evilstreak/markdown-js/issues/37
[#38]: https://github.com/evilstreak/markdown-js/issues/38
[#40]: https://github.com/evilstreak/markdown-js/issues/40
[#42]: https://github.com/evilstreak/markdown-js/issues/42
[#43]: https://github.com/evilstreak/markdown-js/issues/43
[#44]: https://github.com/evilstreak/markdown-js/issues/44
[#46]: https://github.com/evilstreak/markdown-js/issues/46
[#48]: https://github.com/evilstreak/markdown-js/issues/48
[#58]: https://github.com/evilstreak/markdown-js/issues/58
[#65]: https://github.com/evilstreak/markdown-js/issues/65
[#66]: https://github.com/evilstreak/markdown-js/issues/66
[#68]: https://github.com/evilstreak/markdown-js/issues/68
[#71]: https://github.com/evilstreak/markdown-js/issues/71
[#74]: https://github.com/evilstreak/markdown-js/issues/74
[#81]: https://github.com/evilstreak/markdown-js/issues/81
[#82]: https://github.com/evilstreak/markdown-js/issues/82
[#83]: https://github.com/evilstreak/markdown-js/issues/83
[#85]: https://github.com/evilstreak/markdown-js/issues/85
[#86]: https://github.com/evilstreak/markdown-js/issues/86
[#94]: https://github.com/evilstreak/markdown-js/issues/94
[#97]: https://github.com/evilstreak/markdown-js/issues/97
[#99]: https://github.com/evilstreak/markdown-js/issues/99
[#106]: https://github.com/evilstreak/markdown-js/issues/106
[#113]: https://github.com/evilstreak/markdown-js/issues/113
================================================
FILE: Gruntfile.js
================================================
module.exports = function(grunt) {
var pkg = grunt.file.readJSON('package.json');
grunt.initConfig({
pkg: pkg,
env: process.env,
node_tap: {
default_options: {
options: {
outputType: 'failures',
outputTo: 'console'
},
files: {
'tests': ['./test/*.t.js']
}
}
},
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
"browser": false,
"maxerr": 100,
"node": true,
"camelcase": false,
"curly": false,
"eqeqeq": true,
"eqnull": true,
"forin": false,
"globals": {
"define": true,
"print": true,
"uneval": true,
"window": true
},
"immed": true,
"indent": 2,
"latedef": true,
"laxbreak": true,
"laxcomma": true,
"lastsemic": true,
"loopfunc": true,
"noarg": true,
"newcap": true,
"plusplus": false,
"quotmark": "true",
"regexp": true,
"shadow": true,
"strict": false,
"sub": true,
"trailing": true,
"undef": true,
"unused": false,
ignores: ['.git', 'node_modules']
}
},
build: {
web: {
dest: "dist/markdown.js",
minimum: ["parser"],
removeWith: ['dialects/gruber'],
startFile: "inc/header.js",
endFile: "inc/footer-web.js"
},
node: {
dest: "lib/markdown.js",
minimum: ["parser"],
removeWith: ['dialects/gruber'],
startFile: "inc/header.js",
endFile: "inc/footer-node.js"
}
},
uglify: {
my_target: {
options: {
compress: true,
mangle: true,
preserveComments: "some",
report: "min"
},
files: {
'dist/markdown.min.js': ['dist/markdown.js']
}
}
}
});
grunt.registerTask('all', ['test', 'build', 'uglify']);
grunt.registerTask('default', ['all']);
grunt.registerTask('test', 'Runs all tests and linting', ['node_tap', 'jshint']);
grunt.loadNpmTasks('grunt-node-tap');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadTasks("inc/tasks");
};
================================================
FILE: README.md
================================================
[](http://badge.fury.io/js/markdown)
[](https://travis-ci.org/evilstreak/markdown-js)
[](https://gemnasium.com/evilstreak/markdown-js)
## Notice: Unmaintained
This repo is no longer maintained, however there are many alternatives:
- [Markdown-It](https://github.com/markdown-it/markdown-it)
- [Showdown](https://github.com/showdownjs/showdown)
- [Marked](https://github.com/markedjs/marked)
- and more...
# markdown-js
Yet another Markdown parser, this time for JavaScript. There's a few
options that precede this project but they all treat Markdown to HTML
conversion as a single step process. You pass Markdown in and get HTML
out, end of story. We had some pretty particular views on how the
process should actually look, which include:
* Producing well-formed HTML. This means that `em` and `strong` nesting
is important, as is the ability to output as both HTML and XHTML
* Having an intermediate representation to allow processing of parsed
data (we in fact have two, both [JsonML]: a markdown tree and an HTML tree)
* Being easily extensible to add new dialects without having to
rewrite the entire parsing mechanics
* Having a good test suite. The only test suites we could find tested
massive blocks of input, and passing depended on outputting the HTML
with exactly the same whitespace as the original implementation
[JsonML]: http://jsonml.org/ "JSON Markup Language"
## Installation
Just the `markdown` library:
npm install markdown
Optionally, install `md2html` into your path
npm install -g markdown
### In the browser
If you want to use from the browser go to the [releases] page on GitHub and
download the version you want (minified or not).
[releases]: https://github.com/evilstreak/markdown-js/releases
## Usage
The basic interface is:
```js
md_content = "Hello.\n\n* This is markdown.\n* It is fun\n* Love it or leave it."
html_content = markdown.toHTML( md_content );
```
toHTML also accepts a dialect argument:
```js
md_content = "Vessel | Captain\n-----------|-------------\nNCC-1701 | James T Kirk\nNCC-1701 A | James T Kirk\nNCC-1701 D | Picard";
html_content = markdown.toHTML( md_content, 'Maruku');
```
### Node
The simple way to use it with Node is:
```js
var markdown = require( "markdown" ).markdown;
console.log( markdown.toHTML( "Hello *World*!" ) );
```
### ES6
```js
import {markdown} from 'markdown';
console.log( markdown.toHTML( "Hello *World*!" ) );
```
#### Older versions of node
We only officially support node >= 0.10 as the libraries we use for building
and testing don't work on older versions of node. That said since this module
is so simple and doesn't use any parts of the node API if you use the pre-built
version and find a bug let us know and we'll try and fix it.
### Browser
It also works in a browser; here is a complete example:
```html
<!DOCTYPE html>
<html>
<body>
<textarea id="text-input" oninput="this.editor.update()"
rows="6" cols="60">Type **Markdown** here.</textarea>
<div id="preview"> </div>
<script src="lib/markdown.js"></script>
<script>
function Editor(input, preview) {
this.update = function () {
preview.innerHTML = markdown.toHTML(input.value);
};
input.editor = this;
this.update();
}
var $ = function (id) { return document.getElementById(id); };
new Editor($("text-input"), $("preview"));
</script>
</body>
</html>
```
### Command Line
Assuming you've installed the `md2html` script (see Installation,
above), you can convert Markdown to HTML:
```bash
# read from a file
md2html /path/to/doc.md > /path/to/doc.html
# or from stdin
echo 'Hello *World*!' | md2html
```
### More Options
If you want more control check out the documentation in
[the .js files under src/][src_folder] which details all the methods and parameters
available (including examples!). One day we'll get the docs generated
and hosted somewhere for nicer browsing.
[src_folder]: https://github.com/evilstreak/markdown-js/blob/master/src
Meanwhile, here's an example of using the multi-step processing to
make wiki-style linking work by filling in missing link references:
```js
var md = require( "markdown" ).markdown,
text = "[Markdown] is a simple text-based [markup language]\n" +
"created by [John Gruber]\n\n" +
"[John Gruber]: http://daringfireball.net";
// parse the markdown into a tree and grab the link references
var tree = md.parse( text ),
refs = tree[ 1 ].references;
// iterate through the tree finding link references
( function find_link_refs( jsonml ) {
if ( jsonml[ 0 ] === "link_ref" ) {
var ref = jsonml[ 1 ].ref;
// if there's no reference, define a wiki link
if ( !refs[ ref ] ) {
refs[ ref ] = {
href: "http://en.wikipedia.org/wiki/" + ref.replace(/\s+/, "_" )
};
}
}
else if ( Array.isArray( jsonml[ 1 ] ) ) {
jsonml[ 1 ].forEach( find_link_refs );
}
else if ( Array.isArray( jsonml[ 2 ] ) ) {
jsonml[ 2 ].forEach( find_link_refs );
}
} )( tree );
// convert the tree into html
var html = md.renderJsonML( md.toHTMLTree( tree ) );
console.log( html );
```
## Intermediate Representation
Internally the process to convert a chunk of Markdown into a chunk of
HTML has three steps:
1. Parse the Markdown into a JsonML tree. Any references found in the
parsing are stored in the attribute hash of the root node under the
key `references`.
2. Convert the Markdown tree into an HTML tree. Rename any nodes that
need it (`bulletlist` to `ul` for example) and lookup any references
used by links or images. Remove the references attribute once done.
3. Stringify the HTML tree being careful not to wreck whitespace where
whitespace is important (surrounding inline elements for example).
Each step of this process can be called individually if you need to do
some processing or modification of the data at an intermediate stage.
For example, you may want to grab a list of all URLs linked to in the
document before rendering it to HTML which you could do by recursing
through the HTML tree looking for `a` nodes.
## Building and Testing markdown-js
We use [Grunt](http://gruntjs.com/) to build and run markdown-js's tests.
Make sure you run `npm install` to install the developer dependencies for
the project, then you can:
$ npm test
To run our test suite. If you'd like to build markdown-js, you can run:
$ ./node_modules/.bin/grunt all
This command will run all the tests, then output a concatenated markdown.js
and markdown.min.js in the `dist/` directory for use in a browser application.
## Building a custom markdown-js
By default, you will get the [Gruber] and [Maruku] dialects included when you
run `grunt all`. However, you can create a custom build using the following
syntax if you don't want to include Maruku support.
$ ./node_modules/.bin/grunt "custom:-dialects/maruku"
[Gruber]: http://daringfireball.net/projects/markdown/syntax
[Maruku]: http://maruku.rubyforge.org/maruku.html
## Running Tests
To run the tests under Node you will need tap installed (it's listed as a
`devDependencies` so `npm install` from the checkout should be enough), then do
$ npm test
## Contributing
Do the usual GitHub fork and pull request dance. Add yourself to the
contributors section of [package.json] too if you want to.
[package.json]: https://github.com/evilstreak/markdown-js/blob/master/package.json
## License
Released under the MIT license.
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.
================================================
FILE: bin/md2html.js
================================================
#!/usr/bin/env node
(function () {
"use strict";
var fs = require("fs"),
markdown = require("markdown").markdown,
nopt = require("nopt"),
stream,
opts,
buffer = "";
opts = nopt(
{ "dialect": [ "Gruber", "Maruku"],
"help": Boolean
}
);
if (opts.help || process.argv.length === 2) {
var name = process.argv[1].split("/").pop();
console.warn( require("util").format(
"usage: %s [--dialect=DIALECT] FILE\n\nValid dialects are Gruber (the default) or Maruku",
name
) );
process.exit(0);
}
var fullpath = opts.argv.remain[0];
if (fullpath && fullpath !== "-")
stream = fs.createReadStream(fullpath);
else
stream = process.stdin;
stream.resume();
stream.setEncoding("utf8");
stream.on("error", function(error) {
console.error(error.toString());
process.exit(1);
});
stream.on("data", function(data) {
buffer += data;
});
stream.on("end", function() {
var html = markdown.toHTML(buffer, opts.dialect);
console.log(html);
});
}());
================================================
FILE: bower.json
================================================
{
"name": "markdown",
"homepage": "https://github.com/evilstreak/markdown-js",
"_source": "git://github.com/evilstreak/markdown-js.git",
"_target": "master",
"_originalSource": "markdown",
"version": "v0.6.0-beta1",
"authors": [
"Dominic Baggott <dominic.baggott@gmail.com> (http://evilstreak.co.uk)",
"Ash Berlin <ash_markdownjs@firemirror.com> (http://ashberlin.com)"
],
"description": "A sensible Markdown parser for javascript",
"main": "./lib/index.js",
"keywords": [
"markdown",
"text processing",
"ast"
],
"license": "MIT"
}
================================================
FILE: inc/footer-node.js
================================================
expose.Markdown = Markdown;
expose.parse = Markdown.parse;
expose.toHTML = Markdown.toHTML;
expose.toHTMLTree = Markdown.toHTMLTree;
expose.renderJsonML = Markdown.renderJsonML;
expose.DialectHelpers = DialectHelpers;
})(exports);
================================================
FILE: inc/footer-web.js
================================================
expose.Markdown = Markdown;
expose.parse = Markdown.parse;
expose.toHTML = Markdown.toHTML;
expose.toHTMLTree = Markdown.toHTMLTree;
expose.renderJsonML = Markdown.renderJsonML;
expose.DialectHelpers = DialectHelpers;
})(function() {
window.markdown = {};
return window.markdown;
}());
================================================
FILE: inc/header.js
================================================
/*!
* Markdown
* Released under MIT license
* Copyright (c) 2009-2010 Dominic Baggott
* Copyright (c) 2009-2010 Ash Berlin
* Copyright (c) 2011 Christoph Dorn <christoph@christophdorn.com> (http://www.christophdorn.com)
* Version: @VERSION
* Date: @DATE
*/
(function(expose) {
================================================
FILE: inc/tasks/build_markdown.js
================================================
/**
Tasks cribbed from jQuery to handle building custom markdown parsers.
*/
module.exports = function( grunt ) {
"use strict";
var fs = require( "fs" ),
srcFolder = __dirname + "/../../src/",
rdefineEnd = /\}\);[^}\w]*$/,
// This is temporary until the skipSemiColonInsertion option makes it to NPM
requirejs = require( "requirejs" ),
config = {
baseUrl: "src",
name: "markdown",
// We have multiple minify steps
optimize: "none",
skipSemiColonInsertion: true,
onBuildWrite: convert
};
/**
* Strip all definitions generated by requirejs
* Convert "var" modules to var declarations
* "var module" means the module only contains a return statement that should be converted to a var declaration
* This is indicated by including the file in any "var" folder
* @param {String} name
* @param {String} path
* @param {String} contents The contents to be written (including their AMD wrappers)
*/
function convert( name, path, contents ) {
// Convert var modules
if ( /.\/var\//.test( path ) ) {
contents = contents
.replace( /define\([\w\W]*?return/, "var " + (/var\/([\w-]+)/.exec(name)[1]) + " =" )
.replace( rdefineEnd, "" );
} else {
contents = contents
.replace( /^\s*return\s+[^\}]+(\}\);[^\w\}]*)$/m, "$1" );
// Remove define wrappers, closure ends, and empty declarations
contents = contents
.replace( /define\([^{]*?{/, "" )
.replace( rdefineEnd, "" );
// Remove empty definitions
contents = contents
.replace( /define\(\[[^\]]+\]\)[\W\n]+$/, "" );
}
return contents;
}
grunt.registerMultiTask(
"build",
"Concatenate source, remove sub AMD definitions, (include/exclude modules with +/- flags), embed date/version",
function() {
var flag, index,
done = this.async(),
flags = this.flags,
name = this.data.dest,
minimum = this.data.minimum,
removeWith = this.data.removeWith,
excluded = [],
included = [],
version = grunt.config( "pkg.version" ),
/**
* Recursively calls the excluder to remove on all modules in the list
* @param {Array} list
* @param {String} [prepend] Prepend this to the module name. Indicates we're walking a directory
*/
excludeList = function( list, prepend ) {
if ( list ) {
prepend = prepend ? prepend + "/" : "";
list.forEach(function( module ) {
// Exclude var modules as well
if ( module === "var" ) {
excludeList( fs.readdirSync( srcFolder + prepend + module ), prepend + module );
return;
}
if ( prepend ) {
// Skip if this is not a js file and we're walking files in a dir
if ( !(module = /([\w-\/]+)\.js$/.exec( module )) ) {
return;
}
// Prepend folder name if passed
// Remove .js extension
module = prepend + module[1];
}
// Avoid infinite recursion
if ( excluded.indexOf( module ) === -1 ) {
excluder( "-" + module );
}
});
}
},
/**
* Adds the specified module to the excluded or included list, depending on the flag
* @param {String} flag A module path relative to the src directory starting with + or - to indicate whether it should included or excluded
*/
excluder = function( flag ) {
var m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ),
exclude = m[ 1 ] === "-",
module = m[ 2 ];
if ( exclude ) {
// Can't exclude certain modules
if ( minimum.indexOf( module ) === -1 ) {
// Add to excluded
if ( excluded.indexOf( module ) === -1 ) {
grunt.log.writeln( flag );
excluded.push( module );
// Exclude all files in the folder of the same name
// These are the removable dependencies
// It's fine if the directory is not there
try {
excludeList( fs.readdirSync( srcFolder + module ), module );
} catch( e ) {
grunt.verbose.writeln( e );
}
}
// Check removeWith list
excludeList( removeWith[ module ] );
} else {
grunt.log.error( "Module \"" + module + "\" is a mimimum requirement.");
if ( module === "selector" ) {
grunt.log.error( "If you meant to replace Sizzle, use -sizzle instead." );
}
}
} else {
grunt.log.writeln( flag );
included.push( module );
}
};
// append commit id to version
if ( process.env.COMMIT ) {
version += " " + process.env.COMMIT;
}
// figure out which files to exclude based on these rules in this order:
// dependency explicit exclude
// > explicit exclude
// > explicit include
// > dependency implicit exclude
// > implicit exclude
// examples:
// * none (implicit exclude)
// *:* all (implicit include)
// *:*:-css all except css and dependents (explicit > implicit)
// *:*:-css:+effects same (excludes effects because explicit include is trumped by explicit exclude of dependency)
// *:+effects none except effects and its dependencies (explicit include trumps implicit exclude of dependency)
for ( flag in flags ) {
if ( flag !== "*" ) {
excluder( flag );
}
}
grunt.verbose.writeflags( excluded, "Excluded" );
grunt.verbose.writeflags( included, "Included" );
// append excluded modules to version
if ( excluded.length ) {
version += " -" + excluded.join( ",-" );
// set pkg.version to version with excludes, so minified file picks it up
grunt.config.set( "pkg.version", version );
grunt.verbose.writeln( "Version changed to " + version );
// Have to use shallow or core will get excluded since it is a dependency
config.excludeShallow = excluded;
}
config.include = included;
config.wrap = {
startFile: this.data.startFile,
endFile: this.data.endFile
};
/**
* Handle Final output from the optimizer
* @param {String} compiled
*/
config.out = function( compiled ) {
compiled = compiled
// Remove any lone semi colons
.replace(/^;$/gm, '')
// Remove extra line breaks
.replace(/\n\n+/gm, "\n\n")
// Embed Version
.replace( /@VERSION/g, version )
// Embed Date
// yyyy-mm-ddThh:mmZ
.replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" ) );
// Write concatenated source to file
grunt.file.write( name, compiled );
};
// Trace dependencies and concatenate files
requirejs.optimize( config, function( response ) {
grunt.verbose.writeln( response );
grunt.log.ok( "File '" + name + "' created." );
done();
}, function( err ) {
done( err );
});
});
// Special "alias" task to make custom build creation less grawlix-y
// Translation example
//
// grunt custom:+ajax,-dimensions,-effects,-offset
//
// Becomes:
//
// grunt build:*:*:+ajax:-dimensions:-effects:-offset
grunt.registerTask( "custom", function() {
var args = [].slice.call( arguments ),
modules = args.length ? args[ 0 ].replace( /,/g, ":" ) : "";
grunt.log.writeln( "Creating custom build...\n" );
grunt.task.run([ "build:*:*:" + modules, 'uglify']);
});
};
================================================
FILE: lib/index.js
================================================
// super simple module for the most common nodejs use case.
exports.markdown = require("./markdown");
exports.parse = exports.markdown.toHTML;
================================================
FILE: package.json
================================================
{
"name": "markdown",
"version": "0.6.0-beta1",
"description": "A sensible Markdown parser for javascript",
"keywords": [
"markdown",
"text processing",
"ast"
],
"maintainers": [
"Dominic Baggott <dominic.baggott@gmail.com> (http://evilstreak.co.uk)",
"Ash Berlin <ash_markdownjs@firemirror.com> (http://ashberlin.com)"
],
"contributors": [
"Dominic Baggott <dominic.baggott@gmail.com> (http://evilstreak.co.uk)",
"Ash Berlin <ash_markdownjs@firemirror.com> (http://ashberlin.com)",
"XhmikosR <xhmikosr@users.sourceforge.net>",
"Robin Ward <robin.ward@gmail.com> (http://eviltrout.com)"
],
"bugs": {
"url": "https://github.com/evilstreak/markdown-js/issues"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/evilstreak/markdown-js.git"
},
"main": "./lib/index.js",
"bin": {
"md2html": "./bin/md2html.js"
},
"files": [
"bin",
"lib",
"Changes.md",
"README.md"
],
"dependencies": {
"nopt": "~2.1.1"
},
"devDependencies": {
"amdefine": "~0.0.8",
"grunt": "~0.4.1",
"grunt-cli": "~0.1.9",
"grunt-contrib-jshint": "~0.6.4",
"grunt-contrib-uglify": "~0.2.4",
"grunt-node-tap": "0.1.46",
"requirejs": "~2.1.8",
"tap": "~0.3.3"
},
"scripts": {
"test": "grunt test",
"tap": "grunt node_tap",
"lint": "grunt jshint",
"prepublish": "grunt build"
},
"engines": {
"node": ">=0.10.0"
}
}
================================================
FILE: seed.yml
================================================
---
name: markdown-js
description: JavaScript implementation of Markdown
tags: markdown parser
version: 0.1.2
================================================
FILE: src/core.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define([], function() {
/**
* class Markdown
*
* Markdown processing in Javascript done right. We have very particular views
* on what constitutes 'right' which include:
*
* - produces well-formed HTML (this means that em and strong nesting is
* important)
*
* - has an intermediate representation to allow processing of parsed data (We
* in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
*
* - is easily extensible to add new dialects without having to rewrite the
* entire parsing mechanics
*
* - has a good test suite
*
* This implementation fulfills all of these (except that the test suite could
* do with expanding to automatically run all the fixtures from other Markdown
* implementations.)
*
* ##### Intermediate Representation
*
* *TODO* Talk about this :) Its JsonML, but document the node names we use.
*
* [JsonML]: http://jsonml.org/ "JSON Markup Language"
**/
var Markdown = function(dialect) {
switch (typeof dialect) {
case "undefined":
this.dialect = Markdown.dialects.Gruber;
break;
case "object":
this.dialect = dialect;
break;
default:
if ( dialect in Markdown.dialects )
this.dialect = Markdown.dialects[dialect];
else
throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
break;
}
this.em_state = [];
this.strong_state = [];
this.debug_indent = "";
};
/**
* Markdown.dialects
*
* Namespace of built-in dialects.
**/
Markdown.dialects = {};
return Markdown;
});
================================================
FILE: src/dialects/dialect_helpers.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define([], function (w) {
var DialectHelpers = {};
DialectHelpers.inline_until_char = function( text, want ) {
var consumed = 0,
nodes = [];
while ( true ) {
if ( text.charAt( consumed ) === want ) {
// Found the character we were looking for
consumed++;
return [ consumed, nodes ];
}
if ( consumed >= text.length ) {
// No closing char found. Abort.
return [consumed, null, nodes];
}
var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
consumed += res[ 0 ];
// Add any returned nodes.
nodes.push.apply( nodes, res.slice( 1 ) );
}
};
// Helper function to make sub-classing a dialect easier
DialectHelpers.subclassDialect = function( d ) {
function Block() {}
Block.prototype = d.block;
function Inline() {}
Inline.prototype = d.inline;
return { block: new Block(), inline: new Inline() };
};
return DialectHelpers;
});
================================================
FILE: src/dialects/gruber.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define(['../markdown_helpers', './dialect_helpers', '../parser'], function (MarkdownHelpers, DialectHelpers, Markdown) {
var forEach = MarkdownHelpers.forEach,
extract_attr = MarkdownHelpers.extract_attr,
mk_block = MarkdownHelpers.mk_block,
isEmpty = MarkdownHelpers.isEmpty,
inline_until_char = DialectHelpers.inline_until_char;
// A robust regexp for matching URLs. Thanks: https://gist.github.com/dperini/729294
var urlRegexp = /(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?/i.source;
/**
* Gruber dialect
*
* The default dialect that follows the rules set out by John Gruber's
* markdown.pl as closely as possible. Well actually we follow the behaviour of
* that script which in some places is not exactly what the syntax web page
* says.
**/
var Gruber = {
block: {
atxHeader: function atxHeader( block, next ) {
var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
if ( !m )
return undefined;
var header = [ "header", { level: m[ 1 ].length } ];
Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
if ( m[0].length < block.length )
next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
return [ header ];
},
setextHeader: function setextHeader( block, next ) {
var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
if ( !m )
return undefined;
var level = ( m[ 2 ] === "=" ) ? 1 : 2,
header = [ "header", { level : level } ].concat( this.processInline(m[ 1 ]) );
if ( m[0].length < block.length )
next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
return [ header ];
},
code: function code( block, next ) {
// | Foo
// |bar
// should be a code block followed by a paragraph. Fun
//
// There might also be adjacent code block to merge.
var ret = [],
re = /^(?: {0,3}\t| {4})(.*)\n?/;
// 4 spaces + content
if ( !block.match( re ) )
return undefined;
block_search:
do {
// Now pull out the rest of the lines
var b = this.loop_re_over_block(
re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
if ( b.length ) {
// Case alluded to in first comment. push it back on as a new block
next.unshift( mk_block(b, block.trailing) );
break block_search;
}
else if ( next.length ) {
// Check the next block - it might be code too
if ( !next[0].match( re ) )
break block_search;
// Pull how how many blanks lines follow - minus two to account for .join
ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
block = next.shift();
}
else {
break block_search;
}
} while ( true );
return [ [ "code_block", ret.join("\n") ] ];
},
horizRule: function horizRule( block, next ) {
// this needs to find any hr in the block to handle abutting blocks
var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
if ( !m )
return undefined;
var jsonml = [ [ "hr" ] ];
// if there's a leading abutting block, process it
if ( m[ 1 ] ) {
var contained = mk_block( m[ 1 ], "", block.lineNumber );
jsonml.unshift.apply( jsonml, this.toTree( contained, [] ) );
}
// if there's a trailing abutting block, stick it into next
if ( m[ 3 ] )
next.unshift( mk_block( m[ 3 ], block.trailing, block.lineNumber + 1 ) );
return jsonml;
},
// There are two types of lists. Tight and loose. Tight lists have no whitespace
// between the items (and result in text just in the <li>) and loose lists,
// which have an empty line between list items, resulting in (one or more)
// paragraphs inside the <li>.
//
// There are all sorts weird edge cases about the original markdown.pl's
// handling of lists:
//
// * Nested lists are supposed to be indented by four chars per level. But
// if they aren't, you can get a nested list by indenting by less than
// four so long as the indent doesn't match an indent of an existing list
// item in the 'nest stack'.
//
// * The type of the list (bullet or number) is controlled just by the
// first item at the indent. Subsequent changes are ignored unless they
// are for nested lists
//
lists: (function( ) {
// Use a closure to hide a few variables.
var any_list = "[*+-]|\\d+\\.",
bullet_list = /[*+-]/,
// Capture leading indent as it matters for determining nested lists.
is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
indent_re = "(?: {0,3}\\t| {4})";
// TODO: Cache this regexp for certain depths.
// Create a regexp suitable for matching an li for a given stack depth
function regex_for_depth( depth ) {
return new RegExp(
// m[1] = indent, m[2] = list_type
"(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
// m[3] = cont
"(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
);
}
function expand_tab( input ) {
return input.replace( / {0,3}\t/g, " " );
}
// Add inline content `inline` to `li`. inline comes from processInline
// so is an array of content
function add(li, loose, inline, nl) {
if ( loose ) {
li.push( [ "para" ].concat(inline) );
return;
}
// Hmmm, should this be any block level element or just paras?
var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] === "para"
? li[li.length -1]
: li;
// If there is already some content in this list, add the new line in
if ( nl && li.length > 1 )
inline.unshift(nl);
for ( var i = 0; i < inline.length; i++ ) {
var what = inline[i],
is_str = typeof what === "string";
if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] === "string" )
add_to[ add_to.length-1 ] += what;
else
add_to.push( what );
}
}
// contained means have an indent greater than the current one. On
// *every* line in the block
function get_contained_blocks( depth, blocks ) {
var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
ret = [];
while ( blocks.length > 0 ) {
if ( re.exec( blocks[0] ) ) {
var b = blocks.shift(),
// Now remove that indent
x = b.replace( replace, "");
ret.push( mk_block( x, b.trailing, b.lineNumber ) );
}
else
break;
}
return ret;
}
// passed to stack.forEach to turn list items up the stack into paras
function paragraphify(s, i, stack) {
var list = s.list;
var last_li = list[list.length-1];
if ( last_li[1] instanceof Array && last_li[1][0] === "para" )
return;
if ( i + 1 === stack.length ) {
// Last stack frame
// Keep the same array, but replace the contents
last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
}
else {
var sublist = last_li.pop();
last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
}
}
// The matcher function
return function( block, next ) {
var m = block.match( is_list_re );
if ( !m )
return undefined;
function make_list( m ) {
var list = bullet_list.exec( m[2] )
? ["bulletlist"]
: ["numberlist"];
stack.push( { list: list, indent: m[1] } );
return list;
}
var stack = [], // Stack of lists for nesting.
list = make_list( m ),
last_li,
loose = false,
ret = [ stack[0].list ],
i;
// Loop to search over block looking for inner block elements and loose lists
loose_search:
while ( true ) {
// Split into lines preserving new lines at end of line
var lines = block.split( /(?=\n)/ );
// We have to grab all lines for a li and call processInline on them
// once as there are some inline things that can span lines.
var li_accumulate = "", nl = "";
// Loop over the lines in this block looking for tight lists.
tight_search:
for ( var line_no = 0; line_no < lines.length; line_no++ ) {
nl = "";
var l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
// TODO: really should cache this
var line_re = regex_for_depth( stack.length );
m = l.match( line_re );
//print( "line:", uneval(l), "\nline match:", uneval(m) );
// We have a list item
if ( m[1] !== undefined ) {
// Process the previous list item, if any
if ( li_accumulate.length ) {
add( last_li, loose, this.processInline( li_accumulate ), nl );
// Loose mode will have been dealt with. Reset it
loose = false;
li_accumulate = "";
}
m[1] = expand_tab( m[1] );
var wanted_depth = Math.floor(m[1].length/4)+1;
//print( "want:", wanted_depth, "stack:", stack.length);
if ( wanted_depth > stack.length ) {
// Deep enough for a nested list outright
//print ( "new nested list" );
list = make_list( m );
last_li.push( list );
last_li = list[1] = [ "listitem" ];
}
else {
// We aren't deep enough to be strictly a new level. This is
// where Md.pl goes nuts. If the indent matches a level in the
// stack, put it there, else put it one deeper then the
// wanted_depth deserves.
var found = false;
for ( i = 0; i < stack.length; i++ ) {
if ( stack[ i ].indent !== m[1] )
continue;
list = stack[ i ].list;
stack.splice( i+1, stack.length - (i+1) );
found = true;
break;
}
if (!found) {
//print("not found. l:", uneval(l));
wanted_depth++;
if ( wanted_depth <= stack.length ) {
stack.splice(wanted_depth, stack.length - wanted_depth);
//print("Desired depth now", wanted_depth, "stack:", stack.length);
list = stack[wanted_depth-1].list;
//print("list:", uneval(list) );
}
else {
//print ("made new stack for messy indent");
list = make_list(m);
last_li.push(list);
}
}
//print( uneval(list), "last", list === stack[stack.length-1].list );
last_li = [ "listitem" ];
list.push(last_li);
} // end depth of shenegains
nl = "";
}
// Add content
if ( l.length > m[0].length )
li_accumulate += nl + l.substr( m[0].length );
} // tight_search
if ( li_accumulate.length ) {
var contents = this.processBlock(li_accumulate, []),
firstBlock = contents[0];
if (firstBlock) {
firstBlock.shift();
contents.splice.apply(contents, [0, 1].concat(firstBlock));
add( last_li, loose, contents, nl );
// Let's not creating a trailing \n after content in the li
if(last_li[last_li.length-1] === "\n") {
last_li.pop();
}
// Loose mode will have been dealt with. Reset it
loose = false;
li_accumulate = "";
}
}
// Look at the next block - we might have a loose list. Or an extra
// paragraph for the current li
var contained = get_contained_blocks( stack.length, next );
// Deal with code blocks or properly nested lists
if ( contained.length > 0 ) {
// Make sure all listitems up the stack are paragraphs
forEach( stack, paragraphify, this);
last_li.push.apply( last_li, this.toTree( contained, [] ) );
}
var next_block = next[0] && next[0].valueOf() || "";
if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
block = next.shift();
// Check for an HR following a list: features/lists/hr_abutting
var hr = this.dialect.block.horizRule.call( this, block, next );
if ( hr ) {
ret.push.apply(ret, hr);
break;
}
// Add paragraphs if the indentation level stays the same
if (stack[stack.length-1].indent === block.match(/^\s*/)[0]) {
forEach( stack, paragraphify, this);
}
loose = true;
continue loose_search;
}
break;
} // loose_search
return ret;
};
})(),
blockquote: function blockquote( block, next ) {
// Handle quotes that have spaces before them
var m = /(^|\n) +(\>[\s\S]*)/.exec(block);
if (m && m[2] && m[2].length) {
var blockContents = block.replace(/(^|\n) +\>/, "$1>");
next.unshift(blockContents);
return [];
}
if ( !block.match( /^>/m ) )
return undefined;
var jsonml = [];
// separate out the leading abutting block, if any. I.e. in this case:
//
// a
// > b
//
if ( block[ 0 ] !== ">" ) {
var lines = block.split( /\n/ ),
prev = [],
line_no = block.lineNumber;
// keep shifting lines until you find a crotchet
while ( lines.length && lines[ 0 ][ 0 ] !== ">" ) {
prev.push( lines.shift() );
line_no++;
}
var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
// reassemble new block of just block quotes!
block = mk_block( lines.join( "\n" ), block.trailing, line_no );
}
// if the next block is also a blockquote merge it in
while ( next.length && next[ 0 ][ 0 ] === ">" ) {
var b = next.shift();
block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
}
// Strip off the leading "> " and re-process as a block.
var input = block.replace( /^> ?/gm, "" ),
old_tree = this.tree,
processedBlock = this.toTree( input, [ "blockquote" ] ),
attr = extract_attr( processedBlock );
// If any link references were found get rid of them
if ( attr && attr.references ) {
delete attr.references;
// And then remove the attribute object if it's empty
if ( isEmpty( attr ) )
processedBlock.splice( 1, 1 );
}
jsonml.push( processedBlock );
return jsonml;
},
referenceDefn: function referenceDefn( block, next) {
var re = /^\s*\[([^\[\]]+)\]:\s*(\S+)(?:\s+(?:(['"])(.*)\3|\((.*?)\)))?\n?/;
// interesting matches are [ , ref_id, url, , title, title ]
if ( !block.match(re) )
return undefined;
var attrs = create_attrs.call( this );
var b = this.loop_re_over_block(re, block, function( m ) {
create_reference(attrs, m);
} );
if ( b.length )
next.unshift( mk_block( b, block.trailing ) );
return [];
},
para: function para( block ) {
// everything's a para!
return [ ["para"].concat( this.processInline( block ) ) ];
}
},
inline: {
__oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
var m,
res;
patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
m = re.exec( text );
if (!m) {
// Just boring text
return [ text.length, text ];
}
else if ( m[1] ) {
// Some un-interesting text matched. Return that first
return [ m[1].length, m[1] ];
}
var res;
if ( m[2] in this.dialect.inline ) {
res = this.dialect.inline[ m[2] ].call(
this,
text.substr( m.index ), m, previous_nodes || [] );
}
// Default for now to make dev easier. just slurp special and output it.
res = res || [ m[2].length, m[2] ];
return res;
},
__call__: function inline( text, patterns ) {
var out = [],
res;
function add(x) {
//D:self.debug(" adding output", uneval(x));
if ( typeof x === "string" && typeof out[out.length-1] === "string" )
out[ out.length-1 ] += x;
else
out.push(x);
}
while ( text.length > 0 ) {
res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
text = text.substr( res.shift() );
forEach(res, add );
}
return out;
},
// These characters are interesting elsewhere, so have rules for them so that
// chunks of plain text blocks don't include them
"]": function () {},
"}": function () {},
__escape__ : /^\\[\\`\*_{}<>\[\]()#\+.!\-]/,
"\\": function escaped( text ) {
// [ length of input processed, node/children to add... ]
// Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
if ( this.dialect.inline.__escape__.exec( text ) )
return [ 2, text.charAt( 1 ) ];
else
// Not an esacpe
return [ 1, "\\" ];
},
"
// 1 2 3 4 <--- captures
//
// First attempt to use a strong URL regexp to catch things like parentheses. If it misses, use the
// old one.
var m = text.match(new RegExp("^!\\[(.*?)][ \\t]*\\((" + urlRegexp + ")\\)([ \\t])*([\"'].*[\"'])?")) ||
text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
if ( m ) {
if ( m[2] && m[2][0] === "<" && m[2][m[2].length-1] === ">" )
m[2] = m[2].substring( 1, m[2].length - 1 );
m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
var attrs = { alt: m[1], href: m[2] || "" };
if ( m[4] !== undefined)
attrs.title = m[4];
return [ m[0].length, [ "img", attrs ] ];
}
// ![Alt text][id]
m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
if ( m ) {
// We can't check if the reference is known here as it likely wont be
// found till after. Check it in md tree->hmtl tree conversion
return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
}
// Just consume the '!['
return [ 2, "![" ];
},
"[": function link( text ) {
var open = 1;
for (var i=0; i<text.length; i++) {
var c = text.charAt(i);
if (c === '[') { open++; }
if (c === ']') { open--; }
if (open > 3) { return [1, "["]; }
}
var orig = String(text);
// Inline content is possible inside `link text`
var res = inline_until_char.call( this, text.substr(1), "]" );
// No closing ']' found. Just consume the [
if ( !res[1] ) {
return [ res[0] + 1, text.charAt(0) ].concat(res[2]);
}
// empty link
if ( res[0] === 1 ) { return [ 2, "[]" ]; }
var consumed = 1 + res[ 0 ],
children = res[ 1 ],
link,
attrs;
// At this point the first [...] has been parsed. See what follows to find
// out which kind of link we are (reference or direct url)
text = text.substr( consumed );
// [link text](/path/to/img.jpg "Optional title")
// 1 2 3 <--- captures
// This will capture up to the last paren in the block. We then pull
// back based on if there a matching ones in the url
// ([here](/url/(test))
// The parens have to be balanced
var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
if ( m ) {
var url = m[1].replace(/\s+$/, '');
consumed += m[0].length;
if ( url && url[0] === "<" && url[url.length-1] === ">" )
url = url.substring( 1, url.length - 1 );
// If there is a title we don't have to worry about parens in the url
if ( !m[3] ) {
var open_parens = 1; // One open that isn't in the capture
for ( var len = 0; len < url.length; len++ ) {
switch ( url[len] ) {
case "(":
open_parens++;
break;
case ")":
if ( --open_parens === 0) {
consumed -= url.length - len;
url = url.substring(0, len);
}
break;
}
}
}
// Process escapes only
url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
attrs = { href: url || "" };
if ( m[3] !== undefined)
attrs.title = m[3];
link = [ "link", attrs ].concat( children );
return [ consumed, link ];
}
m = text.match(new RegExp("^\\((" + urlRegexp + ")\\)"));
if (m && m[1]) {
consumed += m[0].length;
link = ["link", {href: m[1]}].concat(children);
return [consumed, link];
}
// [Alt text][id]
// [Alt text] [id]
m = text.match( /^\s*\[(.*?)\]/ );
if ( m ) {
consumed += m[ 0 ].length;
// [links][] uses links as its reference
attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(), original: orig.substr( 0, consumed ) };
if (children && children.length > 0) {
link = [ "link_ref", attrs ].concat( children );
// We can't check if the reference is known here as it likely wont be
// found till after. Check it in md tree->hmtl tree conversion.
// Store the original so that conversion can revert if the ref isn't found.
return [ consumed, link ];
}
}
// Another check for references
m = orig.match(/^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/);
if (m) {
var attrs = create_attrs.call(this);
create_reference(attrs, m);
return [ m[0].length ];
}
// [id]
// Only if id is plain (no formatting.)
if ( children.length === 1 && typeof children[0] === "string" ) {
var normalized = children[0].toLowerCase().replace(/\s+/, ' ');
attrs = { ref: normalized, original: orig.substr( 0, consumed ) };
link = [ "link_ref", attrs, children[0] ];
return [ consumed, link ];
}
// Just consume the "["
return [ 1, "[" ];
},
"<": function autoLink( text ) {
var m;
if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) !== null ) {
if ( m[3] )
return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
else if ( m[2] === "mailto" )
return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
else
return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
}
return [ 1, "<" ];
},
"`": function inlineCode( text ) {
// Inline code block. as many backticks as you like to start it
// Always skip over the opening ticks.
var m = text.match( /(`+)(([\s\S]*?)\1)/ );
if ( m && m[2] )
return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
else {
// TODO: No matching end code found - warn!
return [ 1, "`" ];
}
},
" \n": function lineBreak() {
return [ 3, [ "linebreak" ] ];
}
}
};
// Meta Helper/generator method for em and strong handling
function strong_em( tag, md ) {
var state_slot = tag + "_state",
other_slot = tag === "strong" ? "em_state" : "strong_state";
function CloseTag(len) {
this.len_after = len;
this.name = "close_" + md;
}
return function ( text ) {
if ( this[state_slot][0] === md ) {
// Most recent em is of this type
//D:this.debug("closing", md);
this[state_slot].shift();
// "Consume" everything to go back to the recursion in the else-block below
return[ text.length, new CloseTag(text.length-md.length) ];
}
else {
// Store a clone of the em/strong states
var other = this[other_slot].slice(),
state = this[state_slot].slice();
this[state_slot].unshift(md);
//D:this.debug_indent += " ";
// Recurse
var res = this.processInline( text.substr( md.length ) );
//D:this.debug_indent = this.debug_indent.substr(2);
var last = res[res.length - 1];
//D:this.debug("processInline from", tag + ": ", uneval( res ) );
var check = this[state_slot].shift();
if ( last instanceof CloseTag ) {
res.pop();
// We matched! Huzzah.
var consumed = text.length - last.len_after;
return [ consumed, [ tag ].concat(res) ];
}
else {
// Restore the state of the other kind. We might have mistakenly closed it.
this[other_slot] = other;
this[state_slot] = state;
// We can't reuse the processed result as it could have wrong parsing contexts in it.
return [ md.length, md ];
}
}
}; // End returned function
}
// A helper function to create attributes
function create_attrs() {
if ( !extract_attr( this.tree ) ) {
this.tree.splice( 1, 0, {} );
}
var attrs = extract_attr( this.tree );
// make a references hash if it doesn't exist
if ( attrs.references === undefined ) {
attrs.references = {};
}
return attrs;
}
// Create references for attributes
function create_reference(attrs, m) {
if ( m[2] && m[2][0] === "<" && m[2][m[2].length-1] === ">" )
m[2] = m[2].substring( 1, m[2].length - 1 );
var ref = attrs.references[ m[1].toLowerCase() ] = {
href: m[2]
};
if ( m[4] !== undefined )
ref.title = m[4];
else if ( m[5] !== undefined )
ref.title = m[5];
}
Gruber.inline["**"] = strong_em("strong", "**");
Gruber.inline["__"] = strong_em("strong", "__");
Gruber.inline["*"] = strong_em("em", "*");
Gruber.inline["_"] = strong_em("em", "_");
Markdown.dialects.Gruber = Gruber;
Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
return Gruber;
});
================================================
FILE: src/dialects/maruku.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define(['../markdown_helpers', './dialect_helpers', './gruber', '../parser'], function (MarkdownHelpers, DialectHelpers, Gruber, Markdown) {
var Maruku = DialectHelpers.subclassDialect( Gruber ),
extract_attr = MarkdownHelpers.extract_attr,
forEach = MarkdownHelpers.forEach;
Maruku.processMetaHash = function processMetaHash( meta_string ) {
var meta = split_meta_hash( meta_string ),
attr = {};
for ( var i = 0; i < meta.length; ++i ) {
// id: #foo
if ( /^#/.test( meta[ i ] ) )
attr.id = meta[ i ].substring( 1 );
// class: .foo
else if ( /^\./.test( meta[ i ] ) ) {
// if class already exists, append the new one
if ( attr["class"] )
attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
else
attr["class"] = meta[ i ].substring( 1 );
}
// attribute: foo=bar
else if ( /\=/.test( meta[ i ] ) ) {
var s = meta[ i ].split( /\=/ );
attr[ s[ 0 ] ] = s[ 1 ];
}
}
return attr;
};
function split_meta_hash( meta_string ) {
var meta = meta_string.split( "" ),
parts = [ "" ],
in_quotes = false;
while ( meta.length ) {
var letter = meta.shift();
switch ( letter ) {
case " " :
// if we're in a quoted section, keep it
if ( in_quotes )
parts[ parts.length - 1 ] += letter;
// otherwise make a new part
else
parts.push( "" );
break;
case "'" :
case '"' :
// reverse the quotes and move straight on
in_quotes = !in_quotes;
break;
case "\\" :
// shift off the next letter to be used straight away.
// it was escaped so we'll keep it whatever it is
letter = meta.shift();
/* falls through */
default :
parts[ parts.length - 1 ] += letter;
break;
}
}
return parts;
}
Maruku.block.document_meta = function document_meta( block ) {
// we're only interested in the first block
if ( block.lineNumber > 1 )
return undefined;
// document_meta blocks consist of one or more lines of `Key: Value\n`
if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) )
return undefined;
// make an attribute node if it doesn't exist
if ( !extract_attr( this.tree ) )
this.tree.splice( 1, 0, {} );
var pairs = block.split( /\n/ );
for ( var p in pairs ) {
var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
key = m[ 1 ].toLowerCase(),
value = m[ 2 ];
this.tree[ 1 ][ key ] = value;
}
// document_meta produces no content!
return [];
};
Maruku.block.block_meta = function block_meta( block ) {
// check if the last line of the block is an meta hash
var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
if ( !m )
return undefined;
// process the meta hash
var attr = this.dialect.processMetaHash( m[ 2 ] ),
hash;
// if we matched ^ then we need to apply meta to the previous block
if ( m[ 1 ] === "" ) {
var node = this.tree[ this.tree.length - 1 ];
hash = extract_attr( node );
// if the node is a string (rather than JsonML), bail
if ( typeof node === "string" )
return undefined;
// create the attribute hash if it doesn't exist
if ( !hash ) {
hash = {};
node.splice( 1, 0, hash );
}
// add the attributes in
for ( var a in attr )
hash[ a ] = attr[ a ];
// return nothing so the meta hash is removed
return [];
}
// pull the meta hash off the block and process what's left
var b = block.replace( /\n.*$/, "" ),
result = this.processBlock( b, [] );
// get or make the attributes hash
hash = extract_attr( result[ 0 ] );
if ( !hash ) {
hash = {};
result[ 0 ].splice( 1, 0, hash );
}
// attach the attributes to the block
for ( var a in attr )
hash[ a ] = attr[ a ];
return result;
};
Maruku.block.definition_list = function definition_list( block, next ) {
// one or more terms followed by one or more definitions, in a single block
var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
list = [ "dl" ],
i, m;
// see if we're dealing with a tight or loose block
if ( ( m = block.match( tight ) ) ) {
// pull subsequent tight DL blocks out of `next`
var blocks = [ block ];
while ( next.length && tight.exec( next[ 0 ] ) )
blocks.push( next.shift() );
for ( var b = 0; b < blocks.length; ++b ) {
var m = blocks[ b ].match( tight ),
terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
defns = m[ 2 ].split( /\n:\s+/ );
// print( uneval( m ) );
for ( i = 0; i < terms.length; ++i )
list.push( [ "dt", terms[ i ] ] );
for ( i = 0; i < defns.length; ++i ) {
// run inline processing over the definition
list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
}
}
}
else {
return undefined;
}
return [ list ];
};
// splits on unescaped instances of @ch. If @ch is not a character the result
// can be unpredictable
Maruku.block.table = function table ( block ) {
var _split_on_unescaped = function( s, ch ) {
ch = ch || '\\s';
if ( ch.match(/^[\\|\[\]{}?*.+^$]$/) )
ch = '\\' + ch;
var res = [ ],
r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
m;
while ( ( m = s.match( r ) ) ) {
res.push( m[1] );
s = m[2];
}
res.push(s);
return res;
};
var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
// find at least an unescaped pipe in each line
no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
i,
m;
if ( ( m = block.match( leading_pipe ) ) ) {
// remove leading pipes in contents
// (header and horizontal rule already have the leading pipe left out)
m[3] = m[3].replace(/^\s*\|/gm, '');
} else if ( ! ( m = block.match( no_leading_pipe ) ) ) {
return undefined;
}
var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
// remove trailing pipes, then split on pipes
// (no escaped pipes are allowed in horizontal rule)
m[2] = m[2].replace(/\|\s*$/, '').split('|');
// process alignment
var html_attrs = [ ];
forEach (m[2], function (s) {
if (s.match(/^\s*-+:\s*$/))
html_attrs.push({align: "right"});
else if (s.match(/^\s*:-+\s*$/))
html_attrs.push({align: "left"});
else if (s.match(/^\s*:-+:\s*$/))
html_attrs.push({align: "center"});
else
html_attrs.push({});
});
// now for the header, avoid escaped pipes
m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
for (i = 0; i < m[1].length; i++) {
table[1][1].push(['th', html_attrs[i] || {}].concat(
this.processInline(m[1][i].trim())));
}
// now for body contents
forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
var html_row = ['tr'];
row = _split_on_unescaped(row, '|');
for (i = 0; i < row.length; i++)
html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
table[2].push(html_row);
}, this);
return [table];
};
Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
if ( !out.length )
return [ 2, "{:" ];
// get the preceeding element
var before = out[ out.length - 1 ];
if ( typeof before === "string" )
return [ 2, "{:" ];
// match a meta hash
var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
// no match, false alarm
if ( !m )
return [ 2, "{:" ];
// attach the attributes to the preceeding element
var meta = this.dialect.processMetaHash( m[ 1 ] ),
attr = extract_attr( before );
if ( !attr ) {
attr = {};
before.splice( 1, 0, attr );
}
for ( var k in meta )
attr[ k ] = meta[ k ];
// cut out the string and replace it with nothing
return [ m[ 0 ].length, "" ];
};
Markdown.dialects.Maruku = Maruku;
Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
return Maruku;
});
================================================
FILE: src/markdown.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
// Include all our dependencies and return the resulting library.
define(['./parser', './markdown_helpers', './render_tree', './dialects/gruber', './dialects/maruku'], function(Markdown) {
return Markdown;
});
================================================
FILE: src/markdown_helpers.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define([], function (w) {
var MarkdownHelpers = {};
// For Spidermonkey based engines
function mk_block_toSource() {
return "Markdown.mk_block( " +
uneval(this.toString()) +
", " +
uneval(this.trailing) +
", " +
uneval(this.lineNumber) +
" )";
}
// node
function mk_block_inspect() {
var util = require("util");
return "Markdown.mk_block( " +
util.inspect(this.toString()) +
", " +
util.inspect(this.trailing) +
", " +
util.inspect(this.lineNumber) +
" )";
}
MarkdownHelpers.mk_block = function(block, trail, line) {
// Be helpful for default case in tests.
if ( arguments.length === 1 )
trail = "\n\n";
// We actually need a String object, not a string primitive
/* jshint -W053 */
var s = new String(block);
s.trailing = trail;
// To make it clear its not just a string
s.inspect = mk_block_inspect;
s.toSource = mk_block_toSource;
if ( line !== undefined )
s.lineNumber = line;
return s;
};
var isArray = MarkdownHelpers.isArray = Array.isArray || function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
// Don't mess with Array.prototype. Its not friendly
if ( Array.prototype.forEach ) {
MarkdownHelpers.forEach = function forEach( arr, cb, thisp ) {
return arr.forEach( cb, thisp );
};
}
else {
MarkdownHelpers.forEach = function forEach(arr, cb, thisp) {
for (var i = 0; i < arr.length; i++)
cb.call(thisp || arr, arr[i], i, arr);
};
}
MarkdownHelpers.isEmpty = function isEmpty( obj ) {
for ( var key in obj ) {
if ( hasOwnProperty.call( obj, key ) )
return false;
}
return true;
};
MarkdownHelpers.extract_attr = function extract_attr( jsonml ) {
return isArray(jsonml)
&& jsonml.length > 1
&& typeof jsonml[ 1 ] === "object"
&& !( isArray(jsonml[ 1 ]) )
? jsonml[ 1 ]
: undefined;
};
return MarkdownHelpers;
});
================================================
FILE: src/parser.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module) }
define(['./markdown_helpers', './core'], function(MarkdownHelpers, Markdown) {
// Imported functions
var mk_block = Markdown.mk_block = MarkdownHelpers.mk_block,
isArray = MarkdownHelpers.isArray;
/**
* parse( markdown, [dialect] ) -> JsonML
* - markdown (String): markdown string to parse
* - dialect (String | Dialect): the dialect to use, defaults to gruber
*
* Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
**/
Markdown.parse = function( source, dialect ) {
// dialect will default if undefined
var md = new Markdown( dialect );
return md.toTree( source );
};
/**
* count_lines( str ) -> count
* - str (String): String whose lines we want to count
*
* Counts the number of linebreaks in `str`
**/
function count_lines( str ) {
return str.split("\n").length - 1;
}
// Internal - split source into rough blocks
Markdown.prototype.split_blocks = function splitBlocks( input ) {
// Normalize linebreaks to \n.
input = input.replace(/\r\n?/g, "\n");
// Match until the end of the string, a newline followed by #, or two or more newlines.
// [\s\S] matches _anything_ (newline or space)
// [^] is equivalent but doesn't work in IEs.
var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
blocks = [],
m;
var line_no = 1;
if ( ( m = /^(\s*\n)/.exec(input) ) !== null ) {
// skip (but count) leading blank lines
line_no += count_lines( m[0] );
re.lastIndex = m[0].length;
}
while ( ( m = re.exec(input) ) !== null ) {
if (m[2] === "\n#") {
m[2] = "\n";
re.lastIndex--;
}
blocks.push( mk_block( m[1], m[2], line_no ) );
line_no += count_lines( m[0] );
}
return blocks;
};
/**
* Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
* - block (String): the block to process
* - next (Array): the following blocks
*
* Process `block` and return an array of JsonML nodes representing `block`.
*
* It does this by asking each block level function in the dialect to process
* the block until one can. Succesful handling is indicated by returning an
* array (with zero or more JsonML nodes), failure by a false value.
*
* Blocks handlers are responsible for calling [[Markdown#processInline]]
* themselves as appropriate.
*
* If the blocks were split incorrectly or adjacent blocks need collapsing you
* can adjust `next` in place using shift/splice etc.
*
* If any of this default behaviour is not right for the dialect, you can
* define a `__call__` method on the dialect that will get invoked to handle
* the block processing.
*/
Markdown.prototype.processBlock = function processBlock( block, next ) {
var cbs = this.dialect.block,
ord = cbs.__order__;
if ( "__call__" in cbs )
return cbs.__call__.call(this, block, next);
for ( var i = 0; i < ord.length; i++ ) {
//D:this.debug( "Testing", ord[i] );
var res = cbs[ ord[i] ].call( this, block, next );
if ( res ) {
if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) && ( typeof res[0] !== "string")) ) {
this.debug(ord[i], "didn't return proper JsonML");
}
return res;
}
}
// Uhoh! no match! Should we throw an error?
return [];
};
Markdown.prototype.processInline = function processInline( block ) {
return this.dialect.inline.__call__.call( this, String( block ) );
};
/**
* Markdown#toTree( source ) -> JsonML
* - source (String): markdown source to parse
*
* Parse `source` into a JsonML tree representing the markdown document.
**/
// custom_tree means set this.tree to `custom_tree` and restore old value on return
Markdown.prototype.toTree = function toTree( source, custom_root ) {
var blocks = source instanceof Array ? source : this.split_blocks( source );
// Make tree a member variable so its easier to mess with in extensions
var old_tree = this.tree;
try {
this.tree = custom_root || this.tree || [ "markdown" ];
blocks_loop:
while ( blocks.length ) {
var b = this.processBlock( blocks.shift(), blocks );
// Reference blocks and the like won't return any content
if ( !b.length )
continue blocks_loop;
this.tree.push.apply( this.tree, b );
}
return this.tree;
}
finally {
if ( custom_root )
this.tree = old_tree;
}
};
// Noop by default
Markdown.prototype.debug = function () {
var args = Array.prototype.slice.call( arguments);
args.unshift(this.debug_indent);
if ( typeof print !== "undefined" )
print.apply( print, args );
if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
console.log.apply( null, args );
};
Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
// Dont use /g regexps with this
var m,
b = block.valueOf();
while ( b.length && (m = re.exec(b) ) !== null ) {
b = b.substr( m[0].length );
cb.call(this, m);
}
return b;
};
// Build default order from insertion order.
Markdown.buildBlockOrder = function(d) {
var ord = [];
for ( var i in d ) {
if ( i === "__order__" || i === "__call__" )
continue;
ord.push( i );
}
d.__order__ = ord;
};
// Build patterns for inline matcher
Markdown.buildInlinePatterns = function(d) {
var patterns = [];
for ( var i in d ) {
// __foo__ is reserved and not a pattern
if ( i.match( /^__.*__$/) )
continue;
var l = i.replace( /([\\.*+?^$|()\[\]{}])/g, "\\$1" )
.replace( /\n/, "\\n" );
patterns.push( i.length === 1 ? l : "(?:" + l + ")" );
}
patterns = patterns.join("|");
d.__patterns__ = patterns;
//print("patterns:", uneval( patterns ) );
var fn = d.__call__;
d.__call__ = function(text, pattern) {
if ( pattern !== undefined )
return fn.call(this, text, pattern);
else
return fn.call(this, text, patterns);
};
};
return Markdown;
});
================================================
FILE: src/render_tree.js
================================================
if (typeof define !== 'function') { var define = require('amdefine')(module); }
define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) {
var extract_attr = MarkdownHelpers.extract_attr;
/**
* renderJsonML( jsonml[, options] ) -> String
* - jsonml (Array): JsonML array to render to XML
* - options (Object): options
*
* Converts the given JsonML into well-formed XML.
*
* The options currently understood are:
*
* - root (Boolean): wether or not the root node should be included in the
* output, or just its children. The default `false` is to not include the
* root itself.
*/
Markdown.renderJsonML = function( jsonml, options ) {
options = options || {};
// include the root element in the rendered output?
options.root = options.root || false;
jsonml = JSON.parse(JSON.stringify(jsonml)); // Clone to prevent mutation of original reference.
var content = [];
if ( options.root ) {
content.push( render_tree( jsonml ) );
}
else {
jsonml.shift(); // get rid of the tag
if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) )
jsonml.shift(); // get rid of the attributes
while ( jsonml.length )
content.push( render_tree( jsonml.shift() ) );
}
return content.join( "\n\n" );
};
/**
* toHTMLTree( markdown, [dialect] ) -> JsonML
* toHTMLTree( md_tree ) -> JsonML
* - markdown (String): markdown string to parse
* - dialect (String | Dialect): the dialect to use, defaults to gruber
* - md_tree (Markdown.JsonML): parsed markdown tree
*
* Turn markdown into HTML, represented as a JsonML tree. If a string is given
* to this function, it is first parsed into a markdown tree by calling
* [[parse]].
**/
Markdown.toHTMLTree = function toHTMLTree( input, dialect , options ) {
// convert string input to an MD tree
if ( typeof input === "string" )
input = this.parse( input, dialect );
// Now convert the MD tree to an HTML tree
// remove references from the tree
var attrs = extract_attr( input ),
refs = {};
if ( attrs && attrs.references )
refs = attrs.references;
var html = convert_tree_to_html( input, refs , options );
merge_text_nodes( html );
return html;
};
/**
* toHTML( markdown, [dialect] ) -> String
* toHTML( md_tree ) -> String
* - markdown (String): markdown string to parse
* - md_tree (Markdown.JsonML): parsed markdown tree
*
* Take markdown (either as a string or as a JsonML tree) and run it through
* [[toHTMLTree]] then turn it into a well-formated HTML fragment.
**/
Markdown.toHTML = function toHTML( source , dialect , options ) {
var input = this.toHTMLTree( source , dialect , options );
return this.renderJsonML( input );
};
function escapeHTML( text ) {
if (text && text.length > 0) {
return text.replace( /&/g, "&" )
.replace( /</g, "<" )
.replace( />/g, ">" )
.replace( /"/g, """ )
.replace( /'/g, "'" );
} else {
return "";
}
}
function render_tree( jsonml ) {
// basic case
if ( typeof jsonml === "string" )
return escapeHTML( jsonml );
var tag = jsonml.shift(),
attributes = {},
content = [];
if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) )
attributes = jsonml.shift();
while ( jsonml.length )
content.push( render_tree( jsonml.shift() ) );
var tag_attrs = "";
if (typeof attributes.src !== 'undefined') {
tag_attrs += ' src="' + escapeHTML( attributes.src ) + '"';
delete attributes.src;
}
for ( var a in attributes ) {
var escaped = escapeHTML( attributes[ a ]);
if (escaped && escaped.length) {
tag_attrs += " " + a + '="' + escaped + '"';
}
}
// be careful about adding whitespace here for inline elements
if ( tag === "img" || tag === "br" || tag === "hr" )
return "<"+ tag + tag_attrs + "/>";
else
return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
}
function convert_tree_to_html( tree, references, options ) {
var i;
options = options || {};
// shallow clone
var jsonml = tree.slice( 0 );
if ( typeof options.preprocessTreeNode === "function" )
jsonml = options.preprocessTreeNode(jsonml, references);
// Clone attributes if they exist
var attrs = extract_attr( jsonml );
if ( attrs ) {
jsonml[ 1 ] = {};
for ( i in attrs ) {
jsonml[ 1 ][ i ] = attrs[ i ];
}
attrs = jsonml[ 1 ];
}
// basic case
if ( typeof jsonml === "string" )
return jsonml;
// convert this node
switch ( jsonml[ 0 ] ) {
case "header":
jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
delete jsonml[ 1 ].level;
break;
case "bulletlist":
jsonml[ 0 ] = "ul";
break;
case "numberlist":
jsonml[ 0 ] = "ol";
break;
case "listitem":
jsonml[ 0 ] = "li";
break;
case "para":
jsonml[ 0 ] = "p";
break;
case "markdown":
jsonml[ 0 ] = "html";
if ( attrs )
delete attrs.references;
break;
case "code_block":
jsonml[ 0 ] = "pre";
i = attrs ? 2 : 1;
var code = [ "code" ];
code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
jsonml[ i ] = code;
break;
case "inlinecode":
jsonml[ 0 ] = "code";
break;
case "img":
jsonml[ 1 ].src = jsonml[ 1 ].href;
delete jsonml[ 1 ].href;
break;
case "linebreak":
jsonml[ 0 ] = "br";
break;
case "link":
jsonml[ 0 ] = "a";
break;
case "link_ref":
jsonml[ 0 ] = "a";
// grab this ref and clean up the attribute node
var ref = references[ attrs.ref ];
// if the reference exists, make the link
if ( ref ) {
delete attrs.ref;
// add in the href and title, if present
attrs.href = ref.href;
if ( ref.title )
attrs.title = ref.title;
// get rid of the unneeded original text
delete attrs.original;
}
// the reference doesn't exist, so revert to plain text
else {
return attrs.original;
}
break;
case "img_ref":
jsonml[ 0 ] = "img";
// grab this ref and clean up the attribute node
var ref = references[ attrs.ref ];
// if the reference exists, make the link
if ( ref ) {
delete attrs.ref;
// add in the href and title, if present
attrs.src = ref.href;
if ( ref.title )
attrs.title = ref.title;
// get rid of the unneeded original text
delete attrs.original;
}
// the reference doesn't exist, so revert to plain text
else {
return attrs.original;
}
break;
}
// convert all the children
i = 1;
// deal with the attribute node, if it exists
if ( attrs ) {
// if there are keys, skip over it
for ( var key in jsonml[ 1 ] ) {
i = 2;
break;
}
// if there aren't, remove it
if ( i === 1 )
jsonml.splice( i, 1 );
}
for ( ; i < jsonml.length; ++i ) {
jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
}
return jsonml;
}
// merges adjacent text nodes into a single node
function merge_text_nodes( jsonml ) {
// skip the tag name and attribute hash
var i = extract_attr( jsonml ) ? 2 : 1;
while ( i < jsonml.length ) {
// if it's a string check the next item too
if ( typeof jsonml[ i ] === "string" ) {
if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
// merge the second string into the first and remove it
jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
}
else {
++i;
}
}
// if it's not a string recurse
else {
merge_text_nodes( jsonml[ i ] );
++i;
}
}
}
return Markdown;
});
================================================
FILE: test/features/blockquotes/contains_code.json
================================================
["html",
["blockquote",
["p",
"There's a code block in here:"
],
["pre",
["code",
"SET foo = TRUE\n\nIF foo GOTO 10"
]
],
["p",
"Wasn't that nice?"
]
]
]
================================================
FILE: test/features/blockquotes/contains_code.text
================================================
> There's a code block in here:
>
> SET foo = TRUE
>
> IF foo GOTO 10
>
> Wasn't that nice?
================================================
FILE: test/features/blockquotes/lazy_wrapping.json
================================================
["html",
["blockquote",
["p",
"If you're too lazy\nto wrap your code nicely"
],
["p",
"This will still work"
]
]
]
================================================
FILE: test/features/blockquotes/lazy_wrapping.text
================================================
> If you're too lazy
to wrap your code nicely
> This will still work
================================================
FILE: test/features/blockquotes/leading_paras.json
================================================
["html",
["p",
"Amy wrote:"
],
["blockquote",
["p",
"No wai?"
]
],
["p",
"Bob wrote:"
],
["blockquote",
["p",
"Ya rly!"
]
]
]
================================================
FILE: test/features/blockquotes/leading_paras.text
================================================
Amy wrote:
> No wai?
Bob wrote:
> Ya rly!
================================================
FILE: test/features/blockquotes/nested.json
================================================
["html",
["blockquote",
["p",
"One"
],
["blockquote",
["p",
"Two"
]
],
["p",
"Three"
]
]
]
================================================
FILE: test/features/blockquotes/nested.text
================================================
> One
>
> > Two
>
> Three
================================================
FILE: test/features/blockquotes/simple.json
================================================
["html",
["blockquote",
["p",
"Blockquote"
]
]
]
================================================
FILE: test/features/blockquotes/simple.text
================================================
> Blockquote
================================================
FILE: test/features/blockquotes/spaceless.json
================================================
["html",
["blockquote",
["p",
"blockquote\nwithout spaces"
]
]
]
================================================
FILE: test/features/blockquotes/spaceless.text
================================================
>blockquote
>without spaces
================================================
FILE: test/features/blockquotes/spaces_before.json
================================================
["html",
["blockquote",
["p",
"evil"
]
]
]
================================================
FILE: test/features/blockquotes/spaces_before.text
================================================
> evil
================================================
FILE: test/features/blockquotes/threequotes.json
================================================
[ "html",
[ "blockquote",
[ "p", "this is" ],
[ "p", "three" ],
[ "p", "quotes" ]
]
]
================================================
FILE: test/features/blockquotes/threequotes.text
================================================
> this is
> three
> quotes
================================================
FILE: test/features/code/blank_lines.json
================================================
["html",
["p",
"This block is composed of three lines:"
],
["pre",
["code",
"one\n\nthree"
]
],
["p",
"This block is composed of 5"
],
["pre",
["code",
"one\n\n\nfour"
]
],
["p",
"This block is composed of 2"
],
["pre",
["code",
"two"
]
]
]
================================================
FILE: test/features/code/blank_lines.text
================================================
This block is composed of three lines:
one
three
This block is composed of 5
one
four
This block is composed of 2
two
================================================
FILE: test/features/code/block.json
================================================
["html",
["p",
"Here is an example of AppleScript:"
],
["pre",
["code",
"tell application \"Foo\"\n beep\nend tell\n\ttab"
]
]
]
================================================
FILE: test/features/code/block.text
================================================
Here is an example of AppleScript:
tell application "Foo"
beep
end tell
tab
================================================
FILE: test/features/code/embedded_backtick.json
================================================
["html",
["p",
"This is a ",
["code",
"code span with an `embedded` backtick"],
"."
]
]
================================================
FILE: test/features/code/embedded_backtick.text
================================================
This is a ``code span with an `embedded` backtick``.
================================================
FILE: test/features/code/horizontal_rules.json
================================================
["html",
["pre",
["code",
"fsfsfsf\n* * *\n\n***\n\n*****\n\n- - -\n\n---------------------------------------"
]
]
]
================================================
FILE: test/features/code/horizontal_rules.text
================================================
fsfsfsf
* * *
***
*****
- - -
---------------------------------------
================================================
FILE: test/features/code/in_lists.json
================================================
["html",
["ul",
["li",
["p",
"Loose list"
],
["pre",
["code",
"some code\n\nmore code"
]
]
]
]
]
================================================
FILE: test/features/code/in_lists.text
================================================
* Loose list
some code
more code
================================================
FILE: test/features/code/inline.json
================================================
["html",
["p",
["code",
"This"
],
" is a code span."
]
]
================================================
FILE: test/features/code/inline.text
================================================
`This` is a code span.
================================================
FILE: test/features/code/inline_multiline.json
================================================
["html",
["p",
"foo ",
["code",
"code\ncode"
],
" bar"
]
]
================================================
FILE: test/features/code/inline_multiline.text
================================================
foo `code
code` bar
================================================
FILE: test/features/code/trailing_para.json
================================================
["html",
["p",
"Paragraph above"
],
["pre",
["code",
"Code block"
]
],
["p",
"Paragraph below"
]
]
================================================
FILE: test/features/code/trailing_para.text
================================================
Paragraph above
Code block
Paragraph below
================================================
FILE: test/features/code/with_greater_than.json
================================================
["html",
["pre",
["code", "> meep"]
]
]
================================================
FILE: test/features/code/with_greater_than.text
================================================
> meep
================================================
FILE: test/features/definition_lists/inline.json
================================================
["html",
["dl",
["dt",
"a term"
],
["dd",
["em",
"emphasised"
],
" definition."
],
["dt",
"another term"
],
["dd",
["strong",
"strong"
],
" definition."
]
]
]
================================================
FILE: test/features/definition_lists/inline.text
================================================
a term
: *emphasised* definition.
another term
: **strong** definition.
================================================
FILE: test/features/definition_lists/long.json
================================================
["html",
["dl",
["dt",
"first term"
],
["dd",
"the quick brown fox jumps\nover the lazy dog"
],
["dt",
"second term"
],
["dd",
"pack my box with five\ndozen liquor jugs"
]
]
]
================================================
FILE: test/features/definition_lists/long.text
================================================
first term
: the quick brown fox jumps
over the lazy dog
second term
: pack my box with five
dozen liquor jugs
================================================
FILE: test/features/definition_lists/multiple_definitions.json
================================================
["html",
["dl",
["dt",
"fruit"
],
["dd",
"apple"
],
["dd",
"banana"
],
["dd",
"pear"
],
["dt",
"animal"
],
["dd",
"cow"
],
["dd",
"duck"
],
["dd",
"horse"
]
]
]
================================================
FILE: test/features/definition_lists/multiple_definitions.text
================================================
fruit
: apple
: banana
: pear
animal
: cow
: duck
: horse
================================================
FILE: test/features/definition_lists/multiple_terms.json
================================================
["html",
["dl",
["dt",
"fruit"
],
["dt",
"vegetable"
],
["dd",
"tomato"
],
["dt",
"animal"
],
["dt",
"mineral"
],
["dd",
"pet rock"
]
]
]
================================================
FILE: test/features/definition_lists/multiple_terms.text
================================================
fruit
vegetable
: tomato
animal
mineral
: pet rock
================================================
FILE: test/features/definition_lists/tight.json
================================================
["html",
["dl",
["dt",
"one"
],
["dd",
"alpha"
],
["dt",
"two"
],
["dd",
"beta"
],
["dt",
"three"
],
["dd",
"gamma"
]
]
]
================================================
FILE: test/features/definition_lists/tight.text
================================================
one
: alpha
two
: beta
three
: gamma
================================================
FILE: test/features/emphasis/multiple_lines.json
================================================
["html",
["p",
"You can ",
["em",
"start emphasis on one line,\nand finish it"
],
" on another."
]
]
================================================
FILE: test/features/emphasis/multiple_lines.text
================================================
You can *start emphasis on one line,
and finish it* on another.
================================================
FILE: test/features/emphasis/nested.json
================================================
["html",
["p",
"You can ",
["strong",
"nest ",
["em",
"em"
],
" inside strong"
],
"."
],
["p",
"You can ",
["em",
"nest ",
["strong",
"strong"
],
" inside em"
],
"."
]
]
================================================
FILE: test/features/emphasis/nested.text
================================================
You can **nest *em* inside strong**.
You can *nest **strong** inside em*.
================================================
FILE: test/features/emphasis/simple.json
================================================
["html",
["p",
"Emphasis can be ",
["em",
"weak"
],
" or ",
["strong",
"strong"
],
"."
],
["p",
"It can ",
["em",
"even"
],
" use ",
["strong",
"underscores"
],
"."
]
]
================================================
FILE: test/features/emphasis/simple.text
================================================
Emphasis can be *weak* or **strong**.
It can _even_ use __underscores__.
================================================
FILE: test/features/headers/atx.json
================================================
["html",
["h1",
"One"
],
["h2",
"Two"
],
["h3",
"Three"
],
["h4",
"Four"
],
["h5",
"Five"
],
["h6",
"Six"
]
]
================================================
FILE: test/features/headers/atx.text
================================================
# One
## Two
### Three
#### Four
##### Five
###### Six
================================================
FILE: test/features/headers/atx_closing_hashes.json
================================================
["html",
["h1",
"One"
],
["h2",
"Two"
],
["h3",
"Three"
]
]
================================================
FILE: test/features/headers/atx_closing_hashes.text
================================================
# One #
## Two #####
### Three ##
================================================
FILE: test/features/headers/inline.json
================================================
["html",
["h2",
["strong", "Bold"]
]
]
================================================
FILE: test/features/headers/inline.text
================================================
**Bold**
--------
================================================
FILE: test/features/headers/setext.json
================================================
["html",
["h1",
"One"
],
["h2",
"Two"
]
]
================================================
FILE: test/features/headers/setext.text
================================================
One
===
Two
---
================================================
FILE: test/features/headers/trailing_paras.json
================================================
["html",
["h1",
"Header"
],
["p",
"Paragraph"
],
["h2",
"Header"
],
["p",
"Paragraph"
],
["h3",
"Header"
],
["p",
"Paragraph"
]
]
================================================
FILE: test/features/headers/trailing_paras.text
================================================
Header
======
Paragraph
Header
------
Paragraph
### Header
Paragraph
================================================
FILE: test/features/horizontal_rules/abutting_blocks.json
================================================
["html",
["p",
"para"
],
["hr"],
["ul",
["li",
"list"
]
],
["hr"],
["ul",
["li",
"list before para"
]
],
["p",
" para"
],
["hr"],
["blockquote",
["p",
"blockquote"
]
]
]
================================================
FILE: test/features/horizontal_rules/abutting_blocks.text
================================================
para
***
* list
- - -
* list before para
para
- - -
> blockquote
================================================
FILE: test/features/horizontal_rules/dashes.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/dashes.text
================================================
---
================================================
FILE: test/features/horizontal_rules/front_matter.json
================================================
["html",
["hr"],
["p",
"layout: post\ntitle: A title"
],
["hr"],
["p",
"Pack my box with five dozen liquor jugs."
]
]
================================================
FILE: test/features/horizontal_rules/front_matter.text
================================================
---
layout: post
title: A title
---
Pack my box with five dozen liquor jugs.
================================================
FILE: test/features/horizontal_rules/leading_spaces.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/leading_spaces.text
================================================
* * *
================================================
FILE: test/features/horizontal_rules/long.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/long.text
================================================
*********************
================================================
FILE: test/features/horizontal_rules/long_loose.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/long_loose.text
================================================
* * * * * * * * * * *
================================================
FILE: test/features/horizontal_rules/loose_dashes.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/loose_dashes.text
================================================
- - -
================================================
FILE: test/features/horizontal_rules/loose_stars.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/loose_stars.text
================================================
* * *
================================================
FILE: test/features/horizontal_rules/loose_underscores.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/loose_underscores.text
================================================
_ _ _
================================================
FILE: test/features/horizontal_rules/stars.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/stars.text
================================================
***
================================================
FILE: test/features/horizontal_rules/underscores.json
================================================
["html",
["hr"]
]
================================================
FILE: test/features/horizontal_rules/underscores.text
================================================
___
================================================
FILE: test/features/images/basic.json
================================================
["html",
["p",
["img", {
"src": "/path/to/img.jpg",
"alt": "Alt text"
} ]
]
]
================================================
FILE: test/features/images/basic.text
================================================

================================================
FILE: test/features/images/crotcheted_url.json
================================================
["html",
["p",
["img", {
"src": "/url/",
"alt": "alt text"
} ]
]
]
================================================
FILE: test/features/images/crotcheted_url.text
================================================

================================================
FILE: test/features/images/crotcheted_url_with_title.json
================================================
["html",
["p",
["img", {
"src": "/url/",
"alt": "alt text",
"title": "with a title"
} ]
]
]
================================================
FILE: test/features/images/crotcheted_url_with_title.text
================================================

================================================
FILE: test/features/images/empty.json
================================================
["html",
["p",
["img", {
"src": "",
"alt": "Empty"
} ]
]
]
================================================
FILE: test/features/images/empty.text
================================================
![Empty]()
================================================
FILE: test/features/images/incomplete_image.json
================================================
[ "html",
[ "p",
"](https://link-url)
================================================
FILE: test/features/images/ref.json
================================================
["html",
["p",
["img", {
"src": "/path/to/img.jpg",
"alt": "Alt text"
} ]
]
]
================================================
FILE: test/features/images/ref.text
================================================
![Alt text] [img]
[img]: /path/to/img.jpg
================================================
FILE: test/features/images/spaces_in_href.json
================================================
["html",
["p",
["img", {
"src": "path to img.jpg",
"alt": "Alt text"
} ]
]
]
================================================
FILE: test/features/images/spaces_in_href.text
================================================

================================================
FILE: test/features/images/spaces_round_title.json
================================================
["html",
["p",
["img", {
"src": "/url/",
"alt": "alt text",
"title": "title has spaces afterward"
} ]
]
]
================================================
FILE: test/features/images/spaces_round_title.text
================================================

================================================
FILE: test/features/images/title.json
================================================
["html",
["p",
["img", {
"src": "/path/to/img.jpg",
"alt": "Alt text",
"title": "Optional title"
} ]
]
]
================================================
FILE: test/features/images/title.text
================================================

================================================
FILE: test/features/linebreaks/simple.json
================================================
["html",
["p",
"The quick brown fox",
["br"],
"jumps over the lazy dog."
]
]
================================================
FILE: test/features/linebreaks/simple.text
================================================
The quick brown fox
jumps over the lazy dog.
================================================
FILE: test/features/links/apostrophe.json
================================================
["html",
["p",
["a",
{ "href" : "http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.3" },
"Postgres 9.3"
]
]
]
================================================
FILE: test/features/links/apostrophe.text
================================================
[Postgres 9.3](http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.3)
================================================
FILE: test/features/links/autolink_email.json
================================================
["html",
["p",
"Email addresses written like ",
["a",
{ "href" : "mailto:bill@microsoft.com" },
"bill@microsoft.com"
],
" get autolinkified."
]
]
================================================
FILE: test/features/links/autolink_email.text
================================================
Email addresses written like <bill@microsoft.com> get autolinkified.
================================================
FILE: test/features/links/autolink_in_code.json
================================================
["html",
["p",
"Autolinks don't happen inside code: ",
["code",
"<http://google.com>"
]
]
]
================================================
FILE: test/features/links/autolink_in_code.text
================================================
Autolinks don't happen inside code: `<http://google.com>`
================================================
FILE: test/features/links/autolink_url.json
================================================
["html",
["p",
"URLs like ",
["a",
{ "href" : "http://google.com" },
"http://google.com"
],
" get autolinkified."
]
]
================================================
FILE: test/features/links/autolink_url.text
================================================
URLs like <http://google.com> get autolinkified.
================================================
FILE: test/features/links/broken_brackets.json
================================================
["html",
["p", "[[][]"]
]
================================================
FILE: test/features/links/broken_brackets.text
================================================
[[][]
================================================
FILE: test/features/links/broken_link.json
================================================
["html",
["p", "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]"]
]
================================================
FILE: test/features/links/broken_link.text
================================================
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]
================================================
FILE: test/features/links/case_insensitive.json
================================================
["html",
["p",
"This is ",
["a",
{ "href" : "http://google.com" },
"google"
],
". ",
["a",
{ "href" : "http://google.com" },
"Google"
],
" and ",
["a",
{ "href" : "http://google.com" },
"this"
],
" are the same thing too"
]
]
================================================
FILE: test/features/links/case_insensitive.text
================================================
This is [google]. [Google] and [this][GoOgLe] are the same thing too
[GOOGLE]: http://google.com
================================================
FILE: test/features/links/escaped_broken_link.json
================================================
["html",
["p", "[][][][][][][][][][][][][][][][][][][][][]"]
]
================================================
FILE: test/features/links/escaped_broken_link.text
================================================
[\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\][\]
================================================
FILE: test/features/links/implicit.json
================================================
["html",
["p",
"These ",
["a",
{ "href" : "http://links.com" },
"links"
],
" use ",
["a",
{ "href" : "http://implicit.com" },
"implicit"
],
" references."
]
]
================================================
FILE: test/features/links/implicit.text
================================================
These [links][] use [implicit] references.
[links]: http://links.com
[implicit]: http://implicit.com
================================================
FILE: test/features/links/in_blockquotes.json
================================================
["html",
["blockquote",
["p",
"Let's fork this repo!"
],
["p",
"[markdown][]"
]
]
]
================================================
FILE: test/features/links/in_blockquotes.text
================================================
> Let's fork this repo!
>
> [markdown][]
>
> [markdown]: https://github.com/evilstreak/markdown-js
================================================
FILE: test/features/links/in_brackets.json
================================================
["html",
["p",
"Lorem ipsum (",
["a", {"href": "http://www.lipsum.com/"}, "lorem ipsum"],
") dolar sit amut"
],
["p",
"(",
["a", {"href": "/url()((test))"}, "Inline link"],
")"
]
]
================================================
FILE: test/features/links/in_brackets.text
================================================
Lorem ipsum ([lorem ipsum](http://www.lipsum.com/)) dolar sit amut
([Inline link](/url()((test))))
================================================
FILE: test/features/links/inline.json
================================================
["html",
["p",
"An ",
["a",
{ "href" : "http://inline.com" },
"inline"
],
" link."
]
]
================================================
FILE: test/features/links/inline.text
================================================
An [inline](http://inline.com) link.
================================================
FILE: test/features/links/inline_with_newline.json
================================================
["html",
["p",
"An ",
["a",
{ "href" : "http://inline.com" },
"inline\nlink"
],
" with a newline."
]
]
================================================
FILE: test/features/links/inline_with_newline.text
================================================
An [inline
link](http://inline.com) with a newline.
================================================
FILE: test/features/links/inline_with_title.json
================================================
["html",
["p",
"An ",
["a",
{ "href" : "http://inline.com",
"title" : "le title" },
"inline link"
],
" with a title."
]
]
================================================
FILE: test/features/links/inline_with_title.text
================================================
An [inline link](http://inline.com "le title") with a title.
================================================
FILE: test/features/links/missing_references.json
================================================
["html",
["p",
"Link with [missing][id] reference"
],
["p",
"Link with [empty][] reference"
],
["p",
"Link with [inferred] reference"
]
]
================================================
FILE: test/features/links/missing_references.text
================================================
Link with [missing][id] reference
Link with [empty][] reference
Link with [inferred] reference
================================================
FILE: test/features/links/no_closing.json
================================================
["html",
["p",
"[[1]"
]
]
================================================
FILE: test/features/links/no_closing.text
================================================
[[1]
================================================
FILE: test/features/links/parens_escaped_inline.json
================================================
["html",
["p",
["a",
{ "href": "/url(test)",
"title": "title" },
"Inline link"
],
" with escaped parens."
]
]
================================================
FILE: test/features/links/parens_escaped_inline.text
================================================
[Inline link](/url\(test\) "title") with escaped parens.
================================================
FILE: test/features/links/parens_inline.json
================================================
["html",
["p",
["a",
{ "href": "/url(test)",
"title": "title" },
"Inline link"
],
" with non-escaped parens."
]
]
================================================
FILE: test/features/links/parens_inline.text
================================================
[Inline link](/url(test) "title") with non-escaped parens.
================================================
FILE: test/features/links/parens_reference.json
================================================
["html",
["p",
["a",
{ "href": "/url(test)",
"title": "title" },
"Reference link"
],
" with non-escaped parens."
]
]
================================================
FILE: test/features/links/parens_reference.text
================================================
[Reference link][1] with non-escaped parens.
[1]: /url(test) "title"
================================================
FILE: test/features/links/ref_reuse.json
================================================
["html",
["p",
"Two ",
["a",
{ "href" : "http://google.com" },
"links"
],
", one ",
["a",
{ "href" : "http://google.com" },
"ref"
]
]
]
================================================
FILE: test/features/links/ref_reuse.text
================================================
Two [links][id], one [ref][id]
[id]: http://google.com
================================================
FILE: test/features/links/ref_with_image_ref.json
================================================
["html",
["p",
["a",
{"href": "http://link_url"},
["img",
{"src": "http://image_url", "alt": "alt text"}
]
]
]
]
================================================
FILE: test/features/links/ref_with_image_ref.text
================================================
[![alt text][id_2]][id_1]
[id_1]: http://link_url
[id_2]: http://image_url
================================================
FILE: test/features/links/reference.json
================================================
["html",
["p",
"A ",
["a",
{ "href" : "http://reference.com" },
"link using a reference"
],
"."
]
]
================================================
FILE: test/features/links/reference.text
================================================
A [link using a reference][1].
[1]: http://reference.com
================================================
FILE: test/features/links/reference_missing.json
================================================
["html",
["p",
["a",
{ "href" : "http://example.com" },
"hi"
]
],
["ul", ["li"]]
]
================================================
FILE: test/features/links/reference_missing.text
================================================
[hi][link]
- [link]: http://example.com
================================================
FILE: test/features/links/reference_with_newline.json
================================================
["html",
["p",
"This one has a ",
["a",
{ "href" : "/foo" },
"line\nbreak"
],
"."
]
]
================================================
FILE: test/features/links/reference_with_newline.text
================================================
This one has a [line
break].
[line break]: /foo
================================================
FILE: test/features/links/reference_with_newline_and_space.json
================================================
["html",
["p",
"This one has a ",
["a",
{ "href" : "/foo" },
"line \nbreak"
],
"."
]
]
================================================
FILE: test/features/links/reference_with_newline_and_space.text
================================================
This one has a [line
break].
[line break]: /foo
================================================
FILE: test/features/links/reference_with_quote.json
================================================
["html",
["p",
"Foo ", [ "a", {"href": "/url/", "title": "Title with \"quotes\" inside"}, "bar" ], "."
]
]
================================================
FILE: test/features/links/reference_with_quote.text
================================================
Foo [bar][].
[bar]: /url/ "Title with "quotes" inside"
================================================
FILE: test/features/links/reference_with_space.json
================================================
["html",
["p",
"A ",
["a",
{ "href" : "http://reference.com" },
"link using a reference"
],
" separated by a space."
]
]
================================================
FILE: test/features/links/reference_with_space.text
================================================
A [link using a reference] [1] separated by a space.
[1]: http://reference.com
================================================
FILE: test/features/links/spaces_in_url.json
================================================
["html",
["p",
["a",
{ "href" : "Link to file/Lorem Ipsum.txt", "title" : "Alt2" },
"link text"
]
]
]
================================================
FILE: test/features/links/spaces_in_url.text
================================================
[link text](Link to file/Lorem Ipsum.txt "Alt2")
================================================
FILE: test/features/lists/bullet_types.json
================================================
["html",
["p",
"Stars"
],
["ul",
["li",
"star"
]
],
["p",
"Dashes"
],
["ul",
["li",
"dash"
]
],
["p",
"Pluses"
],
["ul",
["li",
"plus"
]
]
]
================================================
FILE: test/features/lists/bullet_types.text
================================================
Stars
* star
Dashes
- dash
Pluses
+ plus
================================================
FILE: test/features/lists/hr_abutting.json
================================================
["html",
["ul",
[ "li", "foo" ],
[ "li", "bar" ]
],
["hr"],
["p", "after"]
]
================================================
FILE: test/features/lists/hr_abutting.text
================================================
* foo
* bar
* * *
after
================================================
FILE: test/features/lists/hr_inside.json
================================================
["html",
["ul",
[ "li",
["p", "before"],
["hr"],
["p", "after"]
]
]
]
================================================
FILE: test/features/lists/hr_inside.text
================================================
* before
- - - -
after
================================================
FILE: test/features/lists/lazy_wrapping.json
================================================
["html",
["ul",
["li",
"If you're too\nlazy to wrap your"
],
["li",
"Lists nicely, this\nwill still work"
]
]
]
================================================
FILE: test/features/lists/lazy_wrapping.text
================================================
* If you're too
lazy to wrap your
* Lists nicely, this
will still work
================================================
FILE: test/features/lists/leading_whitespace.json
================================================
["html",
["ul",
["li",
"white"
],
["li",
"space"
]
]
]
================================================
FILE: test/features/lists/leading_whitespace.text
================================================
* white
* space
================================================
FILE: test/features/lists/loose.json
================================================
["html",
["ul",
["li",
["p",
"the quick brown fox jumps\nover the lazy dog"
]
],
["li",
["p",
"pack my box with five\ndozen liquor jugs"
],
["p",
"this item has a\nsecond paragraph"
]
],
["li",
["p",
"this item has\nonly one paragraph"
]
]
]
]
================================================
FILE: test/features/lists/loose.text
================================================
* the quick brown fox jumps
over the lazy dog
* pack my box with five
dozen liquor jugs
this item has a
second paragraph
* this item has
only one paragraph
================================================
FILE: test/features/lists/loose_with_inline.json
================================================
["html",
["ul",
["li",
["p",
"List item ",
["em",
"ending"
],
"\nwith ",
["em",
"emphasis"
],
"."
]
],
["li",
["p",
"List item\nwith ",
["strong",
"strong emphasis"
],
"."
]
],
["li",
["p",
"List item\nwith ",
["a",
{ "href" : "http://google.com" },
"a link"
],
"."
]
]
]
]
================================================
FILE: test/features/lists/loose_with_inline.text
================================================
* List item _ending_
with _emphasis_.
* List item
with **strong emphasis**.
* List item
with [a link](http://google.com).
================================================
FILE: test/features/lists/multiline_inline.json
================================================
["html",
["ul",
["li",
"List items can have ",
[ "em", "inline content\nthat spans multiple lines" ],
". Pain"
]
]
]
================================================
FILE: test/features/lists/multiline_inline.text
================================================
* List items can have *inline content
that spans multiple lines*. Pain
================================================
FILE: test/features/lists/nested.json
================================================
["html",
["ol",
["li",
"one",
["ul",
["li",
"alpha",
["ul",
["li",
"almond"
],
["li",
"brazil"
]
]
],
["li",
"beta",
["ul",
["li",
"cashew"
]
]
]
]
],
["li",
"two"
],
["li",
"three",
["ul",
["li",
"gamma"
]
]
]
]
]
================================================
FILE: test/features/lists/nested.text
================================================
1. one
* alpha
- almond
- brazil
* beta
- cashew
2. two
3. three
* gamma
================================================
FILE: test/features/lists/nested_para.json
================================================
["html",
["ol",
["li", ["p", "First"] ],
["li",
["p", "Second:"],
["ul",
["li", "Fee"],
["li", "Fie"],
["li", "Foe"]
]
],
["li", ["p", "Third"]]
]
]
================================================
FILE: test/features/lists/nested_para.text
================================================
1. First
2. Second:
* Fee
* Fie
* Foe
3. Third
================================================
FILE: test/features/lists/numeric.json
================================================
["html",
["ol",
["li",
"one"
],
["li",
"two"
],
["li",
"three"
]
]
]
================================================
FILE: test/features/lists/numeric.text
================================================
1. one
2. two
3. three
================================================
FILE: test/features/lists/quote_inside.json
================================================
["html",
["ol",
[ "li",
"bar",
["blockquote", ["p", "this should go under #1"]]
]
]
]
================================================
FILE: test/features/lists/quote_inside.text
================================================
1. bar
> this should go under #1
================================================
FILE: test/features/lists/references.json
================================================
["html",
["ul",
["li",
["a", {"href": "http://eviltrout.com"}, "Evil Trout"]
]
]
]
================================================
FILE: test/features/lists/references.text
================================================
* [Evil Trout][1]
[1]: http://eviltrout.com
================================================
FILE: test/features/lists/tight.json
================================================
["html",
["ul",
["li",
"alpha"
],
["li",
"beta"
],
["li",
"gamma"
]
]
]
================================================
FILE: test/features/lists/tight.text
================================================
* alpha
* beta
* gamma
================================================
FILE: test/features/meta/attribute.json
================================================
["html",
["p",
{ "foo" : "bar" },
"A paragraph with an\narbitrary attribute."
]
]
================================================
FILE: test/features/meta/attribute.text
================================================
A paragraph with an
arbitrary attribute.
{: foo=bar}
================================================
FILE: test/features/meta/class.json
================================================
["html",
["p",
{ "class" : "para" },
"This is a paragraph\nwith an ID."
]
]
================================================
FILE: test/features/meta/class.text
================================================
This is a paragraph
with an ID.
{: .para}
================================================
FILE: test/features/meta/code.json
================================================
["html",
["pre",
{ "foo" : "bar" },
["code",
"A pre with an\narbitrary attribute."
]
]
]
================================================
FILE: test/features/meta/code.text
================================================
A pre with an
arbitrary attribute.
{: foo=bar}
================================================
FILE: test/features/meta/document.json
================================================
["html",
{
"key" : "value",
"anotherkey" : "another value"
},
["p",
"A regular paragraph"
]
]
================================================
FILE: test/features/meta/document.text
================================================
Key: value
AnotherKey: another value
A regular paragraph
================================================
FILE: test/features/meta/id.json
================================================
["html",
["p",
{ "id" : "para" },
"This is a paragraph\nwith an ID."
]
]
================================================
FILE: test/features/meta/id.text
================================================
This is a paragraph
with an ID.
{: #para}
================================================
FILE: test/features/meta/inline.json
================================================
["html",
["p",
"An ",
["em",
{ "class" : "foo" },
"em"
],
" and ",
["strong",
{ "class" : "bar" },
"strong"
],
"\nwith attached attributes."
]
]
================================================
FILE: test/features/meta/inline.text
================================================
An *em*{: .foo} and **strong**{: .bar}
with attached attributes.
================================================
FILE: test/features/meta/inner_whitespace.json
================================================
["html",
["p",
{ "id" : "none" },
"We can have no whitespace"
],
["p",
{ "id" : "one" },
"Or a single whitespace"
],
["p",
{ "id" : "lots" },
"And even lots of whitespace"
]
]
================================================
FILE: test/features/meta/inner_whitespace.text
================================================
We can have no whitespace
{:#none}
Or a single whitespace
{: #one }
And even lots of whitespace
{: #lots }
================================================
FILE: test/features/meta/leading_whitespace.json
================================================
["html",
["p",
{ "id" : "zero" },
"Zero"
],
["p",
{ "id" : "one" },
"One"
],
["p",
{ "id" : "two" },
"Two"
],
["p",
{ "id" : "three" },
"Three"
],
["p",
"Four\n {: #four}"
]
]
================================================
FILE: test/features/meta/leading_whitespace.text
================================================
Zero
{: #zero}
One
{: #one}
Two
{: #two}
Three
{: #three}
Four
{: #four}
================================================
FILE: test/features/meta/list.json
================================================
["html",
["ul",
{ "id" : "list" },
["li",
"here's a\nloose list"
],
["li",
"it might confuse the\nblock_meta routine"
]
]
]
================================================
FILE: test/features/meta/list.text
================================================
* here's a
loose list
* it might confuse the
block_meta routine
{: #list}
================================================
FILE: test/features/meta/list.todo
================================================
================================================
FILE: test/features/meta/multiple_classes.json
================================================
["html",
["p",
{ "class" : "foo bar" },
"Here's a paragraph and\nan ",
["em",
{ "class" : "foo bar" },
"em"
],
"\nwith multiple classes"
]
]
================================================
FILE: test/features/meta/multiple_classes.text
================================================
Here's a paragraph and
an *em*{: .foo .bar}
with multiple classes
{: .foo .bar}
================================================
FILE: test/features/meta/quoted.json
================================================
["html",
["p",
{ "foo" : "bar baz" },
"A paragraph with a\nquoted attribute."
]
]
================================================
FILE: test/features/meta/quoted.text
================================================
A paragraph with a
quoted attribute.
{: foo="bar baz"}
================================================
FILE: test/features/tables/align.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
{ "align": "left" },
"#"
],
[ "th",
{ "align": "center" },
"Item"
],
[ "th",
{ "align": "right" },
"Value"
]
]
],
[ "tbody",
[ "tr",
[ "td",
{ "align": "left" },
"1"
],
[ "td",
{ "align": "center" },
"Computer"
],
[ "td",
{ "align": "right" },
"$1600"
]
],
[ "tr",
[ "td",
{ "align": "left" },
"2"
],
[ "td",
{ "align": "center" },
"Phone"
],
[ "td",
{ "align": "right" },
"$12"
]
],
[ "tr",
[ "td",
{ "align": "left" },
"3"
],
[ "td",
{ "align": "center" },
"Pipe"
],
[ "td",
{ "align": "right" },
"$1"
]
]
]
]
]
================================================
FILE: test/features/tables/align.text
================================================
| # | Item | Value |
| :- | :-------: | -----:|
| 1 | Computer | $1600 |
| 2 | Phone | $12 |
| 3 | Pipe | $1 |
================================================
FILE: test/features/tables/compact.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
{ "align": "left" },
"#"
],
[ "th",
{ "align": "center" },
"Item"
],
[ "th",
{ "align": "right" },
"Value"
]
]
],
[ "tbody",
[ "tr",
[ "td",
{ "align": "left" },
"1"
],
[ "td",
{ "align": "center" },
"Computer"
],
[ "td",
{ "align": "right" },
"$1600"
]
],
[ "tr",
[ "td",
{ "align": "left" },
"2"
],
[ "td",
{ "align": "center" },
"Phone"
],
[ "td",
{ "align": "right" },
"$12"
]
],
[ "tr",
[ "td",
{ "align": "left" },
"3"
],
[ "td",
{ "align": "center" },
"Pipe"
],
[ "td",
{ "align": "right" },
"$1"
]
]
]
]
]
================================================
FILE: test/features/tables/compact.text
================================================
#|Item|Value
:-|:-:|-:
1|Computer|$1600
2|Phone|$12
3|Pipe|$1
================================================
FILE: test/features/tables/inline_formatting.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
"Function name"
],
[ "th",
"Description"
]
]
],
[ "tbody",
[ "tr",
[ "td",
[ "code",
"help()"
]
],
[ "td",
"Display the help window."
]
],
[ "tr",
[ "td",
[ "code",
"destroy()"
]
],
[ "td",
[ "strong",
"Destroy your computer!"
]
]
]
]
]
]
================================================
FILE: test/features/tables/inline_formatting.text
================================================
| Function name | Description |
| ------------- | ------------------------------ |
| `help()` | Display the help window. |
| `destroy()` | **Destroy your computer!** |
================================================
FILE: test/features/tables/pipe_escape.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
"a|b"
],
[ "th",
"c"
]
]
],
[ "tbody",
[ "tr",
[ "td",
"1"
],
[ "td",
"2|3"
]
],
[ "tr",
[ "td",
"4|5"
],
[ "td",
"6"
]
]
]
]
]
================================================
FILE: test/features/tables/pipe_escape.text
================================================
| a\|b | c |
| -----|------|
| 1 | 2\|3 |
| 4\|5 | 6 |
================================================
FILE: test/features/tables/simple_leading.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
"First Header"
],
[ "th",
"Second Header"
]
]
],
[ "tbody",
[ "tr",
[ "td",
"Content 1"
],
[ "td",
"Content 2"
]
],
[ "tr",
[ "td",
"Content 3"
],
[ "td",
"Content 4"
]
]
]
]
]
================================================
FILE: test/features/tables/simple_leading.text
================================================
| First Header | Second Header |
| ------------- | ------------- |
| Content 1 | Content 2 |
| Content 3 | Content 4 |
================================================
FILE: test/features/tables/simple_no_leading.json
================================================
[ "html",
[ "table",
[ "thead",
[ "tr",
[ "th",
"First Header"
],
[ "th",
"Second Header"
]
]
],
[ "tbody",
[ "tr",
[ "td",
"Content 1"
],
[ "td",
"Content 2"
]
],
[ "tr",
[ "td",
"Content 3"
],
[ "td",
"Content 4"
]
]
]
]
]
================================================
FILE: test/features/tables/simple_no_leading.text
================================================
First Header | Second Header
------------- | -------------
Content 1 | Content 2
Content 3 | Content 4
================================================
FILE: test/features/tables/spaces_tolerance.json
================================================
[ "html",
[ "p",
"This is a table (look out, less than 4 spaces\nbefore headers and rule)."
],
[ "table",
[ "thead",
[ "tr",
[ "th",
"Header"
],
[ "th",
"Header"
]
]
],
[ "tbody",
[ "tr",
[ "td",
"1"
],
[ "td",
"2"
]
],
[ "tr",
[ "td",
"3"
],
[ "td",
"4"
]
]
]
],
[ "p",
"Yeah, right."
]
]
================================================
FILE: test/features/tables/spaces_tolerance.text
================================================
This is a table (look out, less than 4 spaces
before headers and rule).
Header | Header
-------- | --------
1 | 2
3 | 4
Yeah, right.
================================================
FILE: test/features.t.js
================================================
var markdown = require("../src/markdown");
function test_dialect( dialect, features ) {
var fs = require("fs"),
path = require("path"),
tap = require("tap");
var slurpFile = function slurpFile( path ) {
return fs.readFileSync( path, "utf8" );
};
var isFile = function isFile( f ) {
try {
return fs.statSync( f ).isFile();
}
catch (e) {
if ( e.code === "ENOENT" )
return false;
throw e;
}
};
tap.test( dialect, function(tap) {
for ( var f in features ) {
(function( feature ) {
tap.test( feature, function(tap) {
var test_path = path.join(__dirname, "features", feature);
// grab all the test files in this feature
var tests = fs.readdirSync( test_path );
// filter to only the raw files
tests = tests.filter( function( x ) {return x.match( /\.text$/ ); } );
// remove the extensions
tests = tests.map( function( x ) {return x.replace( /\.text$/, "" ); } );
for ( var t in tests ) {
// load the raw text
var testName = dialect + "/" + feature + "/" + tests[ t ].substring( tests[ t ].lastIndexOf( "/" ) + 1 ),
testFileBase = path.join(test_path, tests[ t ]),
text = slurpFile( testFileBase + ".text" );
// load the target output
var json = JSON.parse( slurpFile( testFileBase + ".json" ) );
var output = markdown.toHTMLTree( text, dialect );
tap.equivalent( output, json, testName, {todo: isFile( testFileBase + ".todo" )} );
}
tap.end();
} );
} )( features[ f ] );
}
});
}
var dialects = {};
dialects.Gruber = [
"blockquotes",
"code",
"emphasis",
"headers",
"horizontal_rules",
"images",
"linebreaks",
"links",
"lists"
];
dialects.Maruku = dialects.Gruber.slice( 0 );
dialects.Maruku.push( "meta", "definition_lists", "tables" );
// TODO if dialects/features were passed on the command line, filter to them
// if ( args.length )
// features = features.filter( function( x ) args.indexOf( x ) !== -1 );
for ( var d in dialects ) {
test_dialect( d, dialects[ d ] );
}
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Amps_and_angle_encoding.json
================================================
["html", ["p", "AT&T has an ampersand in their name."],
["p", "AT&T is another way to write it."],
["p", "This & that."],
["p", "4 < 5."],
["p", "6 > 5."],
["p", "Here's a ", ["a", {
"href": "http://example.com/?foo=1&bar=2"
},
"link"], " with an ampersand in the URL."],
["p", "Here's a link with an amersand in the link text: ", ["a", {
"href": "http://att.com/",
"title": "AT&T"
},
"AT&T"], "."],
["p", "Here's an inline ", ["a", {
"href": "/script?foo=1&bar=2"
},
"link"], "."],
["p", "Here's an inline ", ["a", {
"href": "/script?foo=1&bar=2"
},
"link"], "."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Amps_and_angle_encoding.text
================================================
AT&T has an ampersand in their name.
AT&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"
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Amps_and_angle_encoding.xhtml
================================================
<p>AT&T has an ampersand in their name.</p>
<p>AT&T is another way to write it.</p>
<p>This & that.</p>
<p>4 < 5.</p>
<p>6 > 5.</p>
<p>Here's a <a href="http://example.com/?foo=1&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&T">AT&T</a>.</p>
<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p>
<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Auto_links.json
================================================
["html", ["p", "Link: ", ["a", {
"href": "http://example.com/"
},
"http://example.com/"], "."],
["p", "With an ampersand: ", ["a", {
"href": "http://example.com/?foo=1&bar=2"
},
"http://example.com/?foo=1&bar=2"]],
["ul", ["li", "In a list?"],
["li", ["a", {
"href": "http://example.com/"
},
"http://example.com/"]],
["li", "It should."]],
["blockquote", ["p", "Blockquoted: ", ["a", {
"href": "http://example.com/"
},
"http://example.com/"]]],
["p", "Auto-links should not occur here: ", ["code", "<http://example.com/>"]],
["pre", ["code", "or here: <http://example.com/>\u000a"]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Auto_links.text
================================================
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/>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Auto_links.xhtml
================================================
<p>Link: <a href="http://example.com/">http://example.com/</a>.</p>
<p>With an ampersand: <a href="http://example.com/?foo=1&bar=2">http://example.com/?foo=1&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><http://example.com/></code></p>
<pre><code>or here: <http://example.com/>
</code></pre>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Backslash_escapes.json
================================================
["html", ["p", "These should all get escaped:"],
["p", "Backslash: \\"],
["p", "Backtick: `"],
["p", "Asterisk: *"],
["p", "Underscore: _"],
["p", "Left brace: {"],
["p", "Right brace: }"],
["p", "Left bracket: ["],
["p", "Right bracket: ]"],
["p", "Left paren: ("],
["p", "Right paren: )"],
["p", "Greater-than: >"],
["p", "Hash: #"],
["p", "Period: ."],
["p", "Bang: !"],
["p", "Plus: +"],
["p", "Minus: -"],
["p", "These should not, because they occur within a code block:"],
["pre", ["code", "Backslash: \\\\\u000a\u000aBacktick: \\`\u000a\u000aAsterisk: \\*\u000a\u000aUnderscore: \\_\u000a\u000aLeft brace: \\{\u000a\u000aRight brace: \\}\u000a\u000aLeft bracket: \\[\u000a\u000aRight bracket: \\]\u000a\u000aLeft paren: \\(\u000a\u000aRight paren: \\)\u000a\u000aGreater-than: \\>\u000a\u000aHash: \\#\u000a\u000aPeriod: \\.\u000a\u000aBang: \\!\u000a\u000aPlus: \\+\u000a\u000aMinus: \\-\u000a"]],
["p", "Nor should these, which occur in code spans:"],
["p", "Backslash: ", ["code", "\\\\"]],
["p", "Backtick: ", ["code", "\\`"]],
["p", "Asterisk: ", ["code", "\\*"]],
["p", "Underscore: ", ["code", "\\_"]],
["p", "Left brace: ", ["code", "\\{"]],
["p", "Right brace: ", ["code", "\\}"]],
["p", "Left bracket: ", ["code", "\\["]],
["p", "Right bracket: ", ["code", "\\]"]],
["p", "Left paren: ", ["code", "\\("]],
["p", "Right paren: ", ["code", "\\)"]],
["p", "Greater-than: ", ["code", "\\>"]],
["p", "Hash: ", ["code", "\\#"]],
["p", "Period: ", ["code", "\\."]],
["p", "Bang: ", ["code", "\\!"]],
["p", "Plus: ", ["code", "\\+"]],
["p", "Minus: ", ["code", "\\-"]],
["p", "These should get escaped, even though they're matching pairs for\u000aother Markdown constructs:"],
["p", "*asterisks*"],
["p", "_underscores_"],
["p", "`backticks`"],
["p", "This is a code span with a literal backslash-backtick sequence: ", ["code", "\\`"]],
["p", "This is a tag with unescaped backticks ", ["span", {
"attr": "`ticks`"
},
"bar"], "."],
["p", "This is a tag with backslashes ", ["span", {
"attr": "\\\\backslashes\\\\"
},
"bar"], "."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Backslash_escapes.text
================================================
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>.
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Backslash_escapes.xhtml
================================================
<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: ></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: \>
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>\></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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Blockquotes_with_code_blocks.json
================================================
["html", ["blockquote", ["p", "Example:"],
["pre", ["code", "sub status {\u000a print \"working\";\u000a}\u000a"]],
["p", "Or:"],
["pre", ["code", "sub status {\u000a return \"working\";\u000a}\u000a"]]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Blockquotes_with_code_blocks.text
================================================
> Example:
>
> sub status {
> print "working";
> }
>
> Or:
>
> sub status {
> return "working";
> }
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Blockquotes_with_code_blocks.xhtml
================================================
<blockquote>
<p>Example:</p>
<pre><code>sub status {
print "working";
}
</code></pre>
<p>Or:</p>
<pre><code>sub status {
return "working";
}
</code></pre>
</blockquote>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Blocks.json
================================================
["html", ["pre", ["code", "code block on the first line\u000a"]],
["p", "Regular text."],
["pre", ["code", "code block indented by spaces\u000a"]],
["p", "Regular text."],
["pre", ["code", "the lines in this block \u000aall contain trailing spaces \u000a"]],
["p", "Regular Text."],
["pre", ["code", "code block on the last line\u000a"]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Blocks.text
================================================
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
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Blocks.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Spans.json
================================================
["html", ["p", ["code", "<test a=\""], " content of attribute ", ["code", "\">"]],
["p", "Fix for backticks within HTML tag: ", ["span", {
"attr": "`ticks`"
},
"like this"]],
["p", "Here's how you put ", ["code", "`backticks`"], " in a code span."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Spans.text
================================================
`<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.
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Code_Spans.xhtml
================================================
<p><code><test a="</code> content of attribute <code>"></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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Hard-wrapped_paragraphs_with_list-like_lines.json
================================================
["html", ["p", "In Markdown 1.0.0 and earlier. Version\u000a8. This line turns into a list item.\u000aBecause a hard-wrapped line in the\u000amiddle of a paragraph looked like a\u000alist item."],
["p", "Here's one with a bullet.\u000a* criminey."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Hard-wrapped_paragraphs_with_list-like_lines.text
================================================
In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.
Here's one with a bullet.
* criminey.
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Hard-wrapped_paragraphs_with_list-like_lines.xhtml
================================================
<p>In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.</p>
<p>Here's one with a bullet.
* criminey.</p>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Horizontal_rules.json
================================================
["html", ["p", "Dashes:"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "---\u000a"]], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "- - -\u000a"]],
["p", "Asterisks:"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "***\u000a"]], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "* * *\u000a"]],
["p", "Underscores:"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "___\u000a"]], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["pre", ["code", "_ _ _\u000a"]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Horizontal_rules.text
================================================
Dashes:
---
---
---
---
---
- - -
- - -
- - -
- - -
- - -
Asterisks:
***
***
***
***
***
* * *
* * *
* * *
* * *
* * *
Underscores:
___
___
___
___
___
_ _ _
_ _ _
_ _ _
_ _ _
_ _ _
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Horizontal_rules.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Images.json
================================================
["html", ["p", ["img", {
"src": "/path/to/img.jpg",
"alt": "Alt text"
}]],
["p", ["img", {
"src": "/path/to/img.jpg",
"alt": "Alt text",
"title": "Optional title"
}]],
["p", "Inline within a paragraph: ", ["a", {
"href": "/url/"
},
"alt text"], "."],
["p", ["img", {
"src": "/url/",
"alt": "alt text",
"title": "title preceded by two spaces"
}]],
["p", ["img", {
"src": "/url/",
"alt": "alt text",
"title": "title has spaces afterward"
}]],
["p", ["img", {
"src": "/url/",
"alt": "alt text"
}]],
["p", ["img", {
"src": "/url/",
"alt": "alt text",
"title": "with a title"
}], "."],
["p", ["img", {
"alt": "Empty"
}]],
["p", ["img", {
"src": "http://example.com/(parens).jpg",
"alt": "this is a stupid URL"
}]],
["p", ["img", {
"src": "/url/",
"alt": "alt text"
}]],
["p", ["img", {
"src": "/url/",
"alt": "alt text",
"title": "Title here"
}]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Images.text
================================================


Inline within a paragraph: [alt text](/url/).



.
![Empty]()
.jpg)
![alt text][foo]
[foo]: /url/
![alt text][bar]
[bar]: /url/ "Title here"
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Images.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Advanced).json
================================================
["html", ["p", "Simple block on one line:"], "\u000a\u000a", ["div", "foo"], "\u000a\u000a", ["p", "And nested without indentation:"], "\u000a\u000a", ["div", "\u000a", ["div", "\u000a", ["div", "\u000afoo\u000a"], "\u000a", ["div", {
"style": ">"
}], "\u000a"], "\u000a", ["div", "bar"], "\u000a"], "\u000a\u000a", ["p", "And with attributes:"], "\u000a\u000a", ["div", "\u000a ", ["div", {
"id": "foo"
}], "\u000a"], "\u000a\u000a", ["p", "This was broken in 1.0.2b7:"], "\u000a\u000a", ["div", {
"class": "inlinepage"
},
"\u000a", ["div", {
"class": "toggleableend"
},
"\u000afoo\u000a"], "\u000a"], "\u000a"]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Advanced).text
================================================
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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Advanced).xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Simple).html
================================================
<p>Here's a simple block:</p>
<div>
foo
</div>
<p>This should be a code block, though:</p>
<pre><code><div>
foo
</div>
</code></pre>
<p>As should this:</p>
<pre><code><div>foo</div>
</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><!-- Comment -->
</code></pre>
<p>Just plain comment, with trailing spaces on the line:</p>
<!-- foo -->
<p>Code:</p>
<pre><code><hr />
</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" >
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Simple).json
================================================
["html", ["p", "Here's a simple block:"], "\u000a\u000a", ["div", "\u000a foo\u000a"], "\u000a\u000a", ["p", "This should be a code block, though:"],
["pre", ["code", "<div>\u000a foo\u000a</div>\u000a"]],
["p", "As should this:"],
["pre", ["code", "<div>foo</div>\u000a"]],
["p", "Now, nested:"], "\u000a\u000a", ["div", "\u000a ", ["div", "\u000a ", ["div", "\u000a foo\u000a "], "\u000a "], "\u000a"], "\u000a\u000a", ["p", "This should just be an HTML comment:"], "\u000a\u000a", "\u000a\u000a", ["p", "Multiline:"], "\u000a\u000a", "\u000a\u000a", ["p", "Code block:"],
["pre", ["code", "<!-- Comment -->\u000a"]],
["p", "Just plain comment, with trailing spaces on the line:"], "\u000a\u000a", " \u000a\u000a", ["p", "Code:"],
["pre", ["code", "<hr />\u000a"]],
["p", "Hr's:"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], "\u000a\u000a", ["hr"], " \u000a\u000a", ["hr"], " \u000a\u000a", ["hr"], " \u000a\u000a", ["hr", {
"class": "foo",
"id": "bar"
}], "\u000a\u000a", ["hr", {
"class": "foo",
"id": "bar"
}], "\u000a\u000a", ["hr", {
"class": "foo",
"id": "bar"
}], "\u000a"]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_(Simple).text
================================================
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" >
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_comments.html
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_comments.json
================================================
["html", ["p", "Paragraph one."], "\u000a\u000a", "\u000a\u000a", "\u000a\u000a", ["p", "Paragraph two."], "\u000a\u000a", "\u000a\u000a", ["p", "The end."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Inline_HTML_comments.text
================================================
Paragraph one.
<!-- This is a simple comment -->
<!--
This is another comment.
-->
Paragraph two.
<!-- one comment block -- -- with two comments -->
The end.
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_inline_style.json
================================================
["html", ["p", "Just a ", ["a", {
"href": "/url/"
},
"URL"], "."],
["p", ["a", {
"href": "/url/",
"title": "title"
},
"URL and title"], "."],
["p", ["a", {
"href": "/url/",
"title": "title preceded by two spaces"
},
"URL and title"], "."],
["p", ["a", {
"href": "/url/",
"title": "title preceded by a tab"
},
"URL and title"], "."],
["p", ["a", {
"href": "/url/",
"title": "title has spaces afterward"
},
"URL and title"], "."],
["p", ["a", {
"href": "/url/"
},
"URL wrapped in angle brackets"], "."],
["p", ["a", {
"href": "/url/",
"title": "Here's the title"
},
"URL w/ angle brackets + title"], "."],
["p", ["a", "Empty"], "."],
["p", ["a", {
"href": "http://en.wikipedia.org/wiki/WIMP_(computing)"
},
"With parens in the URL"]],
["p", "(With outer parens and ", ["a", {
"href": "/foo(bar)"
},
"parens in url"], ")"],
["p", ["a", {
"href": "/foo(bar)",
"title": "and a title"
},
"With parens in the URL"]],
["p", "(With outer parens and ", ["a", {
"href": "/foo(bar)",
"title": "and a title"
},
"parens in url"], ")"]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_inline_style.text
================================================
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"))
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_inline_style.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_reference_style.json
================================================
["html", ["p", "Foo ", ["a", {
"href": "/url/",
"title": "Title"
},
"bar"], "."],
["p", "Foo ", ["a", {
"href": "/url/",
"title": "Title"
},
"bar"], "."],
["p", "Foo ", ["a", {
"href": "/url/",
"title": "Title"
},
"bar"], "."],
["p", "With ", ["a", {
"href": "/url/"
},
"embedded [brackets]"], "."],
["p", "Indented ", ["a", {
"href": "/url"
},
"once"], "."],
["p", "Indented ", ["a", {
"href": "/url"
},
"twice"], "."],
["p", "Indented ", ["a", {
"href": "/url"
},
"thrice"], "."],
["p", "Indented [four][] times."],
["pre", ["code", "[four]: /url\u000a"]], "\u000a\u000a", ["hr"], "\u000a\u000a", ["p", ["a", {
"href": "foo"
},
"this"], " should work"],
["p", "So should ", ["a", {
"href": "foo"
},
"this"], "."],
["p", "And ", ["a", {
"href": "foo"
},
"this"], "."],
["p", "And ", ["a", {
"href": "foo"
},
"this"], "."],
["p", "And ", ["a", {
"href": "foo"
},
"this"], "."],
["p", "But not [that] []."],
["p", "Nor [that][]."],
["p", "Nor [that]."],
["p", "[Something in brackets like ", ["a", {
"href": "foo"
},
"this"], " should work]"],
["p", "[Same with ", ["a", {
"href": "foo"
},
"this"], ".]"],
["p", "In this case, ", ["a", {
"href": "/somethingelse/"
},
"this"], " points to something else."],
["p", "Backslashing should suppress [this] and [this]."], "\u000a\u000a", ["hr"], "\u000a\u000a", ["p", "Here's one where the ", ["a", {
"href": "/url/"
},
"link\u000abreaks"], " across lines."],
["p", "Here's another where the ", ["a", {
"href": "/url/"
},
"link \u000abreaks"], " across lines, but with a line-ending space."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_reference_style.text
================================================
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/
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_reference_style.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_shortcut_references.json
================================================
["html", ["p", "This is the ", ["a", {
"href": "/simple"
},
"simple case"], "."],
["p", "This one has a ", ["a", {
"href": "/foo"
},
"line\u000abreak"], "."],
["p", "This one has a ", ["a", {
"href": "/foo"
},
"line \u000abreak"], " with a line-ending space."],
["p", ["a", {
"href": "/that"
},
"this"], " and the ", ["a", {
"href": "/other"
},
"other"]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_shortcut_references.text
================================================
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
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Links_shortcut_references.xhtml
================================================
<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>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Literal_quotes_in_titles.json
================================================
["html", ["p", "Foo ", ["a", {
"href": "/url/",
"title": "Title with \"quotes\" inside"
},
"bar"], "."],
["p", "Foo ", ["a", {
"href": "/url/",
"title": "Title with \"quotes\" inside"
},
"bar"], "."]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Literal_quotes_in_titles.text
================================================
Foo [bar][].
Foo [bar](/url/ "Title with "quotes" inside").
[bar]: /url/ "Title with "quotes" inside"
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Literal_quotes_in_titles.xhtml
================================================
<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p>
<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p>
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Markdown_Documentation_-_Basics.json
================================================
["html", ["h1", "Markdown: Basics"], "\u000a\u000a", ["ul", {
"id": "ProjectSubmenu"
},
["li", ["a", {
"href": "/projects/markdown/",
"title": "Markdown Project Page"
},
"Main"]],
["li", ["a", {
"class": "selected",
"title": "Markdown Basics"
},
"Basics"]],
["li", ["a", {
"href": "/projects/markdown/syntax",
"title": "Markdown Syntax Documentation"
},
"Syntax"]],
["li", ["a", {
"href": "/projects/markdown/license",
"title": "Pricing and License Information"
},
"License"]],
["li", ["a", {
"href": "/projects/markdown/dingus",
"title": "Online Markdown Web Form"
},
"Dingus"]]], "\u000a\u000a", ["h2", "Getting the Gist of Markdown's Formatting Syntax"], "\u000a\u000a", ["p", "This page offers a brief overview of what it's like to use Markdown.\u000aThe ", ["a", {
"href": "/projects/markdown/syntax",
"title": "Markdown Syntax"
},
"syntax page"], " provides complete, detailed documentation for\u000aevery feature, but Markdown should be very easy to pick up simply by\u000alooking at a few examples of it in action. The examples on this page\u000aare written in a before/after style, showing example syntax and the\u000aHTML output produced by Markdown."],
["p", "It's also helpful to simply try Markdown out; the ", ["a", {
"href": "/projects/markdown/dingus",
"title": "Markdown Dingus"
},
"Dingus"], " is a\u000aweb application that allows you type your own Markdown-formatted text\u000aand translate it to XHTML."],
["p", ["strong", "Note:"], " This document is itself written using Markdown; you\u000acan ", ["a", {
"href": "/projects/markdown/basics.text"
},
"see the source for it by adding '.text' to the URL"], "."], "\u000a\u000a", ["h2", "Paragraphs, Headers, Blockquotes"], "\u000a\u000a", ["p", "A paragraph is simply one or more consecutive lines of text, separated\u000aby one or more blank lines. (A blank line is any line that looks like a\u000ablank line -- a line containing nothing spaces or tabs is considered\u000ablank.) Normal paragraphs should not be intended with spaces or tabs."],
["p", "Markdown offers two styles of headers: ", ["em", "Setext"], " and ", ["em", "atx"], ".\u000aSetext-style headers for ", ["code", "<h1>"], " and ", ["code", "<h2>"], " are created by\u000a\"underlining\" with equal signs (", ["code", "="], ") and hyphens (", ["code", "-"], "), respectively.\u000aTo create an atx-style header, you put 1-6 hash marks (", ["code", "#"], ") at the\u000abeginning of the line -- the number of hashes equals the resulting\u000aHTML header level."],
["p", "Blockquotes are indicated using email-style '", ["code", ">"], "' angle brackets."],
["p", "Markdown:"],
["pre", ["code", "A First Level Header\u000a====================\u000a\u000aA Second Level Header\u000a---------------------\u000a\u000aNow is the time for all good men to come to\u000athe aid of their country. This is just a\u000aregular paragraph.\u000a\u000aThe quick brown fox jumped over the lazy\u000adog's back.\u000a\u000a### Header 3\u000a\u000a> This is a blockquote.\u000a> \u000a> This is the second paragraph in the blockquote.\u000a>\u000a> ## This is an H2 in a blockquote\u000a"]],
["p", "Output:"],
["pre", ["code", "<h1>A First Level Header</h1>\u000a\u000a<h2>A Second Level Header</h2>\u000a\u000a<p>Now is the time for all good men to come to\u000athe aid of their country. This is just a\u000aregular paragraph.</p>\u000a\u000a<p>The quick brown fox jumped over the lazy\u000adog's back.</p>\u000a\u000a<h3>Header 3</h3>\u000a\u000a<blockquote>\u000a <p>This is a blockquote.</p>\u000a\u000a <p>This is the second paragraph in the blockquote.</p>\u000a\u000a <h2>This is an H2 in a blockquote</h2>\u000a</blockquote>\u000a"]], "\u000a\u000a", ["h3", "Phrase Emphasis"], "\u000a\u000a", ["p", "Markdown uses asterisks and underscores to indicate spans of emphasis."],
["p", "Markdown:"],
["pre", ["code", "Some of these words *are emphasized*.\u000aSome of these words _are emphasized also_.\u000a\u000aUse two asterisks for **strong emphasis**.\u000aOr, if you prefer, __use two underscores instead__.\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>Some of these words <em>are emphasized</em>.\u000aSome of these words <em>are emphasized also</em>.</p>\u000a\u000a<p>Use two asterisks for <strong>strong emphasis</strong>.\u000aOr, if you prefer, <strong>use two underscores instead</strong>.</p>\u000a"]], "\u000a\u000a", ["h2", "Lists"], "\u000a\u000a", ["p", "Unordered (bulleted) lists use asterisks, pluses, and hyphens (", ["code", "*"], ",\u000a", ["code", "+"], ", and ", ["code", "-"], ") as list markers. These three markers are\u000ainterchangable; this:"],
["pre", ["code", "* Candy.\u000a* Gum.\u000a* Booze.\u000a"]],
["p", "this:"],
["pre", ["code", "+ Candy.\u000a+ Gum.\u000a+ Booze.\u000a"]],
["p", "and this:"],
["pre", ["code", "- Candy.\u000a- Gum.\u000a- Booze.\u000a"]],
["p", "all produce the same output:"],
["pre", ["code", "<ul>\u000a<li>Candy.</li>\u000a<li>Gum.</li>\u000a<li>Booze.</li>\u000a</ul>\u000a"]],
["p", "Ordered (numbered) lists use regular numbers, followed by periods, as\u000alist markers:"],
["pre", ["code", "1. Red\u000a2. Green\u000a3. Blue\u000a"]],
["p", "Output:"],
["pre", ["code", "<ol>\u000a<li>Red</li>\u000a<li>Green</li>\u000a<li>Blue</li>\u000a</ol>\u000a"]],
["p", "If you put blank lines between items, you'll get ", ["code", "<p>"], " tags for the\u000alist item text. You can create multi-paragraph list items by indenting\u000athe paragraphs by 4 spaces or 1 tab:"],
["pre", ["code", "* A list item.\u000a\u000a With multiple paragraphs.\u000a\u000a* Another item in the list.\u000a"]],
["p", "Output:"],
["pre", ["code", "<ul>\u000a<li><p>A list item.</p>\u000a<p>With multiple paragraphs.</p></li>\u000a<li><p>Another item in the list.</p></li>\u000a</ul>\u000a"]], "\u000a\u000a", ["h3", "Links"], "\u000a\u000a", ["p", "Markdown supports two styles for creating links: ", ["em", "inline"], " and\u000a", ["em", "reference"], ". With both styles, you use square brackets to delimit the\u000atext you want to turn into a link."],
["p", "Inline-style links use parentheses immediately after the link text.\u000aFor example:"],
["pre", ["code", "This is an [example link](http://example.com/).\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>This is an <a href=\"http://example.com/\">\u000aexample link</a>.</p>\u000a"]],
["p", "Optionally, you may include a title attribute in the parentheses:"],
["pre", ["code", "This is an [example link](http://example.com/ \"With a Title\").\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>This is an <a href=\"http://example.com/\" title=\"With a Title\">\u000aexample link</a>.</p>\u000a"]],
["p", "Reference-style links allow you to refer to your links by names, which\u000ayou define elsewhere in your document:"],
["pre", ["code", "I get 10 times more traffic from [Google][1] than from\u000a[Yahoo][2] or [MSN][3].\u000a\u000a[1]: http://google.com/ \"Google\"\u000a[2]: http://search.yahoo.com/ \"Yahoo Search\"\u000a[3]: http://search.msn.com/ \"MSN Search\"\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>I get 10 times more traffic from <a href=\"http://google.com/\"\u000atitle=\"Google\">Google</a> than from <a href=\"http://search.yahoo.com/\"\u000atitle=\"Yahoo Search\">Yahoo</a> or <a href=\"http://search.msn.com/\"\u000atitle=\"MSN Search\">MSN</a>.</p>\u000a"]],
["p", "The title attribute is optional. Link names may contain letters,\u000anumbers and spaces, but are ", ["em", "not"], " case sensitive:"],
["pre", ["code", "I start my morning with a cup of coffee and\u000a[The New York Times][NY Times].\u000a\u000a[ny times]: http://www.nytimes.com/\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>I start my morning with a cup of coffee and\u000a<a href=\"http://www.nytimes.com/\">The New York Times</a>.</p>\u000a"]], "\u000a\u000a", ["h3", "Images"], "\u000a\u000a", ["p", "Image syntax is very much like link syntax."],
["p", "Inline (titles are optional):"],
["pre", ["code", "\u000a"]],
["p", "Reference-style:"],
["pre", ["code", "![alt text][id]\u000a\u000a[id]: /path/to/img.jpg \"Title\"\u000a"]],
["p", "Both of the above examples produce the same output:"],
["pre", ["code", "<img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" />\u000a"]], "\u000a\u000a", ["h3", "Code"], "\u000a\u000a", ["p", "In a regular paragraph, you can create code span by wrapping text in\u000abacktick quotes. Any ampersands (", ["code", "&"], ") and angle brackets (", ["code", "<"], " or\u000a", ["code", ">"], ") will automatically be translated into HTML entities. This makes\u000ait easy to use Markdown to write about HTML example code:"],
["pre", ["code", "I strongly recommend against using any `<blink>` tags.\u000a\u000aI wish SmartyPants used named entities like `—`\u000ainstead of decimal-encoded entites like `—`.\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>I strongly recommend against using any\u000a<code><blink></code> tags.</p>\u000a\u000a<p>I wish SmartyPants used named entities like\u000a<code>&mdash;</code> instead of decimal-encoded\u000aentites like <code>&#8212;</code>.</p>\u000a"]],
["p", "To specify an entire block of pre-formatted code, indent every line of\u000athe block by 4 spaces or 1 tab. Just like with code spans, ", ["code", "&"], ", ", ["code", "<"], ",\u000aand ", ["code", ">"], " characters will be escaped automatically."],
["p", "Markdown:"],
["pre", ["code", "If you want your page to validate under XHTML 1.0 Strict,\u000ayou've got to put paragraph tags in your blockquotes:\u000a\u000a <blockquote>\u000a <p>For example.</p>\u000a </blockquote>\u000a"]],
["p", "Output:"],
["pre", ["code", "<p>If you want your page to validate under XHTML 1.0 Strict,\u000ayou've got to put paragraph tags in your blockquotes:</p>\u000a\u000a<pre><code><blockquote>\u000a <p>For example.</p>\u000a</blockquote>\u000a</code></pre>\u000a"]]]
================================================
FILE: test/fixtures/Markdown-from-MDTest1.1.mdtest/Markdown_Documentation_-_Basics.text
================================================
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>
gitextract_2zijr1dr/
├── .gitignore
├── .travis.yml
├── Changes.md
├── Gruntfile.js
├── README.md
├── bin/
│ └── md2html.js
├── bower.json
├── inc/
│ ├── footer-node.js
│ ├── footer-web.js
│ ├── header.js
│ └── tasks/
│ └── build_markdown.js
├── lib/
│ └── index.js
├── package.json
├── seed.yml
├── src/
│ ├── core.js
│ ├── dialects/
│ │ ├── dialect_helpers.js
│ │ ├── gruber.js
│ │ └── maruku.js
│ ├── markdown.js
│ ├── markdown_helpers.js
│ ├── parser.js
│ └── render_tree.js
└── test/
├── features/
│ ├── blockquotes/
│ │ ├── contains_code.json
│ │ ├── contains_code.text
│ │ ├── lazy_wrapping.json
│ │ ├── lazy_wrapping.text
│ │ ├── leading_paras.json
│ │ ├── leading_paras.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── simple.json
│ │ ├── simple.text
│ │ ├── spaceless.json
│ │ ├── spaceless.text
│ │ ├── spaces_before.json
│ │ ├── spaces_before.text
│ │ ├── threequotes.json
│ │ └── threequotes.text
│ ├── code/
│ │ ├── blank_lines.json
│ │ ├── blank_lines.text
│ │ ├── block.json
│ │ ├── block.text
│ │ ├── embedded_backtick.json
│ │ ├── embedded_backtick.text
│ │ ├── horizontal_rules.json
│ │ ├── horizontal_rules.text
│ │ ├── in_lists.json
│ │ ├── in_lists.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inline_multiline.json
│ │ ├── inline_multiline.text
│ │ ├── trailing_para.json
│ │ ├── trailing_para.text
│ │ ├── with_greater_than.json
│ │ └── with_greater_than.text
│ ├── definition_lists/
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── long.json
│ │ ├── long.text
│ │ ├── multiple_definitions.json
│ │ ├── multiple_definitions.text
│ │ ├── multiple_terms.json
│ │ ├── multiple_terms.text
│ │ ├── tight.json
│ │ └── tight.text
│ ├── emphasis/
│ │ ├── multiple_lines.json
│ │ ├── multiple_lines.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── simple.json
│ │ └── simple.text
│ ├── headers/
│ │ ├── atx.json
│ │ ├── atx.text
│ │ ├── atx_closing_hashes.json
│ │ ├── atx_closing_hashes.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── setext.json
│ │ ├── setext.text
│ │ ├── trailing_paras.json
│ │ └── trailing_paras.text
│ ├── horizontal_rules/
│ │ ├── abutting_blocks.json
│ │ ├── abutting_blocks.text
│ │ ├── dashes.json
│ │ ├── dashes.text
│ │ ├── front_matter.json
│ │ ├── front_matter.text
│ │ ├── leading_spaces.json
│ │ ├── leading_spaces.text
│ │ ├── long.json
│ │ ├── long.text
│ │ ├── long_loose.json
│ │ ├── long_loose.text
│ │ ├── loose_dashes.json
│ │ ├── loose_dashes.text
│ │ ├── loose_stars.json
│ │ ├── loose_stars.text
│ │ ├── loose_underscores.json
│ │ ├── loose_underscores.text
│ │ ├── stars.json
│ │ ├── stars.text
│ │ ├── underscores.json
│ │ └── underscores.text
│ ├── images/
│ │ ├── basic.json
│ │ ├── basic.text
│ │ ├── crotcheted_url.json
│ │ ├── crotcheted_url.text
│ │ ├── crotcheted_url_with_title.json
│ │ ├── crotcheted_url_with_title.text
│ │ ├── empty.json
│ │ ├── empty.text
│ │ ├── incomplete_image.json
│ │ ├── incomplete_image.text
│ │ ├── inside_link.json
│ │ ├── inside_link.text
│ │ ├── ref.json
│ │ ├── ref.text
│ │ ├── spaces_in_href.json
│ │ ├── spaces_in_href.text
│ │ ├── spaces_round_title.json
│ │ ├── spaces_round_title.text
│ │ ├── title.json
│ │ └── title.text
│ ├── linebreaks/
│ │ ├── simple.json
│ │ └── simple.text
│ ├── links/
│ │ ├── apostrophe.json
│ │ ├── apostrophe.text
│ │ ├── autolink_email.json
│ │ ├── autolink_email.text
│ │ ├── autolink_in_code.json
│ │ ├── autolink_in_code.text
│ │ ├── autolink_url.json
│ │ ├── autolink_url.text
│ │ ├── broken_brackets.json
│ │ ├── broken_brackets.text
│ │ ├── broken_link.json
│ │ ├── broken_link.text
│ │ ├── case_insensitive.json
│ │ ├── case_insensitive.text
│ │ ├── escaped_broken_link.json
│ │ ├── escaped_broken_link.text
│ │ ├── implicit.json
│ │ ├── implicit.text
│ │ ├── in_blockquotes.json
│ │ ├── in_blockquotes.text
│ │ ├── in_brackets.json
│ │ ├── in_brackets.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inline_with_newline.json
│ │ ├── inline_with_newline.text
│ │ ├── inline_with_title.json
│ │ ├── inline_with_title.text
│ │ ├── missing_references.json
│ │ ├── missing_references.text
│ │ ├── no_closing.json
│ │ ├── no_closing.text
│ │ ├── parens_escaped_inline.json
│ │ ├── parens_escaped_inline.text
│ │ ├── parens_inline.json
│ │ ├── parens_inline.text
│ │ ├── parens_reference.json
│ │ ├── parens_reference.text
│ │ ├── ref_reuse.json
│ │ ├── ref_reuse.text
│ │ ├── ref_with_image_ref.json
│ │ ├── ref_with_image_ref.text
│ │ ├── reference.json
│ │ ├── reference.text
│ │ ├── reference_missing.json
│ │ ├── reference_missing.text
│ │ ├── reference_with_newline.json
│ │ ├── reference_with_newline.text
│ │ ├── reference_with_newline_and_space.json
│ │ ├── reference_with_newline_and_space.text
│ │ ├── reference_with_quote.json
│ │ ├── reference_with_quote.text
│ │ ├── reference_with_space.json
│ │ ├── reference_with_space.text
│ │ ├── spaces_in_url.json
│ │ └── spaces_in_url.text
│ ├── lists/
│ │ ├── bullet_types.json
│ │ ├── bullet_types.text
│ │ ├── hr_abutting.json
│ │ ├── hr_abutting.text
│ │ ├── hr_inside.json
│ │ ├── hr_inside.text
│ │ ├── lazy_wrapping.json
│ │ ├── lazy_wrapping.text
│ │ ├── leading_whitespace.json
│ │ ├── leading_whitespace.text
│ │ ├── loose.json
│ │ ├── loose.text
│ │ ├── loose_with_inline.json
│ │ ├── loose_with_inline.text
│ │ ├── multiline_inline.json
│ │ ├── multiline_inline.text
│ │ ├── nested.json
│ │ ├── nested.text
│ │ ├── nested_para.json
│ │ ├── nested_para.text
│ │ ├── numeric.json
│ │ ├── numeric.text
│ │ ├── quote_inside.json
│ │ ├── quote_inside.text
│ │ ├── references.json
│ │ ├── references.text
│ │ ├── tight.json
│ │ └── tight.text
│ ├── meta/
│ │ ├── attribute.json
│ │ ├── attribute.text
│ │ ├── class.json
│ │ ├── class.text
│ │ ├── code.json
│ │ ├── code.text
│ │ ├── document.json
│ │ ├── document.text
│ │ ├── id.json
│ │ ├── id.text
│ │ ├── inline.json
│ │ ├── inline.text
│ │ ├── inner_whitespace.json
│ │ ├── inner_whitespace.text
│ │ ├── leading_whitespace.json
│ │ ├── leading_whitespace.text
│ │ ├── list.json
│ │ ├── list.text
│ │ ├── list.todo
│ │ ├── multiple_classes.json
│ │ ├── multiple_classes.text
│ │ ├── quoted.json
│ │ └── quoted.text
│ └── tables/
│ ├── align.json
│ ├── align.text
│ ├── compact.json
│ ├── compact.text
│ ├── inline_formatting.json
│ ├── inline_formatting.text
│ ├── pipe_escape.json
│ ├── pipe_escape.text
│ ├── simple_leading.json
│ ├── simple_leading.text
│ ├── simple_no_leading.json
│ ├── simple_no_leading.text
│ ├── spaces_tolerance.json
│ └── spaces_tolerance.text
├── features.t.js
├── fixtures/
│ ├── Markdown-from-MDTest1.1.mdtest/
│ │ ├── Amps_and_angle_encoding.json
│ │ ├── Amps_and_angle_encoding.text
│ │ ├── Amps_and_angle_encoding.xhtml
│ │ ├── Auto_links.json
│ │ ├── Auto_links.text
│ │ ├── Auto_links.xhtml
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Backslash_escapes.xhtml
│ │ ├── Blockquotes_with_code_blocks.json
│ │ ├── Blockquotes_with_code_blocks.text
│ │ ├── Blockquotes_with_code_blocks.xhtml
│ │ ├── Code_Blocks.json
│ │ ├── Code_Blocks.text
│ │ ├── Code_Blocks.xhtml
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_Spans.xhtml
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.json
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.text
│ │ ├── Hard-wrapped_paragraphs_with_list-like_lines.xhtml
│ │ ├── Horizontal_rules.json
│ │ ├── Horizontal_rules.text
│ │ ├── Horizontal_rules.xhtml
│ │ ├── Images.json
│ │ ├── Images.text
│ │ ├── Images.xhtml
│ │ ├── Inline_HTML_(Advanced).json
│ │ ├── Inline_HTML_(Advanced).text
│ │ ├── Inline_HTML_(Advanced).xhtml
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Links_inline_style.xhtml
│ │ ├── Links_reference_style.json
│ │ ├── Links_reference_style.text
│ │ ├── Links_reference_style.xhtml
│ │ ├── Links_shortcut_references.json
│ │ ├── Links_shortcut_references.text
│ │ ├── Links_shortcut_references.xhtml
│ │ ├── Literal_quotes_in_titles.json
│ │ ├── Literal_quotes_in_titles.text
│ │ ├── Literal_quotes_in_titles.xhtml
│ │ ├── Markdown_Documentation_-_Basics.json
│ │ ├── Markdown_Documentation_-_Basics.text
│ │ ├── Markdown_Documentation_-_Basics.xhtml
│ │ ├── Markdown_Documentation_-_Syntax.json
│ │ ├── Markdown_Documentation_-_Syntax.text
│ │ ├── Markdown_Documentation_-_Syntax.xhtml
│ │ ├── Nested_blockquotes.json
│ │ ├── Nested_blockquotes.text
│ │ ├── Nested_blockquotes.xhtml
│ │ ├── Ordered_and_unordered_lists.json
│ │ ├── Ordered_and_unordered_lists.text
│ │ ├── Ordered_and_unordered_lists.xhtml
│ │ ├── Strong_and_em_together.json
│ │ ├── Strong_and_em_together.text
│ │ ├── Strong_and_em_together.xhtml
│ │ ├── Tabs.json
│ │ ├── Tabs.text
│ │ ├── Tabs.xhtml
│ │ ├── Tidyness.json
│ │ ├── Tidyness.text
│ │ └── Tidyness.xhtml
│ ├── PHP_Markdown-from-MDTest1.1.mdtest/
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Backslash_escapes.xhtml
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_Spans.xhtml
│ │ ├── Code_block_in_a_list_item.json
│ │ ├── Code_block_in_a_list_item.text
│ │ ├── Code_block_in_a_list_item.xhtml
│ │ ├── Email_auto_links.json
│ │ ├── Email_auto_links.text
│ │ ├── Email_auto_links.xhtml
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Emphasis.xhtml
│ │ ├── Headers.json
│ │ ├── Headers.text
│ │ ├── Headers.xhtml
│ │ ├── Horizontal_Rules.json
│ │ ├── Horizontal_Rules.text
│ │ ├── Horizontal_Rules.xhtml
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_(Span).json
│ │ ├── Inline_HTML_(Span).text
│ │ ├── Inline_HTML_(Span).xhtml
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── Ins_and_del.json
│ │ ├── Ins_and_del.text
│ │ ├── Ins_and_del.xhtml
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Links_inline_style.xhtml
│ │ ├── MD5_Hashes.json
│ │ ├── MD5_Hashes.text
│ │ ├── MD5_Hashes.xhtml
│ │ ├── Nesting.json
│ │ ├── Nesting.text
│ │ ├── Nesting.xhtml
│ │ ├── PHP-Specific_Bugs.json
│ │ ├── PHP-Specific_Bugs.text
│ │ ├── PHP-Specific_Bugs.xhtml
│ │ ├── Parens_in_URL.json
│ │ ├── Parens_in_URL.text
│ │ ├── Parens_in_URL.xhtml
│ │ ├── Tight_blocks.json
│ │ ├── Tight_blocks.text
│ │ └── Tight_blocks.xhtml
│ ├── README
│ ├── Text-Markdown.mdtest/
│ │ ├── CoreDumps5.8.json
│ │ ├── CoreDumps5.8.text
│ │ ├── CoreDumps5.8.xhtml
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Emphasis.xhtml
│ │ ├── HTML-Comment-encoding.json
│ │ ├── HTML-Comment-encoding.text
│ │ ├── HTML-Comment-encoding.xhtml
│ │ ├── HTML5-attributes.html
│ │ ├── HTML5-attributes.json
│ │ ├── HTML5-attributes.text
│ │ ├── Links_brackets.json
│ │ ├── Links_brackets.text
│ │ ├── Links_brackets.xhtml
│ │ ├── Links_multiline_bugs_1.html
│ │ ├── Links_multiline_bugs_1.json
│ │ ├── Links_multiline_bugs_1.text
│ │ ├── Links_multiline_bugs_2.html
│ │ ├── Links_multiline_bugs_2.json
│ │ ├── Links_multiline_bugs_2.text
│ │ ├── Links_reference_style.json
│ │ ├── Links_reference_style.text
│ │ ├── Links_reference_style.xhtml
│ │ ├── Lists-multilevel-md5-edgecase.json
│ │ ├── Lists-multilevel-md5-edgecase.text
│ │ ├── Lists-multilevel-md5-edgecase.xhtml
│ │ ├── PHP-ASP_tags.json
│ │ ├── PHP-ASP_tags.text
│ │ ├── PHP-ASP_tags.xhtml
│ │ ├── Unicode.json
│ │ ├── Unicode.text
│ │ └── Unicode.xhtml
│ ├── docs-maruku-unittest/
│ │ ├── abbreviations.html
│ │ ├── abbreviations.json
│ │ ├── abbreviations.text
│ │ ├── alt.html
│ │ ├── alt.json
│ │ ├── alt.text
│ │ ├── blank.html
│ │ ├── blank.json
│ │ ├── blank.text
│ │ ├── blanks_in_code.html
│ │ ├── blanks_in_code.json
│ │ ├── blanks_in_code.text
│ │ ├── bug_def.html
│ │ ├── bug_def.json
│ │ ├── bug_def.text
│ │ ├── bug_table.html
│ │ ├── bug_table.json
│ │ ├── bug_table.text
│ │ ├── code.html
│ │ ├── code.json
│ │ ├── code.text
│ │ ├── code2.html
│ │ ├── code2.json
│ │ ├── code2.text
│ │ ├── code3.html
│ │ ├── code3.json
│ │ ├── code3.text
│ │ ├── convert.pl
│ │ ├── data_loss.html
│ │ ├── data_loss.json
│ │ ├── data_loss.text
│ │ ├── easy.html
│ │ ├── easy.json
│ │ ├── easy.text
│ │ ├── email.html
│ │ ├── email.json
│ │ ├── email.text
│ │ ├── entities.html
│ │ ├── entities.json
│ │ ├── entities.text
│ │ ├── escaping.html
│ │ ├── escaping.json
│ │ ├── escaping.text
│ │ ├── extra_dl.html
│ │ ├── extra_dl.json
│ │ ├── extra_dl.text
│ │ ├── extra_header_id.html
│ │ ├── extra_header_id.json
│ │ ├── extra_header_id.text
│ │ ├── extra_table1.html
│ │ ├── extra_table1.json
│ │ ├── extra_table1.text
│ │ ├── footnotes.html
│ │ ├── footnotes.json
│ │ ├── footnotes.text
│ │ ├── headers.html
│ │ ├── headers.json
│ │ ├── headers.text
│ │ ├── hex_entities.html
│ │ ├── hex_entities.json
│ │ ├── hex_entities.text
│ │ ├── hrule.html
│ │ ├── hrule.json
│ │ ├── hrule.text
│ │ ├── html2.html
│ │ ├── html2.json
│ │ ├── html2.text
│ │ ├── html3.html
│ │ ├── html3.json
│ │ ├── html3.text
│ │ ├── html4.html
│ │ ├── html4.json
│ │ ├── html4.text
│ │ ├── html5.html
│ │ ├── html5.json
│ │ ├── html5.text
│ │ ├── ie.html
│ │ ├── ie.json
│ │ ├── ie.text
│ │ ├── images.html
│ │ ├── images.json
│ │ ├── images.text
│ │ ├── images2.html
│ │ ├── images2.json
│ │ ├── images2.text
│ │ ├── inline_html.html
│ │ ├── inline_html.json
│ │ ├── inline_html.text
│ │ ├── inline_html2.html
│ │ ├── inline_html2.json
│ │ ├── inline_html2.text
│ │ ├── links.html
│ │ ├── links.json
│ │ ├── links.text
│ │ ├── list1.html
│ │ ├── list1.json
│ │ ├── list1.text
│ │ ├── list2.html
│ │ ├── list2.json
│ │ ├── list2.text
│ │ ├── list3.html
│ │ ├── list3.json
│ │ ├── list3.text
│ │ ├── list4.html
│ │ ├── list4.json
│ │ ├── list4.text
│ │ ├── lists.html
│ │ ├── lists.json
│ │ ├── lists.text
│ │ ├── lists11.html
│ │ ├── lists11.json
│ │ ├── lists11.text
│ │ ├── lists6.html
│ │ ├── lists6.json
│ │ ├── lists6.text
│ │ ├── lists7.html
│ │ ├── lists7.json
│ │ ├── lists7.text
│ │ ├── lists7b.html
│ │ ├── lists7b.json
│ │ ├── lists7b.text
│ │ ├── lists8.html
│ │ ├── lists8.json
│ │ ├── lists8.text
│ │ ├── lists9.html
│ │ ├── lists9.json
│ │ ├── lists9.text
│ │ ├── lists_after_paragraph.html
│ │ ├── lists_after_paragraph.json
│ │ ├── lists_after_paragraph.text
│ │ ├── lists_ol.html
│ │ ├── lists_ol.json
│ │ ├── lists_ol.text
│ │ ├── loss.html
│ │ ├── loss.json
│ │ ├── loss.text
│ │ ├── misc_sw.html
│ │ ├── misc_sw.json
│ │ ├── misc_sw.text
│ │ ├── olist.html
│ │ ├── olist.json
│ │ ├── olist.text
│ │ ├── one.html
│ │ ├── one.json
│ │ ├── one.text
│ │ ├── paragraph.html
│ │ ├── paragraph.json
│ │ ├── paragraph.text
│ │ ├── paragraphs.html
│ │ ├── paragraphs.json
│ │ ├── paragraphs.text
│ │ ├── smartypants.html
│ │ ├── smartypants.json
│ │ ├── smartypants.text
│ │ ├── syntax_hl.html
│ │ ├── syntax_hl.json
│ │ ├── syntax_hl.text
│ │ ├── table_attributes.html
│ │ ├── table_attributes.json
│ │ ├── table_attributes.text
│ │ ├── test.html
│ │ ├── test.json
│ │ ├── test.text
│ │ ├── wrapping.html
│ │ ├── wrapping.json
│ │ ├── wrapping.text
│ │ ├── xml.html
│ │ ├── xml.json
│ │ ├── xml.text
│ │ ├── xml2.html
│ │ ├── xml2.json
│ │ ├── xml2.text
│ │ ├── xml3.html
│ │ ├── xml3.json
│ │ ├── xml3.text
│ │ ├── xml_instruction.html
│ │ ├── xml_instruction.json
│ │ └── xml_instruction.text
│ ├── docs-php-markdown/
│ │ ├── Backslash_escapes.html
│ │ ├── Backslash_escapes.json
│ │ ├── Backslash_escapes.text
│ │ ├── Code_Spans.html
│ │ ├── Code_Spans.json
│ │ ├── Code_Spans.text
│ │ ├── Code_block_in_a_list_item.html
│ │ ├── Code_block_in_a_list_item.json
│ │ ├── Code_block_in_a_list_item.text
│ │ ├── Headers.html
│ │ ├── Headers.json
│ │ ├── Headers.text
│ │ ├── Images_(Untitled).html
│ │ ├── Images_(Untitled).json
│ │ ├── Images_(Untitled).text
│ │ ├── Inline_HTML_(Simple).html
│ │ ├── Inline_HTML_(Simple).json
│ │ ├── Inline_HTML_(Simple).text
│ │ ├── Inline_HTML_comments.html
│ │ ├── Inline_HTML_comments.json
│ │ ├── Inline_HTML_comments.text
│ │ ├── PHP-Specific_Bugs.html
│ │ ├── PHP-Specific_Bugs.json
│ │ ├── PHP-Specific_Bugs.text
│ │ ├── Tight_blocks.html
│ │ ├── Tight_blocks.json
│ │ └── Tight_blocks.text
│ ├── docs-php-markdown-extra/
│ │ ├── Abbr.html
│ │ ├── Abbr.json
│ │ ├── Abbr.text
│ │ ├── Definition_Lists.html
│ │ ├── Definition_Lists.json
│ │ ├── Definition_Lists.text
│ │ ├── Emphasis.html
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Footnotes.html
│ │ ├── Footnotes.json
│ │ ├── Footnotes.text
│ │ ├── Inline_HTML_with_Markdown_content.html
│ │ ├── Inline_HTML_with_Markdown_content.json
│ │ ├── Inline_HTML_with_Markdown_content.text
│ │ ├── Tables.html
│ │ ├── Tables.json
│ │ └── Tables.text
│ ├── docs-php-markdown-todo/
│ │ ├── Email_auto_links.html
│ │ ├── Email_auto_links.json
│ │ ├── Email_auto_links.text
│ │ ├── Emphasis.html
│ │ ├── Emphasis.json
│ │ ├── Emphasis.text
│ │ ├── Inline_HTML_(Span).html
│ │ ├── Inline_HTML_(Span).json
│ │ ├── Inline_HTML_(Span).text
│ │ ├── Ins_and_del.json
│ │ ├── Ins_and_del.text
│ │ ├── Ins_and_del.xhtml
│ │ ├── Links_inline_style.html
│ │ ├── Links_inline_style.json
│ │ ├── Links_inline_style.text
│ │ ├── Nesting.html
│ │ ├── Nesting.json
│ │ ├── Nesting.text
│ │ ├── Parens_in_URL.html
│ │ ├── Parens_in_URL.json
│ │ └── Parens_in_URL.text
│ └── docs-pythonmarkdown2-tm-cases-pass/
│ ├── auto_link.html
│ ├── auto_link.json
│ ├── auto_link.text
│ ├── auto_link_safe_mode.html
│ ├── auto_link_safe_mode.json
│ ├── auto_link_safe_mode.opts
│ ├── auto_link_safe_mode.text
│ ├── basic_safe_mode.html
│ ├── basic_safe_mode.json
│ ├── basic_safe_mode.opts
│ ├── basic_safe_mode.text
│ ├── basic_safe_mode_escape.html
│ ├── basic_safe_mode_escape.json
│ ├── basic_safe_mode_escape.opts
│ ├── basic_safe_mode_escape.text
│ ├── blockquote.html
│ ├── blockquote.json
│ ├── blockquote.text
│ ├── blockquote_with_pre.html
│ ├── blockquote_with_pre.json
│ ├── blockquote_with_pre.text
│ ├── code_block_with_tabs.html
│ ├── code_block_with_tabs.json
│ ├── code_block_with_tabs.text
│ ├── code_safe_emphasis.html
│ ├── code_safe_emphasis.json
│ ├── code_safe_emphasis.opts
│ ├── code_safe_emphasis.text
│ ├── codeblock.html
│ ├── codeblock.json
│ ├── codeblock.text
│ ├── codespans.html
│ ├── codespans.json
│ ├── codespans.text
│ ├── codespans_safe_mode.html
│ ├── codespans_safe_mode.json
│ ├── codespans_safe_mode.opts
│ ├── codespans_safe_mode.text
│ ├── emacs_head_vars.html
│ ├── emacs_head_vars.json
│ ├── emacs_head_vars.text
│ ├── emacs_tail_vars.html
│ ├── emacs_tail_vars.json
│ ├── emacs_tail_vars.text
│ ├── emphasis.html
│ ├── emphasis.json
│ ├── emphasis.text
│ ├── escapes.html
│ ├── escapes.json
│ ├── escapes.text
│ ├── footnotes.html
│ ├── footnotes.json
│ ├── footnotes.opts
│ ├── footnotes.text
│ ├── footnotes_letters.html
│ ├── footnotes_letters.json
│ ├── footnotes_letters.opts
│ ├── footnotes_letters.text
│ ├── footnotes_markup.html
│ ├── footnotes_markup.json
│ ├── footnotes_markup.opts
│ ├── footnotes_markup.text
│ ├── footnotes_safe_mode_escape.html
│ ├── footnotes_safe_mode_escape.json
│ ├── footnotes_safe_mode_escape.opts
│ ├── footnotes_safe_mode_escape.text
│ ├── header.html
│ ├── header.json
│ ├── header.text
│ ├── hr.html
│ ├── hr.json
│ ├── hr.text
│ ├── img_in_link.html
│ ├── img_in_link.json
│ ├── img_in_link.text
│ ├── inline_links.html
│ ├── inline_links.json
│ ├── inline_links.text
│ ├── issue2_safe_mode_borks_markup.html
│ ├── issue2_safe_mode_borks_markup.json
│ ├── issue2_safe_mode_borks_markup.opts
│ ├── issue2_safe_mode_borks_markup.text
│ ├── link_defn_alt_title_delims.html
│ ├── link_defn_alt_title_delims.json
│ ├── link_defn_alt_title_delims.text
│ ├── link_patterns.html
│ ├── link_patterns.json
│ ├── link_patterns.opts
│ ├── link_patterns.text
│ ├── link_patterns_double_hit.html
│ ├── link_patterns_double_hit.json
│ ├── link_patterns_double_hit.opts
│ ├── link_patterns_double_hit.text
│ ├── link_patterns_edge_cases.html
│ ├── link_patterns_edge_cases.json
│ ├── link_patterns_edge_cases.opts
│ ├── link_patterns_edge_cases.text
│ ├── lists.html
│ ├── lists.json
│ ├── lists.text
│ ├── mismatched_footnotes.html
│ ├── mismatched_footnotes.json
│ ├── mismatched_footnotes.opts
│ ├── mismatched_footnotes.text
│ ├── missing_link_defn.html
│ ├── missing_link_defn.json
│ ├── missing_link_defn.text
│ ├── nested_list.html
│ ├── nested_list.json
│ ├── nested_list.text
│ ├── nested_list_safe_mode.html
│ ├── nested_list_safe_mode.json
│ ├── nested_list_safe_mode.opts
│ ├── nested_list_safe_mode.text
│ ├── parens_in_url_4.html
│ ├── parens_in_url_4.json
│ ├── parens_in_url_4.text
│ ├── raw_html.html
│ ├── raw_html.json
│ ├── raw_html.text
│ ├── ref_links.html
│ ├── ref_links.json
│ ├── ref_links.text
│ ├── sublist-para.html
│ ├── sublist-para.json
│ ├── sublist-para.text
│ ├── syntax_color.html
│ ├── syntax_color.json
│ ├── syntax_color.opts
│ ├── syntax_color.text
│ ├── tricky_anchors.html
│ ├── tricky_anchors.json
│ ├── tricky_anchors.text
│ ├── underline_in_autolink.html
│ ├── underline_in_autolink.json
│ └── underline_in_autolink.text
├── html_renderer.t.js
├── interface.t.js
├── regressions.t.js
└── render_tree.t.js
SYMBOL INDEX (25 symbols across 11 files)
FILE: inc/tasks/build_markdown.js
function convert (line 33) | function convert( name, path, contents ) {
FILE: src/dialects/dialect_helpers.js
function Block (line 30) | function Block() {}
function Inline (line 32) | function Inline() {}
FILE: src/dialects/gruber.js
function regex_for_depth (line 146) | function regex_for_depth( depth ) {
function expand_tab (line 155) | function expand_tab( input ) {
function add (line 161) | function add(li, loose, inline, nl) {
function get_contained_blocks (line 187) | function get_contained_blocks( depth, blocks ) {
function paragraphify (line 208) | function paragraphify(s, i, stack) {
function make_list (line 232) | function make_list( m ) {
function add (line 519) | function add(x) {
function strong_em (line 756) | function strong_em( tag, md ) {
function create_attrs (line 813) | function create_attrs() {
function create_reference (line 829) | function create_reference(attrs, m) {
FILE: src/dialects/maruku.js
function split_meta_hash (line 34) | function split_meta_hash( meta_string ) {
FILE: src/markdown_helpers.js
function mk_block_toSource (line 8) | function mk_block_toSource() {
function mk_block_inspect (line 19) | function mk_block_inspect() {
FILE: src/parser.js
function count_lines (line 28) | function count_lines( str ) {
FILE: src/render_tree.js
function escapeHTML (line 91) | function escapeHTML( text ) {
function render_tree (line 103) | function render_tree( jsonml ) {
function convert_tree_to_html (line 138) | function convert_tree_to_html( tree, references, options ) {
function merge_text_nodes (line 277) | function merge_text_nodes( jsonml ) {
FILE: test/features.t.js
function test_dialect (line 3) | function test_dialect( dialect, features ) {
FILE: test/interface.t.js
function clone_array (line 4) | function clone_array( input ) {
FILE: test/regressions.t.js
function test (line 11) | function test(name, cb) {
FILE: test/render_tree.t.js
function clone_array (line 4) | function clone_array( input ) {
Condensed preview — 786 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (583K chars).
[
{
"path": ".gitignore",
"chars": 68,
"preview": ".*.swp\n.DS_Store\n/node_modules/\n/npm-debug.log\ndist\nlib/markdown.js\n"
},
{
"path": ".travis.yml",
"chars": 49,
"preview": "language: node_js\nnode_js:\n - \"0.10\"\n - \"0.11\"\n"
},
{
"path": "Changes.md",
"chars": 3960,
"preview": "# Changelog for markdown\n\n## vNEXT - ???\n\n- **Big change**: Drop official support for Node 0.8\n- Use JSHint to validate "
},
{
"path": "Gruntfile.js",
"chars": 2330,
"preview": "module.exports = function(grunt) {\n\n var pkg = grunt.file.readJSON('package.json');\n\n grunt.initConfig({\n pkg: pkg,"
},
{
"path": "README.md",
"chars": 8759,
"preview": "[](http://badge.fury.io/js/markdown)\n[ {\n \"use strict\";\n\n var fs = require(\"fs\"),\n markdown = require(\"markdown\").markdow"
},
{
"path": "bower.json",
"chars": 624,
"preview": "{\n \"name\": \"markdown\",\n \"homepage\": \"https://github.com/evilstreak/markdown-js\",\n \"_source\": \"git://github.com/"
},
{
"path": "inc/footer-node.js",
"chars": 245,
"preview": "\n expose.Markdown = Markdown;\n expose.parse = Markdown.parse;\n expose.toHTML = Markdown.toHTML;\n expose.toHTMLTree ="
},
{
"path": "inc/footer-web.js",
"chars": 304,
"preview": "\n expose.Markdown = Markdown;\n expose.parse = Markdown.parse;\n expose.toHTML = Markdown.toHTML;\n expose.toHTMLTree ="
},
{
"path": "inc/header.js",
"chars": 285,
"preview": "/*!\n * Markdown\n * Released under MIT license\n * Copyright (c) 2009-2010 Dominic Baggott\n * Copyright (c) 2009-2010 Ash "
},
{
"path": "inc/tasks/build_markdown.js",
"chars": 7756,
"preview": "/**\n Tasks cribbed from jQuery to handle building custom markdown parsers.\n\n*/\n\nmodule.exports = function( grunt ) {\n\n "
},
{
"path": "lib/index.js",
"chars": 143,
"preview": "// super simple module for the most common nodejs use case.\nexports.markdown = require(\"./markdown\");\nexports.parse = ex"
},
{
"path": "package.json",
"chars": 1478,
"preview": "{\n \"name\": \"markdown\",\n \"version\": \"0.6.0-beta1\",\n \"description\": \"A sensible Markdown parser for javascript\",\n \"key"
},
{
"path": "seed.yml",
"chars": 118,
"preview": "---\n name: markdown-js\n description: JavaScript implementation of Markdown\n tags: markdown parser\n version: 0.1.2\n"
},
{
"path": "src/core.js",
"chars": 1719,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\n\ndefine([], function() {\n\n /**\n * clas"
},
{
"path": "src/dialects/dialect_helpers.js",
"chars": 1078,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\ndefine([], function (w) {\n\n var DialectH"
},
{
"path": "src/dialects/gruber.js",
"chars": 29725,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\ndefine(['../markdown_helpers', './dialect"
},
{
"path": "src/dialects/maruku.js",
"chars": 8763,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\ndefine(['../markdown_helpers', './dialect"
},
{
"path": "src/markdown.js",
"chars": 293,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\n\n// Include all our dependencies and retu"
},
{
"path": "src/markdown_helpers.js",
"chars": 2208,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\n\ndefine([], function (w) {\n\n var Markdow"
},
{
"path": "src/parser.js",
"chars": 6299,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module) }\n\ndefine(['./markdown_helpers', './core'],"
},
{
"path": "src/render_tree.js",
"chars": 8268,
"preview": "if (typeof define !== 'function') { var define = require('amdefine')(module); }\n\ndefine(['./core', './markdown_helpers']"
},
{
"path": "test/features/blockquotes/contains_code.json",
"chars": 214,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"There's a code block in here:\"\n ],\n [\"pre\",\n [\"code\",\n \"SET"
},
{
"path": "test/features/blockquotes/contains_code.text",
"chars": 100,
"preview": "> There's a code block in here:\n>\n> SET foo = TRUE\n>\n> IF foo GOTO 10\n>\n> Wasn't that nice?\n"
},
{
"path": "test/features/blockquotes/lazy_wrapping.json",
"chars": 147,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"If you're too lazy\\nto wrap your code nicely\"\n ],\n [\"p\",\n \"This wi"
},
{
"path": "test/features/blockquotes/lazy_wrapping.text",
"chars": 70,
"preview": "> If you're too lazy\nto wrap your code nicely\n\n> This will still work\n"
},
{
"path": "test/features/blockquotes/leading_paras.json",
"chars": 178,
"preview": "[\"html\",\n [\"p\",\n \"Amy wrote:\"\n ],\n [\"blockquote\",\n [\"p\",\n \"No wai?\"\n ]\n ],\n [\"p\",\n \"Bob wrote:\"\n "
},
{
"path": "test/features/blockquotes/leading_paras.text",
"chars": 43,
"preview": "Amy wrote:\n> No wai?\n\nBob wrote:\n> Ya rly!\n"
},
{
"path": "test/features/blockquotes/nested.json",
"chars": 151,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"One\"\n ],\n [\"blockquote\",\n [\"p\",\n \"Two\"\n ]\n ],\n ["
},
{
"path": "test/features/blockquotes/nested.text",
"chars": 26,
"preview": "> One\n>\n> > Two\n>\n> Three\n"
},
{
"path": "test/features/blockquotes/simple.json",
"chars": 67,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"Blockquote\"\n ]\n ]\n]\n"
},
{
"path": "test/features/blockquotes/simple.text",
"chars": 13,
"preview": "> Blockquote\n"
},
{
"path": "test/features/blockquotes/spaceless.json",
"chars": 83,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"blockquote\\nwithout spaces\"\n ]\n ]\n]\n"
},
{
"path": "test/features/blockquotes/spaceless.text",
"chars": 28,
"preview": ">blockquote\n>without spaces\n"
},
{
"path": "test/features/blockquotes/spaces_before.json",
"chars": 61,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"evil\"\n ]\n ]\n]\n"
},
{
"path": "test/features/blockquotes/spaces_before.text",
"chars": 8,
"preview": " > evil"
},
{
"path": "test/features/blockquotes/threequotes.json",
"chars": 102,
"preview": "[ \"html\",\n [ \"blockquote\",\n [ \"p\", \"this is\" ],\n [ \"p\", \"three\" ],\n [ \"p\", \"quotes\" ]\n ]\n]\n"
},
{
"path": "test/features/blockquotes/threequotes.text",
"chars": 29,
"preview": "> this is\n\n> three\n\n> quotes\n"
},
{
"path": "test/features/code/blank_lines.json",
"chars": 319,
"preview": "[\"html\",\n [\"p\",\n \"This block is composed of three lines:\"\n ],\n [\"pre\",\n [\"code\",\n \"one\\n\\nthree\"\n ]\n ]"
},
{
"path": "test/features/code/blank_lines.text",
"chars": 144,
"preview": "This block is composed of three lines:\n\n\tone\n\t\n\tthree\n\nThis block is composed of 5\n\n\t\n\tone\n\t\n\t\n\tfour\n\t\n\nThis block is co"
},
{
"path": "test/features/code/block.json",
"chars": 158,
"preview": "[\"html\",\n [\"p\",\n \"Here is an example of AppleScript:\"\n ],\n [\"pre\",\n [\"code\",\n \"tell application \\\"Foo\\\"\\n "
},
{
"path": "test/features/code/block.text",
"chars": 99,
"preview": "Here is an example of AppleScript:\n\n tell application \"Foo\"\n beep\n end tell\n \ttab\n\n"
},
{
"path": "test/features/code/embedded_backtick.json",
"chars": 110,
"preview": "[\"html\",\n [\"p\",\n \"This is a \",\n [\"code\",\n \"code span with an `embedded` backtick\"],\n \".\"\n ]\n]\n"
},
{
"path": "test/features/code/embedded_backtick.text",
"chars": 53,
"preview": "This is a ``code span with an `embedded` backtick``.\n"
},
{
"path": "test/features/code/horizontal_rules.json",
"chars": 135,
"preview": "[\"html\",\n [\"pre\",\n [\"code\",\n \"fsfsfsf\\n* * *\\n\\n***\\n\\n*****\\n\\n- - -\\n\\n--------------------------------------"
},
{
"path": "test/features/code/horizontal_rules.text",
"chars": 98,
"preview": " fsfsfsf\n * * *\n\n ***\n\n *****\n\n - - -\n\n ---------------------------------------\n"
},
{
"path": "test/features/code/in_lists.json",
"chars": 167,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n [\"p\",\n \"Loose list\"\n ],\n [\"pre\",\n [\"code\",\n \"some co"
},
{
"path": "test/features/code/in_lists.text",
"chars": 53,
"preview": " * Loose list\n\n some code\n\n more code\n"
},
{
"path": "test/features/code/inline.json",
"chars": 79,
"preview": "[\"html\",\n [\"p\",\n [\"code\",\n \"This\"\n ],\n \" is a code span.\"\n ]\n]\n"
},
{
"path": "test/features/code/inline.text",
"chars": 23,
"preview": "`This` is a code span.\n"
},
{
"path": "test/features/code/inline_multiline.json",
"chars": 85,
"preview": "[\"html\",\n [\"p\",\n \"foo \",\n [\"code\",\n \"code\\ncode\"\n ],\n \" bar\"\n ]\n]\n"
},
{
"path": "test/features/code/inline_multiline.text",
"chars": 20,
"preview": "foo `code\ncode` bar\n"
},
{
"path": "test/features/code/trailing_para.json",
"chars": 133,
"preview": "[\"html\",\n [\"p\",\n \"Paragraph above\"\n ],\n [\"pre\",\n [\"code\",\n \"Code block\"\n ]\n ],\n [\"p\",\n \"Paragraph "
},
{
"path": "test/features/code/trailing_para.text",
"chars": 48,
"preview": "Paragraph above\n\n Code block\nParagraph below\n"
},
{
"path": "test/features/code/with_greater_than.json",
"chars": 47,
"preview": "[\"html\",\n [\"pre\",\n \t[\"code\", \"> meep\"]\n ]\n]\n"
},
{
"path": "test/features/code/with_greater_than.text",
"chars": 10,
"preview": " > meep"
},
{
"path": "test/features/definition_lists/inline.json",
"chars": 259,
"preview": "[\"html\",\n [\"dl\",\n [\"dt\",\n \"a term\"\n ],\n [\"dd\",\n [\"em\",\n \"emphasised\"\n ],\n \" definit"
},
{
"path": "test/features/definition_lists/inline.text",
"chars": 73,
"preview": "a term\n: *emphasised* definition.\n\nanother term\n: **strong** definition.\n"
},
{
"path": "test/features/definition_lists/long.json",
"chars": 236,
"preview": "[\"html\",\n [\"dl\",\n [\"dt\",\n \"first term\"\n ],\n [\"dd\",\n \"the quick brown fox jumps\\nover the lazy dog\"\n "
},
{
"path": "test/features/definition_lists/long.text",
"chars": 118,
"preview": "first term\n: the quick brown fox jumps\n over the lazy dog\n\nsecond term\n: pack my box with five\ndozen liquor jugs\n"
},
{
"path": "test/features/definition_lists/multiple_definitions.json",
"chars": 277,
"preview": "[\"html\",\n [\"dl\",\n [\"dt\",\n \"fruit\"\n ],\n [\"dd\",\n \"apple\"\n ],\n [\"dd\",\n \"banana\"\n ],\n ["
},
{
"path": "test/features/definition_lists/multiple_definitions.text",
"chars": 59,
"preview": "fruit\n: apple\n: banana\n: pear\n\nanimal\n: cow\n: duck\n: horse\n"
},
{
"path": "test/features/definition_lists/multiple_terms.json",
"chars": 226,
"preview": "[\"html\",\n [\"dl\",\n [\"dt\",\n \"fruit\"\n ],\n [\"dt\",\n \"vegetable\"\n ],\n [\"dd\",\n \"tomato\"\n ],\n "
},
{
"path": "test/features/definition_lists/multiple_terms.text",
"chars": 52,
"preview": "fruit\nvegetable\n: tomato\n\nanimal\nmineral\n: pet rock\n"
},
{
"path": "test/features/definition_lists/tight.json",
"chars": 210,
"preview": "[\"html\",\n [\"dl\",\n [\"dt\",\n \"one\"\n ],\n [\"dd\",\n \"alpha\"\n ],\n [\"dt\",\n \"two\"\n ],\n [\"dd\","
},
{
"path": "test/features/definition_lists/tight.text",
"chars": 39,
"preview": "one\n: alpha\n\ntwo\n: beta\n\nthree\n: gamma\n"
},
{
"path": "test/features/emphasis/multiple_lines.json",
"chars": 127,
"preview": "[\"html\",\n [\"p\",\n \"You can \",\n [\"em\",\n \"start emphasis on one line,\\nand finish it\"\n ],\n \" on another.\""
},
{
"path": "test/features/emphasis/multiple_lines.text",
"chars": 64,
"preview": "You can *start emphasis on one line,\nand finish it* on another.\n"
},
{
"path": "test/features/emphasis/nested.json",
"chars": 274,
"preview": "[\"html\",\n [\"p\",\n \"You can \",\n [\"strong\",\n \"nest \",\n [\"em\",\n \"em\"\n ],\n \" inside strong\""
},
{
"path": "test/features/emphasis/nested.text",
"chars": 75,
"preview": "You can **nest *em* inside strong**.\n\nYou can *nest **strong** inside em*.\n"
},
{
"path": "test/features/emphasis/simple.json",
"chars": 257,
"preview": "[\"html\",\n [\"p\",\n \"Emphasis can be \",\n [\"em\",\n \"weak\"\n ],\n \" or \",\n [\"strong\",\n \"strong\"\n ],"
},
{
"path": "test/features/emphasis/simple.text",
"chars": 74,
"preview": "Emphasis can be *weak* or **strong**.\n\nIt can _even_ use __underscores__.\n"
},
{
"path": "test/features/headers/atx.json",
"chars": 158,
"preview": "[\"html\",\n [\"h1\",\n \"One\"\n ],\n [\"h2\",\n \"Two\"\n ],\n [\"h3\",\n \"Three\"\n ],\n [\"h4\",\n \"Four\"\n ],\n [\"h5\",\n "
},
{
"path": "test/features/headers/atx.text",
"chars": 60,
"preview": "# One\n\n## Two\n\n### Three\n\n#### Four\n\n##### Five\n\n###### Six\n"
},
{
"path": "test/features/headers/atx_closing_hashes.json",
"chars": 84,
"preview": "[\"html\",\n [\"h1\",\n \"One\"\n ],\n [\"h2\",\n \"Two\"\n ],\n [\"h3\",\n \"Three\"\n ]\n]\n"
},
{
"path": "test/features/headers/atx_closing_hashes.text",
"chars": 36,
"preview": "# One #\n\n## Two #####\n\n### Three ##\n"
},
{
"path": "test/features/headers/inline.json",
"chars": 47,
"preview": "[\"html\",\n [\"h2\",\n [\"strong\", \"Bold\"]\n ]\n]\n"
},
{
"path": "test/features/headers/inline.text",
"chars": 17,
"preview": "**Bold**\n--------"
},
{
"path": "test/features/headers/setext.json",
"chars": 58,
"preview": "[\"html\",\n [\"h1\",\n \"One\"\n ],\n [\"h2\",\n \"Two\"\n ]\n]\n"
},
{
"path": "test/features/headers/setext.text",
"chars": 17,
"preview": "One\n===\n\nTwo\n---\n"
},
{
"path": "test/features/headers/trailing_paras.json",
"chars": 178,
"preview": "[\"html\",\n [\"h1\",\n \"Header\"\n ],\n [\"p\",\n \"Paragraph\"\n ],\n [\"h2\",\n \"Header\"\n ],\n [\"p\",\n \"Paragraph\"\n ],"
},
{
"path": "test/features/headers/trailing_paras.text",
"chars": 71,
"preview": "Header\n======\nParagraph\n\nHeader\n------\nParagraph\n\n### Header\nParagraph\n"
},
{
"path": "test/features/horizontal_rules/abutting_blocks.json",
"chars": 246,
"preview": "[\"html\",\n [\"p\",\n \"para\"\n ],\n [\"hr\"],\n [\"ul\",\n [\"li\",\n \"list\"\n ]\n ],\n [\"hr\"],\n [\"ul\",\n [\"li\",\n "
},
{
"path": "test/features/horizontal_rules/abutting_blocks.text",
"chars": 69,
"preview": "para\n***\n* list\n - - -\n* list before para\n\n para\n - - -\n> blockquote\n"
},
{
"path": "test/features/horizontal_rules/dashes.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/dashes.text",
"chars": 4,
"preview": "---\n"
},
{
"path": "test/features/horizontal_rules/front_matter.json",
"chars": 138,
"preview": "[\"html\",\n [\"hr\"],\n [\"p\",\n \"layout: post\\ntitle: A title\"\n ],\n [\"hr\"],\n [\"p\",\n \"Pack my box with five dozen li"
},
{
"path": "test/features/horizontal_rules/front_matter.text",
"chars": 78,
"preview": "---\nlayout: post\ntitle: A title\n---\n\nPack my box with five dozen liquor jugs.\n"
},
{
"path": "test/features/horizontal_rules/leading_spaces.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/leading_spaces.text",
"chars": 8,
"preview": " * * *\n"
},
{
"path": "test/features/horizontal_rules/long.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/long.text",
"chars": 22,
"preview": "*********************\n"
},
{
"path": "test/features/horizontal_rules/long_loose.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/long_loose.text",
"chars": 22,
"preview": "* * * * * * * * * * *\n"
},
{
"path": "test/features/horizontal_rules/loose_dashes.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/loose_dashes.text",
"chars": 6,
"preview": "- - -\n"
},
{
"path": "test/features/horizontal_rules/loose_stars.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/loose_stars.text",
"chars": 6,
"preview": "* * *\n"
},
{
"path": "test/features/horizontal_rules/loose_underscores.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/loose_underscores.text",
"chars": 6,
"preview": "_ _ _\n"
},
{
"path": "test/features/horizontal_rules/stars.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/stars.text",
"chars": 4,
"preview": "***\n"
},
{
"path": "test/features/horizontal_rules/underscores.json",
"chars": 20,
"preview": "[\"html\",\n [\"hr\"]\n]\n"
},
{
"path": "test/features/horizontal_rules/underscores.text",
"chars": 4,
"preview": "___\n"
},
{
"path": "test/features/images/basic.json",
"chars": 102,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/path/to/img.jpg\",\n \"alt\": \"Alt text\"\n } ]\n ]\n]\n"
},
{
"path": "test/features/images/basic.text",
"chars": 30,
"preview": "\n"
},
{
"path": "test/features/images/crotcheted_url.json",
"chars": 91,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/url/\",\n \"alt\": \"alt text\"\n } ]\n ]\n]\n"
},
{
"path": "test/features/images/crotcheted_url.text",
"chars": 21,
"preview": "\n"
},
{
"path": "test/features/images/crotcheted_url_with_title.json",
"chars": 122,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/url/\",\n \"alt\": \"alt text\",\n \"title\": \"with a title\"\n } ]\n ]\n"
},
{
"path": "test/features/images/crotcheted_url_with_title.text",
"chars": 36,
"preview": "\n"
},
{
"path": "test/features/images/empty.json",
"chars": 83,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"\",\n \"alt\": \"Empty\"\n } ]\n ]\n]\n"
},
{
"path": "test/features/images/empty.text",
"chars": 11,
"preview": "![Empty]()\n"
},
{
"path": "test/features/images/incomplete_image.json",
"chars": 81,
"preview": "[ \"html\",\n [ \"p\",\n \"](https://link-url)\n"
},
{
"path": "test/features/images/ref.json",
"chars": 102,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/path/to/img.jpg\",\n \"alt\": \"Alt text\"\n } ]\n ]\n]\n"
},
{
"path": "test/features/images/ref.text",
"chars": 43,
"preview": "![Alt text] [img]\n\n[img]: /path/to/img.jpg\n"
},
{
"path": "test/features/images/spaces_in_href.json",
"chars": 101,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"path to img.jpg\",\n \"alt\": \"Alt text\"\n } ]\n ]\n]\n"
},
{
"path": "test/features/images/spaces_in_href.text",
"chars": 29,
"preview": "\n"
},
{
"path": "test/features/images/spaces_round_title.json",
"chars": 136,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/url/\",\n \"alt\": \"alt text\",\n \"title\": \"title has spaces afterward"
},
{
"path": "test/features/images/spaces_round_title.text",
"chars": 51,
"preview": "\n"
},
{
"path": "test/features/images/title.json",
"chars": 135,
"preview": "[\"html\",\n [\"p\",\n [\"img\", {\n \"src\": \"/path/to/img.jpg\",\n \"alt\": \"Alt text\",\n \"title\": \"Optional title\""
},
{
"path": "test/features/images/title.text",
"chars": 47,
"preview": "\n"
},
{
"path": "test/features/linebreaks/simple.json",
"chars": 93,
"preview": "[\"html\",\n [\"p\",\n \"The quick brown fox\",\n [\"br\"],\n \"jumps over the lazy dog.\"\n ]\n]\n"
},
{
"path": "test/features/linebreaks/simple.text",
"chars": 47,
"preview": "The quick brown fox \njumps over the lazy dog.\n"
},
{
"path": "test/features/links/apostrophe.json",
"chars": 143,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\" : \"http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.3\" },\n \"Pos"
},
{
"path": "test/features/links/apostrophe.text",
"chars": 77,
"preview": "[Postgres 9.3](http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.3)\n"
},
{
"path": "test/features/links/autolink_email.json",
"chars": 178,
"preview": "[\"html\",\n [\"p\",\n \"Email addresses written like \",\n [\"a\",\n { \"href\" : \"mailto:bill@microsoft.com\" },\n \"b"
},
{
"path": "test/features/links/autolink_email.text",
"chars": 69,
"preview": "Email addresses written like <bill@microsoft.com> get autolinkified.\n"
},
{
"path": "test/features/links/autolink_in_code.json",
"chars": 114,
"preview": "[\"html\",\n [\"p\",\n \"Autolinks don't happen inside code: \",\n [\"code\",\n \"<http://google.com>\"\n ]\n ]\n]\n"
},
{
"path": "test/features/links/autolink_in_code.text",
"chars": 58,
"preview": "Autolinks don't happen inside code: `<http://google.com>`\n"
},
{
"path": "test/features/links/autolink_url.json",
"chars": 150,
"preview": "[\"html\",\n [\"p\",\n \"URLs like \",\n [\"a\",\n { \"href\" : \"http://google.com\" },\n \"http://google.com\"\n ],\n "
},
{
"path": "test/features/links/autolink_url.text",
"chars": 49,
"preview": "URLs like <http://google.com> get autolinkified.\n"
},
{
"path": "test/features/links/broken_brackets.json",
"chars": 28,
"preview": "[\"html\",\n [\"p\", \"[[][]\"]\n]\n"
},
{
"path": "test/features/links/broken_brackets.text",
"chars": 6,
"preview": "[[][]\n"
},
{
"path": "test/features/links/broken_link.json",
"chars": 53,
"preview": "[\"html\",\n [\"p\", \"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]\"]\n]\n"
},
{
"path": "test/features/links/broken_link.text",
"chars": 30,
"preview": "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]"
},
{
"path": "test/features/links/case_insensitive.json",
"chars": 306,
"preview": "[\"html\",\n [\"p\",\n \"This is \",\n [\"a\",\n { \"href\" : \"http://google.com\" },\n \"google\"\n ],\n \". \",\n ["
},
{
"path": "test/features/links/case_insensitive.text",
"chars": 98,
"preview": "This is [google]. [Google] and [this][GoOgLe] are the same thing too\n\n[GOOGLE]: http://google.com\n"
},
{
"path": "test/features/links/escaped_broken_link.json",
"chars": 65,
"preview": "[\"html\",\n [\"p\", \"[][][][][][][][][][][][][][][][][][][][][]\"]\n]\n"
},
{
"path": "test/features/links/escaped_broken_link.text",
"chars": 63,
"preview": "[\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\][\\]"
},
{
"path": "test/features/links/implicit.json",
"chars": 215,
"preview": "[\"html\",\n [\"p\",\n \"These \",\n [\"a\",\n { \"href\" : \"http://links.com\" },\n \"links\"\n ],\n \" use \",\n [\""
},
{
"path": "test/features/links/implicit.text",
"chars": 102,
"preview": "These [links][] use [implicit] references.\n\n[links]: http://links.com\n[implicit]: http://implicit.com\n"
},
{
"path": "test/features/links/in_blockquotes.json",
"chars": 116,
"preview": "[\"html\",\n [\"blockquote\",\n [\"p\",\n \"Let's fork this repo!\"\n ],\n [\"p\",\n \"[markdown][]\"\n ]\n ]\n]\n"
},
{
"path": "test/features/links/in_blockquotes.text",
"chars": 99,
"preview": "> Let's fork this repo!\n>\n> [markdown][]\n>\n> [markdown]: https://github.com/evilstreak/markdown-js\n"
},
{
"path": "test/features/links/in_brackets.json",
"chars": 213,
"preview": "[\"html\",\n [\"p\",\n \"Lorem ipsum (\",\n [\"a\", {\"href\": \"http://www.lipsum.com/\"}, \"lorem ipsum\"],\n \") dolar sit amu"
},
{
"path": "test/features/links/in_brackets.text",
"chars": 100,
"preview": "Lorem ipsum ([lorem ipsum](http://www.lipsum.com/)) dolar sit amut\n\n([Inline link](/url()((test))))\n"
},
{
"path": "test/features/links/inline.json",
"chars": 119,
"preview": "[\"html\",\n [\"p\",\n \"An \",\n [\"a\",\n { \"href\" : \"http://inline.com\" },\n \"inline\"\n ],\n \" link.\"\n ]\n]\n"
},
{
"path": "test/features/links/inline.text",
"chars": 37,
"preview": "An [inline](http://inline.com) link.\n"
},
{
"path": "test/features/links/inline_with_newline.json",
"chars": 135,
"preview": "[\"html\",\n [\"p\",\n \"An \",\n [\"a\",\n { \"href\" : \"http://inline.com\" },\n \"inline\\nlink\"\n ],\n \" with a n"
},
{
"path": "test/features/links/inline_with_newline.text",
"chars": 52,
"preview": "An [inline\nlink](http://inline.com) with a newline.\n"
},
{
"path": "test/features/links/inline_with_title.json",
"chars": 162,
"preview": "[\"html\",\n [\"p\",\n \"An \",\n [\"a\",\n { \"href\" : \"http://inline.com\",\n \"title\" : \"le title\" },\n \"inlin"
},
{
"path": "test/features/links/inline_with_title.text",
"chars": 61,
"preview": "An [inline link](http://inline.com \"le title\") with a title.\n"
},
{
"path": "test/features/links/missing_references.json",
"chars": 162,
"preview": "[\"html\",\n [\"p\",\n \"Link with [missing][id] reference\"\n ],\n [\"p\",\n \"Link with [empty][] reference\"\n ],\n [\"p\",\n "
},
{
"path": "test/features/links/missing_references.text",
"chars": 97,
"preview": "Link with [missing][id] reference\n\nLink with [empty][] reference\n\nLink with [inferred] reference\n"
},
{
"path": "test/features/links/no_closing.json",
"chars": 34,
"preview": "[\"html\",\n [\"p\",\n \"[[1]\"\n ]\n]\n"
},
{
"path": "test/features/links/no_closing.text",
"chars": 5,
"preview": "[[1]\n"
},
{
"path": "test/features/links/parens_escaped_inline.json",
"chars": 146,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\": \"/url(test)\",\n \"title\": \"title\" },\n \"Inline link\"\n ],\n \" wi"
},
{
"path": "test/features/links/parens_escaped_inline.text",
"chars": 57,
"preview": "[Inline link](/url\\(test\\) \"title\") with escaped parens.\n"
},
{
"path": "test/features/links/parens_inline.json",
"chars": 150,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\": \"/url(test)\",\n \"title\": \"title\" },\n \"Inline link\"\n ],\n \" wi"
},
{
"path": "test/features/links/parens_inline.text",
"chars": 59,
"preview": "[Inline link](/url(test) \"title\") with non-escaped parens.\n"
},
{
"path": "test/features/links/parens_reference.json",
"chars": 153,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\": \"/url(test)\",\n \"title\": \"title\" },\n \"Reference link\"\n ],\n \""
},
{
"path": "test/features/links/parens_reference.text",
"chars": 70,
"preview": "[Reference link][1] with non-escaped parens.\n\n[1]: /url(test) \"title\"\n"
},
{
"path": "test/features/links/ref_reuse.json",
"chars": 188,
"preview": "[\"html\",\n [\"p\",\n \"Two \",\n [\"a\",\n { \"href\" : \"http://google.com\" },\n \"links\"\n ],\n \", one \",\n [\""
},
{
"path": "test/features/links/ref_reuse.text",
"chars": 56,
"preview": "Two [links][id], one [ref][id]\n\n[id]: http://google.com\n"
},
{
"path": "test/features/links/ref_with_image_ref.json",
"chars": 145,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n {\"href\": \"http://link_url\"},\n [\"img\",\n {\"src\": \"http://image_url\", \"alt\": \"alt "
},
{
"path": "test/features/links/ref_with_image_ref.text",
"chars": 75,
"preview": "[![alt text][id_2]][id_1]\n\n[id_1]: http://link_url\n[id_2]: http://image_url"
},
{
"path": "test/features/links/reference.json",
"chars": 132,
"preview": "[\"html\",\n [\"p\",\n \"A \",\n [\"a\",\n { \"href\" : \"http://reference.com\" },\n \"link using a reference\"\n ],\n "
},
{
"path": "test/features/links/reference.text",
"chars": 58,
"preview": "A [link using a reference][1].\n\n[1]: http://reference.com\n"
},
{
"path": "test/features/links/reference_missing.json",
"chars": 109,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\" : \"http://example.com\" },\n \"hi\"\n ]\n ],\n [\"ul\", [\"li\"]]\n]\n"
},
{
"path": "test/features/links/reference_missing.text",
"chars": 43,
"preview": "[hi][link]\n\n - [link]: http://example.com\n"
},
{
"path": "test/features/links/reference_with_newline.json",
"chars": 118,
"preview": "[\"html\",\n [\"p\",\n \"This one has a \",\n [\"a\",\n { \"href\" : \"/foo\" },\n \"line\\nbreak\"\n ],\n \".\"\n ]\n]\n"
},
{
"path": "test/features/links/reference_with_newline.text",
"chars": 49,
"preview": "This one has a [line\nbreak].\n\n[line break]: /foo\n"
},
{
"path": "test/features/links/reference_with_newline_and_space.json",
"chars": 119,
"preview": "[\"html\",\n [\"p\",\n \"This one has a \",\n [\"a\",\n { \"href\" : \"/foo\" },\n \"line \\nbreak\"\n ],\n \".\"\n ]\n]\n"
},
{
"path": "test/features/links/reference_with_newline_and_space.text",
"chars": 50,
"preview": "This one has a [line \nbreak].\n\n[line break]: /foo\n"
},
{
"path": "test/features/links/reference_with_quote.json",
"chars": 116,
"preview": "[\"html\",\n [\"p\",\n \"Foo \", [ \"a\", {\"href\": \"/url/\", \"title\": \"Title with \\\"quotes\\\" inside\"}, \"bar\" ], \".\"\n ]\n]\n"
},
{
"path": "test/features/links/reference_with_quote.text",
"chars": 58,
"preview": "Foo [bar][].\n\n [bar]: /url/ \"Title with \"quotes\" inside\"\n"
},
{
"path": "test/features/links/reference_with_space.json",
"chars": 153,
"preview": "[\"html\",\n [\"p\",\n \"A \",\n [\"a\",\n { \"href\" : \"http://reference.com\" },\n \"link using a reference\"\n ],\n "
},
{
"path": "test/features/links/reference_with_space.text",
"chars": 80,
"preview": "A [link using a reference] [1] separated by a space.\n\n[1]: http://reference.com\n"
},
{
"path": "test/features/links/spaces_in_url.json",
"chars": 126,
"preview": "[\"html\",\n [\"p\",\n [\"a\",\n { \"href\" : \"Link to file/Lorem Ipsum.txt\", \"title\" : \"Alt2\" },\n \"link text\"\n ]\n"
},
{
"path": "test/features/links/spaces_in_url.text",
"chars": 49,
"preview": "[link text](Link to file/Lorem Ipsum.txt \"Alt2\")\n"
},
{
"path": "test/features/lists/bullet_types.json",
"chars": 219,
"preview": "[\"html\",\n [\"p\",\n \"Stars\"\n ],\n [\"ul\",\n [\"li\",\n \"star\"\n ]\n ],\n [\"p\",\n \"Dashes\"\n ],\n [\"ul\",\n [\"l"
},
{
"path": "test/features/lists/bullet_types.text",
"chars": 46,
"preview": "Stars\n\n* star\n\nDashes\n\n- dash\n\nPluses\n\n+ plus\n"
},
{
"path": "test/features/lists/hr_abutting.json",
"chars": 94,
"preview": "[\"html\",\n [\"ul\",\n [ \"li\", \"foo\" ],\n [ \"li\", \"bar\" ]\n ],\n [\"hr\"],\n [\"p\", \"after\"]\n]\n\n"
},
{
"path": "test/features/lists/hr_abutting.text",
"chars": 27,
"preview": "* foo\n* bar\n\n * * *\nafter\n\n"
},
{
"path": "test/features/lists/hr_inside.json",
"chars": 101,
"preview": "[\"html\",\n [\"ul\",\n [ \"li\",\n [\"p\", \"before\"],\n [\"hr\"],\n [\"p\", \"after\"]\n ]\n ]\n]\n\n"
},
{
"path": "test/features/lists/hr_inside.text",
"chars": 33,
"preview": "* before\n\n - - - -\n after\n\n"
},
{
"path": "test/features/lists/lazy_wrapping.json",
"chars": 144,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n \"If you're too\\nlazy to wrap your\"\n ],\n [\"li\",\n \"Lists nicely, this\\nwill "
},
{
"path": "test/features/lists/lazy_wrapping.text",
"chars": 71,
"preview": "* If you're too\nlazy to wrap your\n* Lists nicely, this\nwill still work\n"
},
{
"path": "test/features/lists/leading_whitespace.json",
"chars": 87,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n \"white\"\n ],\n [\"li\",\n \"space\"\n ]\n ]\n]\n"
},
{
"path": "test/features/lists/leading_whitespace.text",
"chars": 20,
"preview": " * white\n * space\n"
},
{
"path": "test/features/lists/loose.json",
"chars": 352,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n [\"p\",\n \"the quick brown fox jumps\\nover the lazy dog\"\n ]\n ],\n [\"li\""
},
{
"path": "test/features/lists/loose.text",
"chars": 185,
"preview": " * the quick brown fox jumps\n over the lazy dog\n\n * pack my box with five\n dozen liquor jugs\n\n this item has "
},
{
"path": "test/features/lists/loose_with_inline.json",
"chars": 508,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n [\"p\",\n \"List item \",\n [\"em\",\n \"ending\"\n ],\n \"\\nw"
},
{
"path": "test/features/lists/loose_with_inline.text",
"chars": 136,
"preview": " * List item _ending_\n with _emphasis_.\n\n * List item\n with **strong emphasis**.\n\n * List item\n with [a link](http"
},
{
"path": "test/features/lists/multiline_inline.json",
"chars": 148,
"preview": "[\"html\",\n [\"ul\",\n [\"li\",\n \"List items can have \",\n [ \"em\", \"inline content\\nthat spans multiple lines\" ],\n"
},
{
"path": "test/features/lists/multiline_inline.text",
"chars": 73,
"preview": "* List items can have *inline content\n that spans multiple lines*. Pain\n"
},
{
"path": "test/features/lists/nested.json",
"chars": 517,
"preview": "[\"html\",\n [\"ol\",\n [\"li\",\n \"one\",\n [\"ul\",\n [\"li\",\n \"alpha\",\n [\"ul\",\n [\""
},
{
"path": "test/features/lists/nested.text",
"chars": 112,
"preview": "1. one\n * alpha\n - almond\n - brazil\n * beta\n - cashew\n2. two\n3. three\n * gamma\n"
}
]
// ... and 586 more files (download for full content)
About this extraction
This page contains the full source code of the evilstreak/markdown-js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 786 files (466.7 KB), approximately 169.7k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.