Skip to content
This repository was archived by the owner on Jan 21, 2024. It is now read-only.

Commit a5f7cd2

Browse files
committed
Add ablity to opt-out of iframe escaping
1 parent e3f5a61 commit a5f7cd2

File tree

5 files changed

+96
-7
lines changed

5 files changed

+96
-7
lines changed

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,36 @@ GitDown::parseAndCache($markdown, function ($parse) {
7575
});
7676
```
7777

78+
## Allowing Iframes
79+
By default, GitHub sanitizes HTML tags it deems "unsafe" like `<iframe>`s. However, it's common to embed video or audio into your markdown with `<iframe>`s.
80+
81+
GitDown can intelligently preserve your iframes by setting the `allowIframes` config option in `config/gitdown.php` to `true`.
82+
83+
```php
84+
"allowIframes" => true,
85+
```
86+
7887
## Non-Laravel Usage
7988
You can set a GitHub Personal Access Token by passing it into the `GitDown`'s constructor.
8089
`new GitDown\GitDown($token)`
8190

8291
```php
83-
(new GitDown\GitDown($token))->parse($markdown);
92+
// You can pass config options into the constructur:
93+
$gitDown = new GitDown\GitDown(
94+
$token = 'foo',
95+
$context = 'your/repo',
96+
$allowIframes = false
97+
);
98+
99+
$gitDown->parse($markdown);
84100

85101
// Pass in your own custom caching strategy.
86-
(new GitDown\GitDown($token))->parseAndCache($markdown, function ($parse) {
102+
$gitDown->parseAndCache($markdown, function ($parse) {
87103
return Cache::rememberForever(sha1($markdown), function () use ($parse) {
88104
return $parse();
89105
});
90106
});
107+
91108
```
92109

93110
## Markdown/Syntax CSS

src/GitDown.php

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,34 @@ class GitDown
88
{
99
protected $token;
1010
protected $context;
11+
protected $allowIframes;
1112

12-
public function __construct($token = null, $context = null)
13+
public function __construct($token = null, $context = null, $allowIframes = false)
1314
{
1415
$this->token = $token;
1516
$this->context = $context;
17+
$this->allowIframes = $allowIframes;
1618
}
1719

1820
public function setToken($token)
1921
{
2022
$this->token = $token;
23+
24+
return $this;
2125
}
2226

23-
public function setContext($token)
27+
public function setContext($context)
2428
{
2529
$this->context = $context;
30+
31+
return $this;
32+
}
33+
34+
public function withIframes()
35+
{
36+
$this->allowIframes = true;
37+
38+
return $this;
2639
}
2740

2841
public function parse($content)
@@ -31,14 +44,48 @@ public function parse($content)
3144
'User-Agent' => 'GitDown Plugin',
3245
] + ($this->token ? ['Authorization' => 'token '.$this->token] : []))
3346
->post('https://api.github.com/markdown', [
34-
'text' => $content,
47+
'text' => $this->encryptIframeTags($content),
3548
] + ($this->context ? ['mode' => 'gfm', 'context' => $this->context] : []));
3649

3750
if (! $response->isOk()) {
3851
throw new \Exception('GitHub API Error: ' . $response->body());
3952
}
4053

41-
return (string) $response;
54+
return $this->decryptIframeTags((string) $response);
55+
}
56+
57+
public function encryptIframeTags($input)
58+
{
59+
if (! $this->allowIframes) {
60+
return $input;
61+
}
62+
63+
if (! preg_match_all('/<iframe[^>]*?(?:\/>|>[^<]*?<\/iframe>)/', $input, $matches)) {
64+
return $input;
65+
};
66+
67+
foreach ($matches[0] as $match) {
68+
$input = str_replace($match, '\[iframe\]'. base64_encode($match).'\[endiframe\]', $input);
69+
}
70+
71+
return $input;
72+
}
73+
74+
public function decryptIframeTags($input)
75+
{
76+
if (! $this->allowIframes) {
77+
return $input;
78+
}
79+
80+
if (! preg_match_all('/\[iframe\].*\[endiframe\]/', $input, $matches)) {
81+
return $input;
82+
};
83+
84+
foreach ($matches[0] as $match) {
85+
$input = str_replace($match, base64_decode(ltrim(rtrim($match, '[endiframe]'), '[iframe]')), $input);
86+
}
87+
88+
return $input;
4289
}
4390

4491
public function parseAndCache($content, $minutes = null)

src/GitDownServiceProvider.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ class GitDownServiceProvider extends ServiceProvider
1010
public function register()
1111
{
1212
app()->singleton('gitdown', function () {
13-
return new GitDown(config('gitdown.token'));
13+
return new GitDown(
14+
config('gitdown.token'),
15+
config('gitdown.context'),
16+
config('gitdown.allowIframes')
17+
);
1418
});
1519
}
1620

src/config-stub.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,17 @@
2828

2929
'context' => null,
3030

31+
/*
32+
|--------------------------------------------------------------------------
33+
| Allow Iframes
34+
|--------------------------------------------------------------------------
35+
|
36+
| By default, GitHub escapes any HTML tags it deems "unsafe" while parsing.
37+
| For example, passing in a string like "<iframe></iframe>" will output
38+
| "&lt;iframe&gt;&lt;/iframe&gt;". This config will work-around this.
39+
|
40+
*/
41+
42+
'allowIframes' => false,
43+
3144
];

tests/GitDownTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,12 @@ protected function cacheStrategy(&$callCount)
4747
}
4848
};
4949
}
50+
51+
/** @test */
52+
public function parsed_html_preserves_iframes()
53+
{
54+
$parsed = (new GitDown(null, null, $allowIframes = true))->parse('<iframe></iframe>');
55+
56+
$this->assertEquals('<p><iframe></iframe></p>', trim($parsed));
57+
}
5058
}

0 commit comments

Comments
 (0)