mirror of
https://github.com/erusev/parsedown.git
synced 2023-08-10 21:13:06 +03:00
Compare commits
277 Commits
1.6.1
...
1.8.0-beta
Author | SHA1 | Date | |
---|---|---|---|
1f69f7e697 | |||
c83af0a7d5 | |||
4686daf8c2 | |||
c9e7183cfa | |||
9eed1104e7 | |||
fd95703da5 | |||
8d172a2994 | |||
dfab7240a4 | |||
113c6d2b21 | |||
a9764ec90f | |||
0a842fb5b1 | |||
7f4318dbdb | |||
3e70819a20 | |||
2bf7ca41a0 | |||
b75fd409ff | |||
88a3f31dd7 | |||
726d4ef44a | |||
450a74fedf | |||
7e15d99d90 | |||
d2dd736e1b | |||
e74a5bd7ed | |||
b53aa74a72 | |||
3ea08140b6 | |||
c45e41950f | |||
2faba6fef5 | |||
b42add3762 | |||
107223d3a0 | |||
d4f1ac465c | |||
d6e306d620 | |||
dc5cf8770b | |||
70f5c02d47 | |||
90ad738933 | |||
f2327023c1 | |||
6f13f97674 | |||
8091e5586a | |||
cb33daf0e6 | |||
c440c91af5 | |||
3514881e14 | |||
043c55e4c6 | |||
e4cd13350b | |||
ae8067e862 | |||
5353ebb524 | |||
39df7d4f8e | |||
50f15add44 | |||
3f5b0ee781 | |||
9a021b2130 | |||
43d25a74fe | |||
1d68e5506c | |||
86940be224 | |||
cdaf86b039 | |||
1d65fb858a | |||
600db7e4de | |||
1be2a01de8 | |||
f50ba3d803 | |||
387ef63888 | |||
68be90348c | |||
48b9f71bdc | |||
0039cd00f8 | |||
c6b717cc35 | |||
8f3f61883d | |||
4c9ea94d0c | |||
32e69de014 | |||
201299ddc2 | |||
557db7c179 | |||
0c0ed38290 | |||
798bda682e | |||
9b7b7348b4 | |||
96581dbe16 | |||
06b810cd4a | |||
38ea813b0e | |||
24e48e91c8 | |||
e33f1a48c8 | |||
1c8f6bc253 | |||
ed3e967fb6 | |||
3b3d13489b | |||
498c88c4eb | |||
772c919b05 | |||
cf6d23de55 | |||
d0279cdd3b | |||
8a90586218 | |||
390fa0da1b | |||
9026b1abdb | |||
68736f8800 | |||
535110c57e | |||
ce073c9baa | |||
e4d6c8f911 | |||
cbe2e74d52 | |||
aa90dd481a | |||
20e592359f | |||
9f1f5de387 | |||
40b9da7837 | |||
a9c21447ce | |||
a3e02c1d0e | |||
40e797031e | |||
448b72a149 | |||
92e426e0e8 | |||
07216480db | |||
caea783006 | |||
d849d64611 | |||
00e51ee424 | |||
0550c3eaf9 | |||
790aed42ab | |||
1c52cb6b5e | |||
ae13290221 | |||
e16162e288 | |||
244ea0aaa6 | |||
2f291e0b2f | |||
d2a73f9179 | |||
f594d4c18b | |||
21cdd8a0b3 | |||
a52d386250 | |||
dd9f4036ee | |||
e7fbbf537b | |||
cac63f6fcb | |||
f71bec00f4 | |||
913e04782f | |||
1fa6b038af | |||
e59fbd736d | |||
8c14c5c239 | |||
0205a4cbe6 | |||
011465bca6 | |||
adcba80502 | |||
65d7bc5013 | |||
1a47e74be1 | |||
56cc41803a | |||
d86d839677 | |||
d5ded2b935 | |||
098f24d189 | |||
eb55e426b9 | |||
ced6187ca5 | |||
972648ff64 | |||
77dc0a090a | |||
88dc949890 | |||
624a08b7eb | |||
3fc54bc966 | |||
ef7ed7b66c | |||
e4c5be026d | |||
e6444bb57e | |||
a3265e7c6f | |||
aac00ac742 | |||
6830c3339f | |||
19f1bb9353 | |||
721b885dd3 | |||
f70d96479a | |||
92e9c27ba0 | |||
9857334186 | |||
ae7e8e5067 | |||
253822057a | |||
a18bf495ed | |||
e5bf9560d7 | |||
33b51eaefa | |||
d686a50292 | |||
f3068df45a | |||
9b1f54b9d3 | |||
90439ef882 | |||
72d30d33bc | |||
97dd037e6f | |||
fa89f0d743 | |||
d638fd8a25 | |||
cc53d5ae29 | |||
45f40696f6 | |||
e8f3d4efc0 | |||
096e164756 | |||
e2f3961f80 | |||
e941dcc3f0 | |||
c192001a7e | |||
48a053fe29 | |||
5057e505d8 | |||
ad62bf5a6f | |||
6678d59be4 | |||
c999a4b61b | |||
e938ab4ffe | |||
e69374af0d | |||
722b776684 | |||
7fd92a8fbd | |||
0e1043a8d6 | |||
1196ed9512 | |||
1244122b84 | |||
d98d60aaf3 | |||
296ebf0e60 | |||
a60ba300b1 | |||
089789dfff | |||
03e1a6ac02 | |||
fbe3fe878f | |||
09827f542c | |||
70ef6f5521 | |||
691e36b1f2 | |||
af6affdc2c | |||
9cf41f27ab | |||
16aadff2ed | |||
07c937583d | |||
4404201175 | |||
c05ef0c12a | |||
47e4163a68 | |||
c05bff047a | |||
6a4afac0d0 | |||
129f807e32 | |||
be963a6531 | |||
728952b90a | |||
c82af01bd6 | |||
67c3efbea0 | |||
593ffd45a3 | |||
bbb7687f31 | |||
b1e5aebaf6 | |||
c63b690a79 | |||
226f636360 | |||
2e4afde68d | |||
dc30cb441c | |||
f76b10aaab | |||
054ba3c487 | |||
4bae1c9834 | |||
aee3963e6b | |||
4dc98b635d | |||
e4bb12329e | |||
6d0156d707 | |||
29ad172261 | |||
131ba75851 | |||
924b26e16c | |||
af04ac92e2 | |||
6bb66db00f | |||
b3d45c4bb9 | |||
1d4296f34d | |||
bf5105cb1a | |||
1140613fc7 | |||
1d0af35f10 | |||
d7956e3ade | |||
4367f89a74 | |||
1bf24f7334 | |||
0a09d5ad45 | |||
3fc442b078 | |||
bd0e31a7dd | |||
dfaf03639a | |||
7081afe8cb | |||
4b6493999a | |||
0172d779d7 | |||
cc5b38ca39 | |||
48351504de | |||
67e454e300 | |||
ae0211a84c | |||
a9f696f7bb | |||
a3836b1853 | |||
a9e1163c85 | |||
7b1529fff0 | |||
1d61f90bf9 | |||
4b3b7df710 | |||
30ff5c6e75 | |||
bdf537e9d5 | |||
81025cd468 | |||
e691034861 | |||
eb853da92a | |||
6973302ca8 | |||
0a43799da4 | |||
2db3199510 | |||
2423644d72 | |||
8965c7864f | |||
d26b33c20f | |||
d9679141fa | |||
0bd61a73ed | |||
06c4344a71 | |||
c4d4a6800d | |||
be671e72a3 | |||
f0587d41a9 | |||
3aef89b399 | |||
543a6c4175 | |||
a81aedeb10 | |||
50952b3243 | |||
4d3600f273 | |||
d6d5f53ff4 | |||
1a44cbd62c | |||
73dbe2fd17 | |||
33a23fbfb2 | |||
228d5f4754 | |||
2cacfb8da4 | |||
d33e736fa3 | |||
3a46a31e09 | |||
e1bcc1c472 | |||
b5951e08c6 |
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Ignore all tests for archive
|
||||||
|
/test export-ignore
|
||||||
|
/.gitattributes export-ignore
|
||||||
|
/.gitignore export-ignore
|
||||||
|
/.travis.yml export-ignore
|
||||||
|
/phpunit.xml.dist export-ignore
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
composer.lock
|
||||||
|
vendor/
|
32
.travis.yml
32
.travis.yml
@ -1,16 +1,30 @@
|
|||||||
language: php
|
language: php
|
||||||
|
|
||||||
php:
|
dist: trusty
|
||||||
- 7.1
|
sudo: false
|
||||||
- 7.0
|
|
||||||
- 5.6
|
|
||||||
- 5.5
|
|
||||||
- 5.4
|
|
||||||
- 5.3
|
|
||||||
- hhvm
|
|
||||||
- hhvm-nightly
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
include:
|
||||||
|
- php: 5.3
|
||||||
|
dist: precise
|
||||||
|
- php: 5.4
|
||||||
|
- php: 5.5
|
||||||
|
- php: 5.6
|
||||||
|
- php: 7.0
|
||||||
|
- php: 7.1
|
||||||
|
- php: 7.2
|
||||||
|
- php: nightly
|
||||||
|
- php: hhvm
|
||||||
|
- php: hhvm-nightly
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
- php: nightly
|
||||||
- php: hhvm-nightly
|
- php: hhvm-nightly
|
||||||
|
|
||||||
|
install:
|
||||||
|
- composer install --prefer-dist --no-interaction --no-progress
|
||||||
|
|
||||||
|
script:
|
||||||
|
- vendor/bin/phpunit
|
||||||
|
- vendor/bin/phpunit test/CommonMarkTestWeak.php || true
|
||||||
|
- '[ -z "$TRAVIS_TAG" ] || [ "$TRAVIS_TAG" == "$(php -r "require(\"Parsedown.php\"); echo Parsedown::version;")" ]'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2013 Emanuil Rusev, erusev.com
|
Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
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
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
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
|
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
|
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.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
1382
Parsedown.php
1382
Parsedown.php
File diff suppressed because it is too large
Load Diff
49
README.md
49
README.md
@ -1,4 +1,4 @@
|
|||||||
> You might also like [Caret](http://caret.io?ref=parsedown) - our Markdown editor for Mac / Windows / Linux.
|
> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
|
||||||
|
|
||||||
## Parsedown
|
## Parsedown
|
||||||
|
|
||||||
@ -15,15 +15,25 @@ Better Markdown Parser in PHP
|
|||||||
### Features
|
### Features
|
||||||
|
|
||||||
* One File
|
* One File
|
||||||
|
* No Dependencies
|
||||||
* Super Fast
|
* Super Fast
|
||||||
* Extensible
|
* Extensible
|
||||||
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
|
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
|
||||||
* Tested in 5.3 to 7.1 and in HHVM
|
* Tested in 5.3 to 7.2 and in HHVM
|
||||||
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
#### Composer
|
||||||
|
Install the [composer package] by running the following command:
|
||||||
|
|
||||||
Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
|
composer require erusev/parsedown
|
||||||
|
|
||||||
|
#### Manual
|
||||||
|
1. Download the "Source code" from the [latest release]
|
||||||
|
2. Include `Parsedown.php`
|
||||||
|
|
||||||
|
[composer package]: https://packagist.org/packages/erusev/parsedown "The Parsedown package on packagist.org"
|
||||||
|
[latest release]: https://github.com/erusev/parsedown/releases/latest "The latest release of Parsedown"
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@ -31,10 +41,41 @@ Include `Parsedown.php` or install [the composer package](https://packagist.org/
|
|||||||
$Parsedown = new Parsedown();
|
$Parsedown = new Parsedown();
|
||||||
|
|
||||||
echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
|
echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
|
||||||
|
// you can also parse inline markdown only
|
||||||
|
echo $Parsedown->line('Hello _Parsedown_!'); # prints: Hello <em>Parsedown</em>!
|
||||||
```
|
```
|
||||||
|
|
||||||
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
|
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
Parsedown is capable of escaping user-input within the HTML that it generates. Additionally Parsedown will apply sanitisation to additional scripting vectors (such as scripting link destinations) that are introduced by the markdown syntax itself.
|
||||||
|
|
||||||
|
To tell Parsedown that it is processing untrusted user-input, use the following:
|
||||||
|
```php
|
||||||
|
$parsedown = new Parsedown;
|
||||||
|
$parsedown->setSafeMode(true);
|
||||||
|
```
|
||||||
|
|
||||||
|
If instead, you wish to allow HTML within untrusted user-input, but still want output to be free from XSS it is recommended that you make use of a HTML sanitiser that allows HTML tags to be whitelisted, like [HTML Purifier](http://htmlpurifier.org/).
|
||||||
|
|
||||||
|
In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Security-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (a browser security feature) so that your page is likely to be safe even if an attacker finds a vulnerability in one of the first lines of defence above.
|
||||||
|
|
||||||
|
#### Security of Parsedown Extensions
|
||||||
|
|
||||||
|
Safe mode does not necessarily yield safe results when using extensions to Parsedown. Extensions should be evaluated on their own to determine their specific safety against XSS.
|
||||||
|
|
||||||
|
### Escaping HTML
|
||||||
|
> ⚠️ **WARNING:** This method isn't safe from XSS!
|
||||||
|
|
||||||
|
If you wish to escape HTML **in trusted input**, you can use the following:
|
||||||
|
```php
|
||||||
|
$parsedown = new Parsedown;
|
||||||
|
$parsedown->setMarkupEscaped(true);
|
||||||
|
```
|
||||||
|
|
||||||
|
Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
|
||||||
|
|
||||||
### Questions
|
### Questions
|
||||||
|
|
||||||
**How does Parsedown work?**
|
**How does Parsedown work?**
|
||||||
@ -49,7 +90,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
|
|||||||
|
|
||||||
**Who uses it?**
|
**Who uses it?**
|
||||||
|
|
||||||
[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [Herbie CMS](http://www.getherbie.org/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
|
[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [Statamic CMS](http://www.statamic.com/), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
|
||||||
|
|
||||||
**How can I help?**
|
**How can I help?**
|
||||||
|
|
||||||
|
@ -13,9 +13,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0"
|
"php": ">=5.3.0",
|
||||||
|
"ext-mbstring": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {"Parsedown": ""}
|
"psr-0": {"Parsedown": ""}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-0": {
|
||||||
|
"TestParsedown": "test/",
|
||||||
|
"ParsedownTest": "test/",
|
||||||
|
"CommonMarkTest": "test/",
|
||||||
|
"CommonMarkTestWeak": "test/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit bootstrap="test/bootstrap.php" colors="true">
|
<phpunit bootstrap="vendor/autoload.php" colors="true">
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite>
|
<testsuite>
|
||||||
<file>test/ParsedownTest.php</file>
|
<file>test/ParsedownTest.php</file>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test Parsedown against the CommonMark spec.
|
|
||||||
*
|
|
||||||
* Some code based on the original JavaScript test runner by jgm.
|
|
||||||
*
|
|
||||||
* @link http://commonmark.org/ CommonMark
|
|
||||||
* @link http://git.io/8WtRvQ JavaScript test runner
|
|
||||||
*/
|
|
||||||
class CommonMarkTest extends PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider data
|
|
||||||
* @param $section
|
|
||||||
* @param $markdown
|
|
||||||
* @param $expectedHtml
|
|
||||||
*/
|
|
||||||
function test_($section, $markdown, $expectedHtml)
|
|
||||||
{
|
|
||||||
$Parsedown = new Parsedown();
|
|
||||||
$Parsedown->setUrlsLinked(false);
|
|
||||||
|
|
||||||
$actualHtml = $Parsedown->text($markdown);
|
|
||||||
$actualHtml = $this->normalizeMarkup($actualHtml);
|
|
||||||
|
|
||||||
$this->assertEquals($expectedHtml, $actualHtml);
|
|
||||||
}
|
|
||||||
|
|
||||||
function data()
|
|
||||||
{
|
|
||||||
$spec = file_get_contents(self::SPEC_URL);
|
|
||||||
$spec = strstr($spec, '<!-- END TESTS -->', true);
|
|
||||||
|
|
||||||
$tests = array();
|
|
||||||
$currentSection = '';
|
|
||||||
|
|
||||||
preg_replace_callback(
|
|
||||||
'/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/m',
|
|
||||||
function($matches) use ( & $tests, & $currentSection, & $testCount) {
|
|
||||||
if (isset($matches[3]) and $matches[3]) {
|
|
||||||
$currentSection = $matches[3];
|
|
||||||
} else {
|
|
||||||
$testCount++;
|
|
||||||
$markdown = $matches[1];
|
|
||||||
$markdown = preg_replace('/→/', "\t", $markdown);
|
|
||||||
$expectedHtml = $matches[2];
|
|
||||||
$expectedHtml = $this->normalizeMarkup($expectedHtml);
|
|
||||||
$tests []= array(
|
|
||||||
$currentSection, # section
|
|
||||||
$markdown, # markdown
|
|
||||||
$expectedHtml, # html
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
$spec
|
|
||||||
);
|
|
||||||
|
|
||||||
return $tests;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function normalizeMarkup($markup)
|
|
||||||
{
|
|
||||||
$markup = preg_replace("/\n+/", "\n", $markup);
|
|
||||||
$markup = preg_replace('/^\s+/m', '', $markup);
|
|
||||||
$markup = preg_replace('/^((?:<[\w]+>)+)\n/m', '$1', $markup);
|
|
||||||
$markup = preg_replace('/\n((?:<\/[\w]+>)+)$/m', '$1', $markup);
|
|
||||||
$markup = trim($markup);
|
|
||||||
|
|
||||||
return $markup;
|
|
||||||
}
|
|
||||||
}
|
|
71
test/CommonMarkTestStrict.php
Normal file
71
test/CommonMarkTestStrict.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Parsedown against the CommonMark spec
|
||||||
|
*
|
||||||
|
* @link http://commonmark.org/ CommonMark
|
||||||
|
*/
|
||||||
|
class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt';
|
||||||
|
|
||||||
|
protected $parsedown;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->parsedown = new TestParsedown();
|
||||||
|
$this->parsedown->setUrlsLinked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider data
|
||||||
|
* @param $id
|
||||||
|
* @param $section
|
||||||
|
* @param $markdown
|
||||||
|
* @param $expectedHtml
|
||||||
|
*/
|
||||||
|
public function testExample($id, $section, $markdown, $expectedHtml)
|
||||||
|
{
|
||||||
|
$actualHtml = $this->parsedown->text($markdown);
|
||||||
|
$this->assertEquals($expectedHtml, $actualHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function data()
|
||||||
|
{
|
||||||
|
$spec = file_get_contents(self::SPEC_URL);
|
||||||
|
if ($spec === false) {
|
||||||
|
$this->fail('Unable to load CommonMark spec from ' . self::SPEC_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
$spec = str_replace("\r\n", "\n", $spec);
|
||||||
|
$spec = strstr($spec, '<!-- END TESTS -->', true);
|
||||||
|
|
||||||
|
$matches = array();
|
||||||
|
preg_match_all('/^`{32} example\n((?s).*?)\n\.\n(?:|((?s).*?)\n)`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
$currentId = 0;
|
||||||
|
$currentSection = '';
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
if (isset($match[3])) {
|
||||||
|
$currentSection = $match[3];
|
||||||
|
} else {
|
||||||
|
$currentId++;
|
||||||
|
$markdown = str_replace('→', "\t", $match[1]);
|
||||||
|
$expectedHtml = isset($match[2]) ? str_replace('→', "\t", $match[2]) : '';
|
||||||
|
|
||||||
|
$data[$currentId] = array(
|
||||||
|
'id' => $currentId,
|
||||||
|
'section' => $currentSection,
|
||||||
|
'markdown' => $markdown,
|
||||||
|
'expectedHtml' => $expectedHtml
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
63
test/CommonMarkTestWeak.php
Normal file
63
test/CommonMarkTestWeak.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
require_once(__DIR__ . '/CommonMarkTestStrict.php');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Parsedown against the CommonMark spec, but less aggressive
|
||||||
|
*
|
||||||
|
* The resulting HTML markup is cleaned up before comparison, so examples
|
||||||
|
* which would normally fail due to actually invisible differences (e.g.
|
||||||
|
* superfluous whitespaces), don't fail. However, cleanup relies on block
|
||||||
|
* element detection. The detection doesn't work correctly when a element's
|
||||||
|
* `display` CSS property is manipulated. According to that this test is only
|
||||||
|
* a interim solution on Parsedown's way to full CommonMark compatibility.
|
||||||
|
*
|
||||||
|
* @link http://commonmark.org/ CommonMark
|
||||||
|
*/
|
||||||
|
class CommonMarkTestWeak extends CommonMarkTestStrict
|
||||||
|
{
|
||||||
|
protected $textLevelElementRegex;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$textLevelElements = $this->parsedown->getTextLevelElements();
|
||||||
|
array_walk($textLevelElements, function (&$element) {
|
||||||
|
$element = preg_quote($element, '/');
|
||||||
|
});
|
||||||
|
$this->textLevelElementRegex = '\b(?:' . implode('|', $textLevelElements) . ')\b';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider data
|
||||||
|
* @param $id
|
||||||
|
* @param $section
|
||||||
|
* @param $markdown
|
||||||
|
* @param $expectedHtml
|
||||||
|
*/
|
||||||
|
public function testExample($id, $section, $markdown, $expectedHtml)
|
||||||
|
{
|
||||||
|
$expectedHtml = $this->cleanupHtml($expectedHtml);
|
||||||
|
|
||||||
|
$actualHtml = $this->parsedown->text($markdown);
|
||||||
|
$actualHtml = $this->cleanupHtml($actualHtml);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedHtml, $actualHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cleanupHtml($markup)
|
||||||
|
{
|
||||||
|
// invisible whitespaces at the beginning and end of block elements
|
||||||
|
// however, whitespaces at the beginning of <pre> elements do matter
|
||||||
|
$markup = preg_replace(
|
||||||
|
array(
|
||||||
|
'/(<(?!(?:' . $this->textLevelElementRegex . '|\bpre\b))\w+\b[^>]*>(?:<' . $this->textLevelElementRegex . '[^>]*>)*)\s+/s',
|
||||||
|
'/\s+((?:<\/' . $this->textLevelElementRegex . '>)*<\/(?!' . $this->textLevelElementRegex . ')\w+\b>)/s'
|
||||||
|
),
|
||||||
|
'$1',
|
||||||
|
$markup
|
||||||
|
);
|
||||||
|
|
||||||
|
return $markup;
|
||||||
|
}
|
||||||
|
}
|
56
test/ParsedownTest.php
Normal file → Executable file
56
test/ParsedownTest.php
Normal file → Executable file
@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
require 'SampleExtensions.php';
|
||||||
|
|
||||||
class ParsedownTest extends PHPUnit_Framework_TestCase
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ParsedownTest extends TestCase
|
||||||
{
|
{
|
||||||
final function __construct($name = null, array $data = array(), $dataName = '')
|
final function __construct($name = null, array $data = array(), $dataName = '')
|
||||||
{
|
{
|
||||||
@ -10,7 +13,8 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
|
|||||||
parent::__construct($name, $data, $dataName);
|
parent::__construct($name, $data, $dataName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private $dirs, $Parsedown;
|
private $dirs;
|
||||||
|
protected $Parsedown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
@ -27,7 +31,7 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
protected function initParsedown()
|
protected function initParsedown()
|
||||||
{
|
{
|
||||||
$Parsedown = new Parsedown();
|
$Parsedown = new TestParsedown();
|
||||||
|
|
||||||
return $Parsedown;
|
return $Parsedown;
|
||||||
}
|
}
|
||||||
@ -46,11 +50,48 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
|
|||||||
$expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
|
$expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
|
||||||
$expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
|
$expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
|
||||||
|
|
||||||
|
$this->Parsedown->setSafeMode(substr($test, 0, 3) === 'xss');
|
||||||
|
$this->Parsedown->setStrictMode(substr($test, 0, 6) === 'strict');
|
||||||
|
|
||||||
$actualMarkup = $this->Parsedown->text($markdown);
|
$actualMarkup = $this->Parsedown->text($markdown);
|
||||||
|
|
||||||
$this->assertEquals($expectedMarkup, $actualMarkup);
|
$this->assertEquals($expectedMarkup, $actualMarkup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testRawHtml()
|
||||||
|
{
|
||||||
|
$markdown = "```php\nfoobar\n```";
|
||||||
|
$expectedMarkup = '<pre><code class="language-php"><p>foobar</p></code></pre>';
|
||||||
|
$expectedSafeMarkup = '<pre><code class="language-php"><p>foobar</p></code></pre>';
|
||||||
|
|
||||||
|
$unsafeExtension = new UnsafeExtension;
|
||||||
|
$actualMarkup = $unsafeExtension->text($markdown);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedMarkup, $actualMarkup);
|
||||||
|
|
||||||
|
$unsafeExtension->setSafeMode(true);
|
||||||
|
$actualSafeMarkup = $unsafeExtension->text($markdown);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTrustDelegatedRawHtml()
|
||||||
|
{
|
||||||
|
$markdown = "```php\nfoobar\n```";
|
||||||
|
$expectedMarkup = '<pre><code class="language-php"><p>foobar</p></code></pre>';
|
||||||
|
$expectedSafeMarkup = $expectedMarkup;
|
||||||
|
|
||||||
|
$unsafeExtension = new TrustDelegatedExtension;
|
||||||
|
$actualMarkup = $unsafeExtension->text($markdown);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedMarkup, $actualMarkup);
|
||||||
|
|
||||||
|
$unsafeExtension->setSafeMode(true);
|
||||||
|
$actualSafeMarkup = $unsafeExtension->text($markdown);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
|
||||||
|
}
|
||||||
|
|
||||||
function data()
|
function data()
|
||||||
{
|
{
|
||||||
$data = array();
|
$data = array();
|
||||||
@ -119,12 +160,12 @@ MARKDOWN_WITH_MARKUP;
|
|||||||
<p><div><em>content</em></div></p>
|
<p><div><em>content</em></div></p>
|
||||||
<p>sparse:</p>
|
<p>sparse:</p>
|
||||||
<p><div>
|
<p><div>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<em>content</em>
|
<em>content</em>
|
||||||
</div>
|
</div>
|
||||||
</div></p>
|
</div></p>
|
||||||
<p>paragraph</p>
|
<p>paragraph</p>
|
||||||
<p><style type="text/css">
|
<p><style type="text/css">
|
||||||
p {
|
p {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
@ -132,15 +173,14 @@ color: red;
|
|||||||
<p>comment</p>
|
<p>comment</p>
|
||||||
<p><!-- html comment --></p>
|
<p><!-- html comment --></p>
|
||||||
EXPECTED_HTML;
|
EXPECTED_HTML;
|
||||||
$parsedownWithNoMarkup = new Parsedown();
|
|
||||||
|
$parsedownWithNoMarkup = new TestParsedown();
|
||||||
$parsedownWithNoMarkup->setMarkupEscaped(true);
|
$parsedownWithNoMarkup->setMarkupEscaped(true);
|
||||||
$this->assertEquals($expectedHtml, $parsedownWithNoMarkup->text($markdownWithHtml));
|
$this->assertEquals($expectedHtml, $parsedownWithNoMarkup->text($markdownWithHtml));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLateStaticBinding()
|
public function testLateStaticBinding()
|
||||||
{
|
{
|
||||||
include __DIR__ . '/TestParsedown.php';
|
|
||||||
|
|
||||||
$parsedown = Parsedown::instance();
|
$parsedown = Parsedown::instance();
|
||||||
$this->assertInstanceOf('Parsedown', $parsedown);
|
$this->assertInstanceOf('Parsedown', $parsedown);
|
||||||
|
|
||||||
|
40
test/SampleExtensions.php
Normal file
40
test/SampleExtensions.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class UnsafeExtension extends Parsedown
|
||||||
|
{
|
||||||
|
protected function blockFencedCodeComplete($Block)
|
||||||
|
{
|
||||||
|
$text = $Block['element']['element']['text'];
|
||||||
|
unset($Block['element']['element']['text']);
|
||||||
|
|
||||||
|
// WARNING: There is almost always a better way of doing things!
|
||||||
|
//
|
||||||
|
// This example is one of them, unsafe behaviour is NOT needed here.
|
||||||
|
// Only use this if you trust the input and have no idea what
|
||||||
|
// the output HTML will look like (e.g. using an external parser).
|
||||||
|
$Block['element']['element']['rawHtml'] = "<p>$text</p>";
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TrustDelegatedExtension extends Parsedown
|
||||||
|
{
|
||||||
|
protected function blockFencedCodeComplete($Block)
|
||||||
|
{
|
||||||
|
$text = $Block['element']['element']['text'];
|
||||||
|
unset($Block['element']['element']['text']);
|
||||||
|
|
||||||
|
// WARNING: There is almost always a better way of doing things!
|
||||||
|
//
|
||||||
|
// This behaviour is NOT needed in the demonstrated case.
|
||||||
|
// Only use this if you are sure that the result being added into
|
||||||
|
// rawHtml is safe.
|
||||||
|
// (e.g. using an external parser with escaping capabilities).
|
||||||
|
$Block['element']['element']['rawHtml'] = "<p>$text</p>";
|
||||||
|
$Block['element']['element']['allowRawHtmlInSafeMode'] = true;
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
}
|
@ -2,4 +2,8 @@
|
|||||||
|
|
||||||
class TestParsedown extends Parsedown
|
class TestParsedown extends Parsedown
|
||||||
{
|
{
|
||||||
|
public function getTextLevelElements()
|
||||||
|
{
|
||||||
|
return $this->textLevelElements;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
include 'Parsedown.php';
|
|
@ -6,4 +6,8 @@
|
|||||||
<h6>h6</h6>
|
<h6>h6</h6>
|
||||||
<p>####### not a heading</p>
|
<p>####### not a heading</p>
|
||||||
<h1>closed h1</h1>
|
<h1>closed h1</h1>
|
||||||
<p>#</p>
|
<h1></h1>
|
||||||
|
<h2></h2>
|
||||||
|
<h1># of levels</h1>
|
||||||
|
<h1># of levels #</h1>
|
||||||
|
<h1>heading</h1>
|
@ -14,4 +14,12 @@
|
|||||||
|
|
||||||
# closed h1 #
|
# closed h1 #
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
# # of levels
|
||||||
|
|
||||||
|
# # of levels # #
|
||||||
|
|
||||||
|
#heading
|
@ -5,4 +5,9 @@ echo $message;</code></pre>
|
|||||||
<hr />
|
<hr />
|
||||||
<pre><code>> not a quote
|
<pre><code>> not a quote
|
||||||
- not a list item
|
- not a list item
|
||||||
[not a reference]: http://foo.com</code></pre>
|
[not a reference]: http://foo.com</code></pre>
|
||||||
|
<hr />
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
|
||||||
|
bar</code></pre>
|
@ -7,4 +7,11 @@
|
|||||||
|
|
||||||
> not a quote
|
> not a quote
|
||||||
- not a list item
|
- not a list item
|
||||||
[not a reference]: http://foo.com
|
[not a reference]: http://foo.com
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
foo
|
||||||
|
|
||||||
|
|
||||||
|
bar
|
@ -1,12 +1,40 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>li
|
<li>li<ul>
|
||||||
|
<li>li<ul>
|
||||||
|
<li>li</li>
|
||||||
|
<li>li</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>li</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>li</li>
|
||||||
|
</ul>
|
||||||
|
<hr />
|
||||||
<ul>
|
<ul>
|
||||||
<li>li
|
<li>level 1<ul>
|
||||||
|
<li>level 2<ul>
|
||||||
|
<li>level 3<ul>
|
||||||
|
<li>level 4<ul>
|
||||||
|
<li>level 5</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr />
|
||||||
<ul>
|
<ul>
|
||||||
<li>li</li>
|
<li>a</li>
|
||||||
<li>li</li>
|
<li>b</li>
|
||||||
</ul></li>
|
<li>c</li>
|
||||||
<li>li</li>
|
<li>d</li>
|
||||||
</ul></li>
|
<li>e</li>
|
||||||
<li>li</li>
|
<li>f</li>
|
||||||
|
<li>g</li>
|
||||||
|
<li>h</li>
|
||||||
|
<li>i</li>
|
||||||
</ul>
|
</ul>
|
@ -3,4 +3,24 @@
|
|||||||
- li
|
- li
|
||||||
- li
|
- li
|
||||||
- li
|
- li
|
||||||
- li
|
- li
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- level 1
|
||||||
|
- level 2
|
||||||
|
- level 3
|
||||||
|
- level 4
|
||||||
|
- level 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- a
|
||||||
|
- b
|
||||||
|
- c
|
||||||
|
- d
|
||||||
|
- e
|
||||||
|
- f
|
||||||
|
- g
|
||||||
|
- h
|
||||||
|
- i
|
@ -1 +1,2 @@
|
|||||||
<p>my email is <a href="mailto:me@example.com">me@example.com</a></p>
|
<p>my email is <a href="mailto:me@example.com">me@example.com</a></p>
|
||||||
|
<p>html tags shouldn't start an email autolink <strong>first.last@example.com</strong></p>
|
@ -1 +1,3 @@
|
|||||||
my email is <me@example.com>
|
my email is <me@example.com>
|
||||||
|
|
||||||
|
html tags shouldn't start an email autolink <strong>first.last@example.com</strong>
|
@ -3,4 +3,16 @@
|
|||||||
$message = 'fenced code block';
|
$message = 'fenced code block';
|
||||||
echo $message;</code></pre>
|
echo $message;</code></pre>
|
||||||
<pre><code>tilde</code></pre>
|
<pre><code>tilde</code></pre>
|
||||||
<pre><code class="language-php">echo 'language identifier';</code></pre>
|
<pre><code class="language-php">echo 'language identifier';</code></pre>
|
||||||
|
<pre><code class="language-c#">echo 'language identifier with non words';</code></pre>
|
||||||
|
<pre><code class="language-html+php"><?php
|
||||||
|
echo "Hello World";
|
||||||
|
?>
|
||||||
|
<a href="http://auraphp.com" >Aura Project</a></code></pre>
|
||||||
|
<pre><code>the following isn't quite enough to close
|
||||||
|
```
|
||||||
|
still a fenced code block</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
|
||||||
|
bar</code></pre>
|
@ -11,4 +11,28 @@ tilde
|
|||||||
|
|
||||||
```php
|
```php
|
||||||
echo 'language identifier';
|
echo 'language identifier';
|
||||||
|
```
|
||||||
|
|
||||||
|
```c#
|
||||||
|
echo 'language identifier with non words';
|
||||||
|
```
|
||||||
|
|
||||||
|
```html+php
|
||||||
|
<?php
|
||||||
|
echo "Hello World";
|
||||||
|
?>
|
||||||
|
<a href="http://auraphp.com" >Aura Project</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
````
|
||||||
|
the following isn't quite enough to close
|
||||||
|
```
|
||||||
|
still a fenced code block
|
||||||
|
````
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
|
||||||
|
bar
|
||||||
```
|
```
|
@ -2,4 +2,10 @@
|
|||||||
<p>paragraph</p>
|
<p>paragraph</p>
|
||||||
<!--
|
<!--
|
||||||
multiline -->
|
multiline -->
|
||||||
<p>paragraph</p>
|
<p>paragraph</p>
|
||||||
|
<!-- sss -->abc
|
||||||
|
<ul>
|
||||||
|
<li>abcd</li>
|
||||||
|
<li>bbbb</li>
|
||||||
|
<li>cccc</li>
|
||||||
|
</ul>
|
@ -5,4 +5,10 @@ paragraph
|
|||||||
<!--
|
<!--
|
||||||
multiline -->
|
multiline -->
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
|
|
||||||
|
<!-- sss -->abc
|
||||||
|
|
||||||
|
* abcd
|
||||||
|
* bbbb
|
||||||
|
* cccc
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,8 @@
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<p>quote
|
<p>quote
|
||||||
the rest of it</p>
|
the rest of it</p>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote>
|
||||||
<p>another paragraph
|
<p>another paragraph
|
||||||
the rest of it</p>
|
the rest of it</p>
|
||||||
</blockquote>
|
</blockquote>
|
3
test/data/markup_consecutive_one.html
Normal file
3
test/data/markup_consecutive_one.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div>Markup</div>
|
||||||
|
_No markdown_ without blank line for **strict** compliance with CommonMark.
|
||||||
|
<p><strong>Markdown</strong></p>
|
4
test/data/markup_consecutive_one.md
Normal file
4
test/data/markup_consecutive_one.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div>Markup</div>
|
||||||
|
_No markdown_ without blank line for **strict** compliance with CommonMark.
|
||||||
|
|
||||||
|
**Markdown**
|
4
test/data/markup_consecutive_one_line.html
Normal file
4
test/data/markup_consecutive_one_line.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div>One markup on
|
||||||
|
two lines</div>
|
||||||
|
_No markdown_
|
||||||
|
<p><strong>Markdown</strong></p>
|
5
test/data/markup_consecutive_one_line.md
Normal file
5
test/data/markup_consecutive_one_line.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div>One markup on
|
||||||
|
two lines</div>
|
||||||
|
_No markdown_
|
||||||
|
|
||||||
|
**Markdown**
|
3
test/data/markup_consecutive_one_stripped.html
Normal file
3
test/data/markup_consecutive_one_stripped.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div><p>Stripped markup</p></div>
|
||||||
|
_No markdown_
|
||||||
|
<p><strong>Markdown</strong></p>
|
4
test/data/markup_consecutive_one_stripped.md
Normal file
4
test/data/markup_consecutive_one_stripped.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div><p>Stripped markup</p></div>
|
||||||
|
_No markdown_
|
||||||
|
|
||||||
|
**Markdown**
|
3
test/data/markup_consecutive_two.html
Normal file
3
test/data/markup_consecutive_two.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div>First markup</div><p>and second markup on the same line.</p>
|
||||||
|
_No markdown_
|
||||||
|
<p><strong>Markdown</strong></p>
|
4
test/data/markup_consecutive_two.md
Normal file
4
test/data/markup_consecutive_two.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div>First markup</div><p>and second markup on the same line.</p>
|
||||||
|
_No markdown_
|
||||||
|
|
||||||
|
**Markdown**
|
4
test/data/markup_consecutive_two_lines.html
Normal file
4
test/data/markup_consecutive_two_lines.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div>First markup</div><p>and partial markup
|
||||||
|
on two lines.</p>
|
||||||
|
_No markdown_
|
||||||
|
<p><strong>Markdown</strong></p>
|
5
test/data/markup_consecutive_two_lines.md
Normal file
5
test/data/markup_consecutive_two_lines.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div>First markup</div><p>and partial markup
|
||||||
|
on two lines.</p>
|
||||||
|
_No markdown_
|
||||||
|
|
||||||
|
**Markdown**
|
4
test/data/markup_consecutive_two_stripped.html
Normal file
4
test/data/markup_consecutive_two_stripped.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div><p>Stripped markup
|
||||||
|
on two lines</p></div>
|
||||||
|
_No markdown_
|
||||||
|
<p><strong>Markdown</strong></p>
|
5
test/data/markup_consecutive_two_stripped.md
Normal file
5
test/data/markup_consecutive_two_stripped.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div><p>Stripped markup
|
||||||
|
on two lines</p></div>
|
||||||
|
_No markdown_
|
||||||
|
|
||||||
|
**Markdown**
|
10
test/data/multiline_lists.html
Normal file
10
test/data/multiline_lists.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<p>One
|
||||||
|
First body copy</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Two
|
||||||
|
Last body copy</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
5
test/data/multiline_lists.md
Normal file
5
test/data/multiline_lists.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
1. One
|
||||||
|
First body copy
|
||||||
|
|
||||||
|
2. Two
|
||||||
|
Last body copy
|
@ -10,4 +10,7 @@
|
|||||||
<p>large numbers:</p>
|
<p>large numbers:</p>
|
||||||
<ol start="123">
|
<ol start="123">
|
||||||
<li>one</li>
|
<li>one</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
<p>foo 1. the following should not start a list
|
||||||
|
100.<br />
|
||||||
|
200. </p>
|
@ -8,4 +8,8 @@ repeating numbers:
|
|||||||
|
|
||||||
large numbers:
|
large numbers:
|
||||||
|
|
||||||
123. one
|
123. one
|
||||||
|
|
||||||
|
foo 1. the following should not start a list
|
||||||
|
100.
|
||||||
|
200.
|
@ -8,5 +8,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<p>li</p>
|
<p>li</p>
|
||||||
</li>
|
</li>
|
||||||
<li>li</li>
|
<li>
|
||||||
|
<p>li</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
@ -1,12 +1,18 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
<hr class="foo" id="bar" />
|
<hr class="foo" id="bar" />
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
<hr class="foo" id="bar"/>
|
<hr class="foo" id="bar"/>
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
<hr class="foo" id="bar" >
|
<hr class="foo" id="bar" >
|
||||||
|
|
||||||
paragraph
|
paragraph
|
12
test/data/setext_header_spaces.html
Normal file
12
test/data/setext_header_spaces.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<h1>trailing space</h1>
|
||||||
|
<h2>trailing space</h2>
|
||||||
|
<h1>leading and trailing space</h1>
|
||||||
|
<h2>leading and trailing space</h2>
|
||||||
|
<h1>1 leading space</h1>
|
||||||
|
<h2>1 leading space</h2>
|
||||||
|
<h1>3 leading spaces</h1>
|
||||||
|
<h2>3 leading spaces</h2>
|
||||||
|
<p>too many leading spaces
|
||||||
|
==</p>
|
||||||
|
<p>too many leading spaces
|
||||||
|
--</p>
|
29
test/data/setext_header_spaces.md
Normal file
29
test/data/setext_header_spaces.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
trailing space
|
||||||
|
==
|
||||||
|
|
||||||
|
trailing space
|
||||||
|
--
|
||||||
|
|
||||||
|
leading and trailing space
|
||||||
|
==
|
||||||
|
|
||||||
|
leading and trailing space
|
||||||
|
--
|
||||||
|
|
||||||
|
1 leading space
|
||||||
|
==
|
||||||
|
|
||||||
|
1 leading space
|
||||||
|
--
|
||||||
|
|
||||||
|
3 leading spaces
|
||||||
|
==
|
||||||
|
|
||||||
|
3 leading spaces
|
||||||
|
--
|
||||||
|
|
||||||
|
too many leading spaces
|
||||||
|
==
|
||||||
|
|
||||||
|
too many leading spaces
|
||||||
|
--
|
@ -8,4 +8,19 @@
|
|||||||
<p>no space after <code>></code>:</p>
|
<p>no space after <code>></code>:</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>quote</p>
|
<p>quote</p>
|
||||||
|
</blockquote>
|
||||||
|
<hr />
|
||||||
|
<blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<p>Info 1 text</p>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<p>Info 2 text</p>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
@ -4,4 +4,10 @@ indented:
|
|||||||
> quote
|
> quote
|
||||||
|
|
||||||
no space after `>`:
|
no space after `>`:
|
||||||
>quote
|
>quote
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
>>> Info 1 text
|
||||||
|
|
||||||
|
>>> Info 2 text
|
@ -34,4 +34,42 @@
|
|||||||
<td>cell 2.2</td>
|
<td>cell 2.2</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<hr />
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: left;">header 1</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left;">cell 1.1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left;">cell 2.1</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>header 1</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>cell 1.1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>cell 2.1</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
<p>Not a table, we haven't ended the paragraph:
|
||||||
|
header 1 | header 2
|
||||||
|
-------- | --------
|
||||||
|
cell 1.1 | cell 1.2
|
||||||
|
cell 2.1 | cell 2.2</p>
|
@ -8,4 +8,26 @@ cell 2.1 | cell 2.2
|
|||||||
header 1 | header 2
|
header 1 | header 2
|
||||||
:------- | --------
|
:------- | --------
|
||||||
cell 1.1 | cell 1.2
|
cell 1.1 | cell 1.2
|
||||||
|
cell 2.1 | cell 2.2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
header 1
|
||||||
|
:-------
|
||||||
|
cell 1.1
|
||||||
|
cell 2.1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
header 1
|
||||||
|
-------|
|
||||||
|
cell 1.1
|
||||||
|
cell 2.1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Not a table, we haven't ended the paragraph:
|
||||||
|
header 1 | header 2
|
||||||
|
-------- | --------
|
||||||
|
cell 1.1 | cell 1.2
|
||||||
cell 2.1 | cell 2.2
|
cell 2.1 | cell 2.2
|
@ -2,6 +2,10 @@
|
|||||||
<li>
|
<li>
|
||||||
<p>li</p>
|
<p>li</p>
|
||||||
</li>
|
</li>
|
||||||
<li>li</li>
|
<li>
|
||||||
<li>li</li>
|
<p>li</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>li</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
@ -1,8 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
line 1
|
line 1
|
||||||
|
<p>line 2
|
||||||
line 2
|
line 3</p>
|
||||||
line 3
|
<p>line 4</p>
|
||||||
|
|
||||||
line 4
|
|
||||||
</div>
|
</div>
|
@ -2,7 +2,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<p>li</p>
|
<p>li</p>
|
||||||
</li>
|
</li>
|
||||||
<li>li</li>
|
<li>
|
||||||
|
<p>li</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
<ul>
|
<ul>
|
||||||
|
13
test/data/strict_atx_heading.html
Normal file
13
test/data/strict_atx_heading.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<h1>h1</h1>
|
||||||
|
<h2>h2</h2>
|
||||||
|
<h3>h3</h3>
|
||||||
|
<h4>h4</h4>
|
||||||
|
<h5>h5</h5>
|
||||||
|
<h6>h6</h6>
|
||||||
|
<p>####### not a heading</p>
|
||||||
|
<p>#not a heading</p>
|
||||||
|
<h1>closed h1</h1>
|
||||||
|
<h1></h1>
|
||||||
|
<h2></h2>
|
||||||
|
<h1># of levels</h1>
|
||||||
|
<h1># of levels #</h1>
|
25
test/data/strict_atx_heading.md
Normal file
25
test/data/strict_atx_heading.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# h1
|
||||||
|
|
||||||
|
## h2
|
||||||
|
|
||||||
|
### h3
|
||||||
|
|
||||||
|
#### h4
|
||||||
|
|
||||||
|
##### h5
|
||||||
|
|
||||||
|
###### h6
|
||||||
|
|
||||||
|
####### not a heading
|
||||||
|
|
||||||
|
#not a heading
|
||||||
|
|
||||||
|
# closed h1 #
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
# # of levels
|
||||||
|
|
||||||
|
# # of levels # #
|
@ -1,3 +1,4 @@
|
|||||||
<p><del>strikethrough</del></p>
|
<p><del>strikethrough</del></p>
|
||||||
<p>here's <del>one</del> followed by <del>another one</del></p>
|
<p>here's <del>one</del> followed by <del>another one</del></p>
|
||||||
<p>~~ this ~~ is not one neither is ~this~</p>
|
<p>~~ this ~~ is not one neither is ~this~</p>
|
||||||
|
<p>escaped ~~this~~</p>
|
@ -2,4 +2,6 @@
|
|||||||
|
|
||||||
here's ~~one~~ followed by ~~another one~~
|
here's ~~one~~ followed by ~~another one~~
|
||||||
|
|
||||||
~~ this ~~ is not one neither is ~this~
|
~~ this ~~ is not one neither is ~this~
|
||||||
|
|
||||||
|
escaped \~\~this\~\~
|
@ -2,9 +2,21 @@
|
|||||||
<li>li</li>
|
<li>li</li>
|
||||||
<li>li</li>
|
<li>li</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>mixed markers:</p>
|
<p>mixed unordered markers:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>li</li>
|
<li>li</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
<li>li</li>
|
<li>li</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
<li>li</li>
|
<li>li</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>mixed ordered markers:</p>
|
||||||
|
<ol>
|
||||||
|
<li>starting at 1, list one</li>
|
||||||
|
<li>number 2, list one</li>
|
||||||
|
</ol>
|
||||||
|
<ol start="3">
|
||||||
|
<li>starting at 3, list two</li>
|
||||||
|
</ol>
|
@ -1,8 +1,14 @@
|
|||||||
- li
|
- li
|
||||||
- li
|
- li
|
||||||
|
|
||||||
mixed markers:
|
mixed unordered markers:
|
||||||
|
|
||||||
* li
|
* li
|
||||||
+ li
|
+ li
|
||||||
- li
|
- li
|
||||||
|
|
||||||
|
mixed ordered markers:
|
||||||
|
|
||||||
|
1. starting at 1, list one
|
||||||
|
2. number 2, list one
|
||||||
|
3) starting at 3, list two
|
6
test/data/xss_attribute_encoding.html
Normal file
6
test/data/xss_attribute_encoding.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<p><a href="https://www.example.com"">xss</a></p>
|
||||||
|
<p><img src="https://www.example.com"" alt="xss" /></p>
|
||||||
|
<p><a href="https://www.example.com'">xss</a></p>
|
||||||
|
<p><img src="https://www.example.com'" alt="xss" /></p>
|
||||||
|
<p><img src="https://www.example.com" alt="xss"" /></p>
|
||||||
|
<p><img src="https://www.example.com" alt="xss'" /></p>
|
11
test/data/xss_attribute_encoding.md
Normal file
11
test/data/xss_attribute_encoding.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[xss](https://www.example.com")
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[xss](https://www.example.com')
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
16
test/data/xss_bad_url.html
Normal file
16
test/data/xss_bad_url.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<p><a href="javascript%3Aalert(1)">xss</a></p>
|
||||||
|
<p><a href="javascript%3Aalert(1)">xss</a></p>
|
||||||
|
<p><a href="javascript%3A//alert(1)">xss</a></p>
|
||||||
|
<p><a href="javascript&colon;alert(1)">xss</a></p>
|
||||||
|
<p><img src="javascript%3Aalert(1)" alt="xss" /></p>
|
||||||
|
<p><img src="javascript%3Aalert(1)" alt="xss" /></p>
|
||||||
|
<p><img src="javascript%3A//alert(1)" alt="xss" /></p>
|
||||||
|
<p><img src="javascript&colon;alert(1)" alt="xss" /></p>
|
||||||
|
<p><a href="data%3Atext/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">xss</a></p>
|
||||||
|
<p><a href="data%3Atext/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">xss</a></p>
|
||||||
|
<p><a href="data%3A//text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">xss</a></p>
|
||||||
|
<p><a href="data&colon;text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">xss</a></p>
|
||||||
|
<p><img src="data%3Atext/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==" alt="xss" /></p>
|
||||||
|
<p><img src="data%3Atext/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==" alt="xss" /></p>
|
||||||
|
<p><img src="data%3A//text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==" alt="xss" /></p>
|
||||||
|
<p><img src="data&colon;text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==" alt="xss" /></p>
|
31
test/data/xss_bad_url.md
Normal file
31
test/data/xss_bad_url.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[xss](javascript:alert(1))
|
||||||
|
|
||||||
|
[xss]( javascript:alert(1))
|
||||||
|
|
||||||
|
[xss](javascript://alert(1))
|
||||||
|
|
||||||
|
[xss](javascript:alert(1))
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
[xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
|
||||||
|
|
||||||
|
[xss]( data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
|
||||||
|
|
||||||
|
[xss](data://text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
|
||||||
|
|
||||||
|
[xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
7
test/data/xss_text_encoding.html
Normal file
7
test/data/xss_text_encoding.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<p><script>alert(1)</script></p>
|
||||||
|
<p><script></p>
|
||||||
|
<p>alert(1)</p>
|
||||||
|
<p></script></p>
|
||||||
|
<p><script>
|
||||||
|
alert(1)
|
||||||
|
</script></p>
|
12
test/data/xss_text_encoding.md
Normal file
12
test/data/xss_text_encoding.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<script>alert(1)</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
alert(1)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
alert(1)
|
||||||
|
</script>
|
Reference in New Issue
Block a user