mirror of
https://github.com/erusev/parsedown.git
synced 2025-09-04 12:15:27 +02:00
Compare commits
75 Commits
1.8.0-beta
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
0b274ac959 | ||
|
5b74b74145 | ||
|
95c7e4c3d7 | ||
|
c9dc49f68f | ||
|
28a9b057c7 | ||
|
e0082193b1 | ||
|
999fcf7886 | ||
|
582f9f9cd1 | ||
|
e76c4e44be | ||
|
cfb313fb1f | ||
|
9b14567c57 | ||
|
c65c451606 | ||
|
0476f3be5b | ||
|
9d00deadcd | ||
|
15048b0210 | ||
|
e7a3bccbae | ||
|
26362c5fe9 | ||
|
89880dd0a9 | ||
|
44fd383db7 | ||
|
54f1ffc214 | ||
|
6ae01284b8 | ||
|
26cfde9dbf | ||
|
232c57201e | ||
|
5362f4cbe3 | ||
|
b3e2fa192c | ||
|
908754bcdd | ||
|
1ff0382739 | ||
|
f5aa6fd1ca | ||
|
77947eda2f | ||
|
0586729b46 | ||
|
a86a4e19da | ||
|
6598f3860c | ||
|
1e5080190c | ||
|
1610e4747c | ||
|
3159a9d3cd | ||
|
dbee8ab4f2 | ||
|
dba4125b59 | ||
|
87b57bf3cb | ||
|
bfaa76d370 | ||
|
3825db53a2 | ||
|
bce642f2d7 | ||
|
21c8c792de | ||
|
6ca29539e1 | ||
|
a503c1a69b | ||
|
819c68899d | ||
|
4c2d79fc6a | ||
|
48a2fb26fe | ||
|
33b79d2446 | ||
|
d6d2d96459 | ||
|
d5b6ab5198 | ||
|
15e8439c7f | ||
|
ff6148f9b9 | ||
|
dfd8657bc5 | ||
|
ee64646765 | ||
|
c956090b55 | ||
|
0be26550f3 | ||
|
8e26a65a6f | ||
|
2a24a8583b | ||
|
1d55344e92 | ||
|
5dc8d1cc39 | ||
|
33cf0f0b99 | ||
|
dc1ff7d6c2 | ||
|
0f0987571d | ||
|
18eaa649b5 | ||
|
e124572b60 | ||
|
1686a34469 | ||
|
2bd7113c55 | ||
|
29fce0ec37 | ||
|
b0bbc275d4 | ||
|
72f9ca92ae | ||
|
89c3fa05d9 | ||
|
69163d6e88 | ||
|
3a0c964291 | ||
|
1829106e60 | ||
|
464f5f9329 |
37
.github/workflows/unit-tests.yaml
vendored
Normal file
37
.github/workflows/unit-tests.yaml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
on:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
phpunit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php:
|
||||||
|
- '7.1'
|
||||||
|
- '7.2'
|
||||||
|
- '7.3'
|
||||||
|
- '7.4'
|
||||||
|
- '8.0'
|
||||||
|
- '8.1'
|
||||||
|
- '8.2'
|
||||||
|
- '8.3'
|
||||||
|
- '8.4'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout the source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '${{ matrix.php }}'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
vendor/bin/phpunit
|
||||||
|
vendor/bin/phpunit test/CommonMarkTestWeak.php || true
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
composer.lock
|
composer.lock
|
||||||
vendor/
|
vendor/
|
||||||
|
.phpunit.result.cache
|
||||||
|
28
.travis.yml
28
.travis.yml
@@ -1,28 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
dist: trusty
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
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: 7.3
|
|
||||||
- php: nightly
|
|
||||||
fast_finish: true
|
|
||||||
allow_failures:
|
|
||||||
- php: 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;")" ]'
|
|
@@ -17,7 +17,7 @@ class Parsedown
|
|||||||
{
|
{
|
||||||
# ~
|
# ~
|
||||||
|
|
||||||
const version = '1.8.0-beta-7';
|
const version = '1.8.0';
|
||||||
|
|
||||||
# ~
|
# ~
|
||||||
|
|
||||||
@@ -107,6 +107,7 @@ class Parsedown
|
|||||||
'ftp://',
|
'ftp://',
|
||||||
'ftps://',
|
'ftps://',
|
||||||
'mailto:',
|
'mailto:',
|
||||||
|
'tel:',
|
||||||
'data:image/png;base64,',
|
'data:image/png;base64,',
|
||||||
'data:image/gif;base64,',
|
'data:image/gif;base64,',
|
||||||
'data:image/jpeg;base64,',
|
'data:image/jpeg;base64,',
|
||||||
@@ -555,7 +556,7 @@ class Parsedown
|
|||||||
|
|
||||||
$Block = array(
|
$Block = array(
|
||||||
'element' => array(
|
'element' => array(
|
||||||
'name' => 'h' . min(6, $level),
|
'name' => 'h' . $level,
|
||||||
'handler' => array(
|
'handler' => array(
|
||||||
'function' => 'lineElements',
|
'function' => 'lineElements',
|
||||||
'argument' => $text,
|
'argument' => $text,
|
||||||
@@ -570,7 +571,7 @@ class Parsedown
|
|||||||
#
|
#
|
||||||
# List
|
# List
|
||||||
|
|
||||||
protected function blockList($Line, array $CurrentBlock = null)
|
protected function blockList($Line, ?array $CurrentBlock = null)
|
||||||
{
|
{
|
||||||
list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]');
|
list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]');
|
||||||
|
|
||||||
@@ -807,7 +808,7 @@ class Parsedown
|
|||||||
#
|
#
|
||||||
# Setext
|
# Setext
|
||||||
|
|
||||||
protected function blockSetextHeader($Line, array $Block = null)
|
protected function blockSetextHeader($Line, ?array $Block = null)
|
||||||
{
|
{
|
||||||
if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
|
if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
|
||||||
{
|
{
|
||||||
@@ -893,7 +894,7 @@ class Parsedown
|
|||||||
#
|
#
|
||||||
# Table
|
# Table
|
||||||
|
|
||||||
protected function blockTable($Line, array $Block = null)
|
protected function blockTable($Line, ?array $Block = null)
|
||||||
{
|
{
|
||||||
if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
|
if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
|
||||||
{
|
{
|
||||||
@@ -1133,6 +1134,9 @@ class Parsedown
|
|||||||
|
|
||||||
protected function lineElements($text, $nonNestables = array())
|
protected function lineElements($text, $nonNestables = array())
|
||||||
{
|
{
|
||||||
|
# standardize line breaks
|
||||||
|
$text = str_replace(array("\r\n", "\r"), "\n", $text);
|
||||||
|
|
||||||
$Elements = array();
|
$Elements = array();
|
||||||
|
|
||||||
$nonNestables = (empty($nonNestables)
|
$nonNestables = (empty($nonNestables)
|
||||||
@@ -1490,7 +1494,7 @@ class Parsedown
|
|||||||
|
|
||||||
protected function inlineSpecialCharacter($Excerpt)
|
protected function inlineSpecialCharacter($Excerpt)
|
||||||
{
|
{
|
||||||
if ($Excerpt['text'][1] !== ' ' and strpos($Excerpt['text'], ';') !== false
|
if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false
|
||||||
and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches)
|
and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches)
|
||||||
) {
|
) {
|
||||||
return array(
|
return array(
|
||||||
|
83
README.md
83
README.md
@@ -1,82 +1,79 @@
|
|||||||
> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
|
# Parsedown
|
||||||
|
|
||||||
## Parsedown
|
[](https://packagist.org/packages/erusev/parsedown)
|
||||||
|
[](https://packagist.org/packages/erusev/parsedown)
|
||||||
|
[](https://packagist.org/packages/erusev/parsedown)
|
||||||
|
|
||||||
[](https://travis-ci.org/erusev/parsedown)
|
Better Markdown Parser in PHP — <a href="https://parsedown.org/demo">demo</a>
|
||||||
<!--[](https://packagist.org/packages/erusev/parsedown)-->
|
|
||||||
|
|
||||||
Better Markdown Parser in PHP
|
## Features
|
||||||
|
|
||||||
[Demo](http://parsedown.org/demo) |
|
- One file
|
||||||
[Benchmarks](http://parsedown.org/speed) |
|
- No dependencies
|
||||||
[Tests](http://parsedown.org/tests/) |
|
- [Super fast](http://parsedown.org/speed)
|
||||||
[Documentation](https://github.com/erusev/parsedown/wiki/)
|
- Extensible
|
||||||
|
- [GitHub flavored](https://github.github.com/gfm)
|
||||||
|
- [Tested](http://parsedown.org/tests/) in 5.3 to 7.3
|
||||||
|
- [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
||||||
|
|
||||||
### Features
|
## Installation
|
||||||
|
|
||||||
* One File
|
Install the [composer package]:
|
||||||
* No Dependencies
|
|
||||||
* Super Fast
|
|
||||||
* Extensible
|
|
||||||
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
|
|
||||||
* Tested in 5.3 to 7.2 and in HHVM
|
|
||||||
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
|
|
||||||
|
|
||||||
### Installation
|
```sh
|
||||||
#### Composer
|
composer require erusev/parsedown
|
||||||
Install the [composer package] by running the following command:
|
```
|
||||||
|
|
||||||
composer require erusev/parsedown
|
Or download the [latest release] and include `Parsedown.php`
|
||||||
|
|
||||||
#### 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"
|
[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"
|
[latest release]: https://github.com/erusev/parsedown/releases/latest "The latest release of Parsedown"
|
||||||
|
|
||||||
### Example
|
## Example
|
||||||
|
|
||||||
``` php
|
```php
|
||||||
$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
|
```
|
||||||
|
|
||||||
|
You can also parse inline markdown only:
|
||||||
|
|
||||||
|
```php
|
||||||
echo $Parsedown->line('Hello _Parsedown_!'); # prints: Hello <em>Parsedown</em>!
|
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
|
## 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.
|
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:
|
To tell Parsedown that it is processing untrusted user-input, use the following:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$parsedown = new Parsedown;
|
$Parsedown->setSafeMode(true);
|
||||||
$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/).
|
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.
|
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.
|
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
|
## Escaping HTML
|
||||||
> ⚠️ **WARNING:** This method isn't safe from XSS!
|
|
||||||
|
> WARNING: This method is not safe from XSS!
|
||||||
|
|
||||||
|
If you wish to escape HTML in trusted input, you can use the following:
|
||||||
|
|
||||||
If you wish to escape HTML **in trusted input**, you can use the following:
|
|
||||||
```php
|
```php
|
||||||
$parsedown = new Parsedown;
|
$Parsedown->setMarkupEscaped(true);
|
||||||
$parsedown->setMarkupEscaped(true);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
|
Beware that this still allows users to insert unsafe scripting vectors, ex: `[xss](javascript:alert%281%29)`.
|
||||||
|
|
||||||
### Questions
|
## Questions
|
||||||
|
|
||||||
**How does Parsedown work?**
|
**How does Parsedown work?**
|
||||||
|
|
||||||
@@ -90,8 +87,12 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
|
|||||||
|
|
||||||
**Who uses it?**
|
**Who uses it?**
|
||||||
|
|
||||||
[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).
|
[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/demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
|
||||||
|
|
||||||
**How can I help?**
|
**How can I help?**
|
||||||
|
|
||||||
Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
|
Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).
|
||||||
|
|
||||||
|
**What else should I know?**
|
||||||
|
|
||||||
|
I also make [Nota](https://nota.md/) — a notes app designed for local Markdown files.
|
||||||
|
@@ -13,11 +13,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0",
|
"php": ">=7.1",
|
||||||
"ext-mbstring": "*"
|
"ext-mbstring": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^4.8.35"
|
"phpunit/phpunit": "^7.5|^8.5|^9.6"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {"Parsedown": ""}
|
"psr-0": {"Parsedown": ""}
|
||||||
|
@@ -1,17 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Parsedown against the CommonMark spec
|
* Test Parsedown against the CommonMark spec
|
||||||
*
|
*
|
||||||
* @link http://commonmark.org/ CommonMark
|
* @link http://commonmark.org/ CommonMark
|
||||||
*/
|
*/
|
||||||
class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
|
class CommonMarkTestStrict extends TestCase
|
||||||
{
|
{
|
||||||
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt';
|
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt';
|
||||||
|
|
||||||
protected $parsedown;
|
protected $parsedown;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp() : void
|
||||||
{
|
{
|
||||||
$this->parsedown = new TestParsedown();
|
$this->parsedown = new TestParsedown();
|
||||||
$this->parsedown->setUrlsLinked(false);
|
$this->parsedown->setUrlsLinked(false);
|
||||||
|
@@ -17,7 +17,7 @@ class CommonMarkTestWeak extends CommonMarkTestStrict
|
|||||||
{
|
{
|
||||||
protected $textLevelElementRegex;
|
protected $textLevelElementRegex;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
|
@@ -15,4 +15,6 @@ still a fenced code block</code></pre>
|
|||||||
<pre><code>foo
|
<pre><code>foo
|
||||||
|
|
||||||
|
|
||||||
bar</code></pre>
|
bar</code></pre>
|
||||||
|
<pre><code class="language-php"><?php
|
||||||
|
echo "Hello World";</code></pre>
|
@@ -35,4 +35,9 @@ foo
|
|||||||
|
|
||||||
|
|
||||||
bar
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```php some-class
|
||||||
|
<?php
|
||||||
|
echo "Hello World";
|
||||||
```
|
```
|
Reference in New Issue
Block a user