npc-it
Hosting for npc-it apps
Hosting for npc-it apps
Parsedown is a Markdown parser written in PHP. It's designed to be fast, easy to use, and highly compatible with the Markdown.pl reference implementation. Parsedown converts Markdown text into HTML, making it ideal for rendering user-generated content, blog posts, documentation, and more.
Key Features:
Parsedown supports a wide range of standard Markdown syntax. Here's a rundown of the most common elements.
Use #
symbols to create headers. The number of #
symbols indicates the header level.
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
Rendered HTML:
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
Wrap text in single asterisks (*
) or underscores (_
).
*italic* or _italic_
Wrap text in double asterisks (**
) or double underscores (__
).
**bold** or __bold__
Wrap text in double tildes (~~
).
~~strikethrough~~
Rendered HTML:
<p><em>italic</em> or <em>italic</em></p>
<p><strong>bold</strong> or <strong>bold</strong></p>
<p><del>strikethrough</del></p>
Use asterisks (*
), pluses (+
), or hyphens (-
).
- Item 1
- Item 2
- Subitem 2.1
- Subitem 2.2
* Item 3
Use numbers followed by periods.
1. First item
2. Second item
1. Subitem 2.1
2. Subitem 2.2
3. Third item
Rendered HTML:
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Subitem 2.1</li>
<li>Subitem 2.2</li>
</ul>
</li>
<li>Item 3</li>
</ul>
<ol>
<li>First item</li>
<li>Second item
<ol>
<li>Subitem 2.1</li>
<li>Subitem 2.2</li>
</ol>
</li>
<li>Third item</li>
</ol>
Create hyperlinks using square brackets for text and parentheses for the URL.
[OpenAI](https://openai.com)
Rendered HTML:
<p><a href="https://openai.com">OpenAI</a></p>
Embed images using an exclamation mark (!
), square brackets for alt text, and parentheses for the image URL.

Rendered HTML:
<p><img src="https://example.com/image.jpg" alt="Alt Text" /></p>
Wrap code snippets in backticks (`
).
Use the `echo` statement in PHP.
Rendered HTML:
<p>Use the <code>echo</code> statement in PHP.</p>
Use triple backticks (```
) or tildes (~~~
) to create code blocks. Optionally specify the language for syntax highlighting.
<?php
echo "Hello, World!";
?>
console.log("Hello, World!");
Rendered HTML:
<pre><code class="language-php"><?php
echo "Hello, World!";
?>
</code></pre>
<pre><code class="language-javascript">console.log("Hello, World!");
</code></pre>
Use the greater-than symbol (>
).
> This is a blockquote.
>
> It can span multiple paragraphs.
Rendered HTML:
<blockquote>
<p>This is a blockquote.</p>
<p>It can span multiple paragraphs.</p>
</blockquote>
Create horizontal lines using three or more hyphens (---
), asterisks (***
), or underscores (___
).
---
Rendered HTML:
<hr />
Use pipes (|
) and hyphens (-
) to create tables. Parsedown supports tables similar to GitHub Flavored Markdown.
| Header 1 | Header 2 |
|----------|----------|
| Row 1 | Data |
| Row 2 | More Data|
Rendered HTML:
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1</td>
<td>Data</td>
</tr>
<tr>
<td>Row 2</td>
<td>More Data</td>
</tr>
</tbody>
</table>
You can include HTML directly within your Markdown. Parsedown allows certain HTML elements but sanitizes to prevent XSS attacks.
<p>This is an HTML paragraph.</p>
Rendered HTML:
<p>This is an HTML paragraph.</p>
Beyond standard Markdown, Parsedown offers additional features that enhance its functionality.
Parsedown includes support for many GFM features, enhancing the standard Markdown syntax.
Create checklists using a combination of hyphens, brackets, and whitespace.
- [x] Task 1
- [ ] Task 2
- [x] Task 3
Rendered HTML:
<ul>
<li><input type="checkbox" checked disabled> Task 1</li>
<li><input type="checkbox" disabled> Task 2</li>
<li><input type="checkbox" checked disabled> Task 3</li>
</ul>
Note: The default Parsedown may not support task lists out of the box. You might need to extend it or use a Parsedown extension like Parsedown Extra.
Specify alignment for table columns.
| Left Align | Center Align | Right Align |
|:-----------|:------------:|------------:|
| Data | Data | Data |
| More Data | More Data | More Data |
Rendered HTML:
<table>
<thead>
<tr>
<th style="text-align:left;">Left Align</th>
<th style="text-align:center;">Center Align</th>
<th style="text-align:right;">Right Align</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>More Data</td>
<td>More Data</td>
<td>More Data</td>
</tr>
</tbody>
</table>
Parsedown can integrate with syntax highlighting libraries (e.g., Prism.js, Highlight.js) to style code blocks based on the specified language.
Example with Highlight.js:
Include Highlight.js in Your HTML:
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
Markdown with Language-Specified Code Blocks:
```python
def hello_world():
print("Hello, world!")
Rendered HTML:
<pre><code class="language-python">def hello_world():
print("Hello, world!")
</code></pre>
Note: To enable syntax highlighting, ensure that the appropriate CSS and JS libraries are included in your project as shown above.
Parsedown can be extended to support custom Markdown syntax or to modify existing behavior. This is useful for adding specific features like custom HTML tags, macros, or new block types.
Creating a Custom Parsedown Extension:
Create a Custom Parser Class:
<?php
use Parsedown;
class ParsedownExtended extends Parsedown {
// Override methods or add new ones here.
// Example: Add a custom block type for "spoiler" sections.
protected function blockSpoiler($Line) {
if (preg_match('/^\>\>\>(.*)/', $Line['text'], $matches)) {
return [
'type' => 'spoiler',
'element' => [
'name' => 'div',
'attributes' => [
'class' => 'spoiler'
],
'text' => trim($matches[1]),
'handler' => 'line'
]
];
}
}
protected function blockSpoilerContinue($Line, $Block) {
if (strpos($Line['text'], '>>>') === 0) {
$Block['element']['text'] .= "\n" . trim(substr($Line['text'], 3));
return $Block;
}
}
protected function inlineSpoiler($Excerpt) {
if (preg_match('/\>\>([^<>]+)\<\<$/', $Excerpt['text'], $matches)) {
return [
'extent' => strlen($matches[0]),
'element' => [
'name' => 'span',
'attributes' => [
'class' => 'spoiler-text'
],
'text' => $matches[1]
]
];
}
}
}
Use the Custom Parser in Your Controller:
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Models\ContentModel;
require_once APPPATH . 'ThirdParty/ParsedownExtended.php';
class Pages extends Controller
{
protected $contentModel;
protected $parsedown;
public function __construct()
{
helper(['url', 'form']);
$this->contentModel = new ContentModel();
$this->parsedown = new \ParsedownExtended();
}
public function view($page = 'home')
{
// Sanitize and process page parameter
$page = filter_var($page, FILTER_SANITIZE_STRING);
$page = str_replace('/', DIRECTORY_SEPARATOR, $page);
$data['title'] = ucfirst(str_replace(['-', DIRECTORY_SEPARATOR], ' ', $page));
$markdownContent = $this->contentModel->getPageContent($page);
if (!$markdownContent) {
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
}
// Use ParsedownExtended to parse Markdown
$data['content'] = $this->parsedown->text($markdownContent);
// Load views
echo view('templates/header', $data);
echo view('pages/view', $data);
echo view('templates/footer', $data);
}
}
Define CSS for Custom Elements:
.spoiler {
background-color: #333;
color: #333;
position: relative;
}
.spoiler:hover {
color: #fff;
}
.spoiler-text {
background-color: #333;
color: #333;
position: relative;
}
.spoiler-text:hover {
color: #fff;
}
This example adds a custom "spoiler" block and inline syntax, enhancing your Markdown's capabilities.
Images are a fundamental part of Markdown content. Here's how to effectively manage them using Parsedown.

Example:

Rendered HTML:
<p><img src="https://openai.com/logo.png" alt="OpenAI Logo" title="OpenAI" /></p>
External Images: Host your images on external servers or CDNs.

Internal Images: Store images within your project directory.

Best Practices for Internal Images:
/public/assets/images/
.While standard Markdown allows you to set alt
text and title
, you might want to add additional attributes like class
, id
, or inline styles.
Example with HTML Attributes:
{.class #id style="width:100px;"}
Note: Parsedown does not support extension syntax out of the box for adding classes or IDs to images. To enable this functionality, you need to extend Parsedown or use Parsedown Extra.
Using Parsedown Extra:
If you require more advanced features like adding classes or IDs, consider using Parsedown Extra:
Install Parsedown Extra via Composer:
composer require erusev/parsedown-extra
Use Parsedown Extra in Your Controller:
<?php
use ParsedownExtra;
$parsedown = new ParsedownExtra();
$markdown = '{.class #id}';
$html = $parsedown->text($markdown);
echo $html;
Rendered HTML with Parsedown Extra:
<p><img src="https://example.com/image.jpg" alt="Alt Text" title="Title" class="class" id="id" /></p>
Links enrich your content by connecting it to other resources. Here's how to manage them effectively with Parsedown.
Internal Links: Point to pages within your website.
[Home](/home)
External Links: Point to external websites.
[OpenAI](https://openai.com)
Best Practices:
/home
) for internal links to avoid issues with relative paths.To have links open in new browser tabs, you need to add the target="_blank"
attribute. Standard Markdown doesn't support this directly, so you need to extend Parsedown or use custom syntax.
Using Inline HTML:
<a href="https://openai.com" target="_blank">OpenAI</a>
Automatically Adding target="_blank"
to External Links:
You can extend Parsedown to modify the link rendering behavior.
Example:
<?php
use Parsedown;
class ParsedownWithTarget extends Parsedown {
protected function inlineLink($Excerpt) {
$link = parent::inlineLink($Excerpt);
if ($link) {
$link['element']['attributes']['target'] = '_blank';
}
return $link;
}
}
// Usage
$parsedown = new ParsedownWithTarget();
$markdown = '[OpenAI](https://openai.com)';
$html = $parsedown->text($markdown);
echo $html;
Rendered HTML:
<p><a href="https://openai.com" target="_blank">OpenAI</a></p>
You can add titles to links, which appear as tooltips when users hover over them.
[OpenAI](https://openai.com "Visit OpenAI's website")
Rendered HTML:
<p><a href="https://openai.com" title="Visit OpenAI's website">OpenAI</a></p>
If you haven't already installed Parsedown, you can add it to your project using Composer:
composer require erusev/parsedown
Here's a simple example of using Parsedown to convert Markdown to HTML.
<?php
require 'vendor/autoload.php';
$parsedown = new Parsedown();
$markdown = "# Hello World\nThis is a **bold** statement.";
$html = $parsedown->text($markdown);
echo $html;
Output:
<h1>Hello World</h1>
<p>This is a <strong>bold</strong> statement.</p>
Parsedown allows some customization through its API. You can override methods to change parsing behavior or extend the class to add new features.
Customizing Markdown Parsing:
<?php
use ParsedownExtended;
class MyParsedown extends ParsedownExtended {
// Override methods or add your own
}
// Usage
$parsedown = new MyParsedown();
$markdown = "Your **Markdown** text here.";
$html = $parsedown->text($markdown);
echo $html;
When rendering user-generated Markdown content, it's crucial to prioritize security to prevent Cross-Site Scripting (XSS) attacks.
Tips:
Example Using HTML Purifier:
Install HTML Purifier via Composer:
composer require ezyang/htmlpurifier
Sanitize Parsed HTML:
<?php
require 'vendor/autoload.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$parsedown = new Parsedown();
$markdown = 'Your **Markdown** text with <script>alert("XSS")</script> here.';
$dirty_html = $parsedown->text($markdown);
$clean_html = $purifier->purify($dirty_html);
echo $clean_html;
Output:
<p>Your <strong>Markdown</strong> text with here.</p>
The <script>
tag is removed, preventing XSS attacks.
Depending on your project's needs, you might want to customize how Parsedown renders certain elements.
Examples:
Example: Adding a Custom Class to All <p>
Tags:
<?php
use Parsedown;
class ParsedownCustom extends Parsedown {
protected function element(array $Element) {
if ($Element['name'] === 'p') {
$Element['attributes']['class'] = 'custom-paragraph';
}
return parent::element($Element);
}
}
// Usage
$parsedown = new ParsedownCustom();
$markdown = 'This is a paragraph.';
$html = $parsedown->text($markdown);
echo $html;
Rendered HTML:
<p class="custom-paragraph">This is a paragraph.</p>
If your Markdown content doesn't change frequently, consider caching the parsed HTML to improve performance.
Implementation Steps:
Parse Markdown and Cache HTML:
<?php
use Parsedown;
use CodeIgniter\Cache\CacheInterface;
class ContentModel extends Model
{
protected $contentPath = WRITEPATH . 'content/';
protected $parsedown;
protected $cache;
public function __construct()
{
parent::__construct();
$this->parsedown = new Parsedown();
$this->cache = \Config\Services::cache();
}
public function getPageContent($page)
{
// Sanitize page parameter
$page = str_replace(['../', './'], '', $page);
$filePath = $this->contentPath . $page . '.md';
$cacheKey = 'page_content_' . $page;
// Check cache
if ($this->cache->get($cacheKey)) {
return $this->cache->get($cacheKey);
}
if (file_exists($filePath)) {
$markdown = file_get_contents($filePath);
$html = $this->parsedown->text($markdown);
// Save to cache for 10 minutes
$this->cache->save($cacheKey, $html, 600);
return $html;
}
return false;
}
}
Clear Cache on Content Update:
Ensure that whenever a Markdown file is updated, the corresponding cache is cleared to reflect changes.
public function updatePageContent($page, $newContent)
{
$filePath = $this->contentPath . $page . '.md';
if (file_put_contents($filePath, $newContent) !== false) {
// Clear cache
$cacheKey = 'page_content_' . $page;
$this->cache->delete($cacheKey);
return true;
}
return false;
}
To deepen your understanding and explore more advanced features, consider the following resources: