176 lines
41 KiB
HTML
176 lines
41 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>HTML | Markwon</title>
|
||
<meta name="description" content="Android markdown library based on commonmark specification that renders markdown as system-native Spannables (no WebView)">
|
||
<link rel="apple-touch-icon" sizes="180x180" href="/Markwon/apple-touch-icon.png?v=1">
|
||
<link rel="icon" type="image/png" sizes="16x16" href="/Markwon/favicon-16x16.png?v=1">
|
||
<link rel="icon" href="/Markwon/favicon.ico?v=1">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="/Markwon/favicon-32x32.png?v=1">
|
||
<link rel="manifest" href="/Markwon/manifest.json?v=1">
|
||
<meta name="keywords" content="android,markdown,library,spannable,markwon,commonmark">
|
||
|
||
<link rel="preload" href="/Markwon/assets/css/0.styles.3fbbce9e.css" as="style"><link rel="preload" href="/Markwon/assets/js/app.bdfd2bc6.js" as="script"><link rel="preload" href="/Markwon/assets/js/25.507307eb.js" as="script"><link rel="preload" href="/Markwon/assets/js/3.eaac0903.js" as="script"><link rel="preload" href="/Markwon/assets/js/12.98308542.js" as="script"><link rel="preload" href="/Markwon/assets/js/9.7d018a47.js" as="script"><link rel="prefetch" href="/Markwon/assets/js/42.d7ca0851.js"><link rel="prefetch" href="/Markwon/assets/js/2.81714ae9.js"><link rel="prefetch" href="/Markwon/assets/js/4.31fa5321.js"><link rel="prefetch" href="/Markwon/assets/js/5.6234b6a3.js"><link rel="prefetch" href="/Markwon/assets/js/6.ef59e46d.js"><link rel="prefetch" href="/Markwon/assets/js/7.e9b37c71.js"><link rel="prefetch" href="/Markwon/assets/js/8.9dff76ac.js"><link rel="prefetch" href="/Markwon/assets/js/10.99fc608c.js"><link rel="prefetch" href="/Markwon/assets/js/11.cdc173e9.js"><link rel="prefetch" href="/Markwon/assets/js/13.83b81b01.js"><link rel="prefetch" href="/Markwon/assets/js/14.0e5fe31e.js"><link rel="prefetch" href="/Markwon/assets/js/15.724f3dc4.js"><link rel="prefetch" href="/Markwon/assets/js/16.076204be.js"><link rel="prefetch" href="/Markwon/assets/js/17.9412daf3.js"><link rel="prefetch" href="/Markwon/assets/js/18.187f0167.js"><link rel="prefetch" href="/Markwon/assets/js/19.af3507a7.js"><link rel="prefetch" href="/Markwon/assets/js/20.dc11e22f.js"><link rel="prefetch" href="/Markwon/assets/js/21.393a507f.js"><link rel="prefetch" href="/Markwon/assets/js/22.a6ac92c5.js"><link rel="prefetch" href="/Markwon/assets/js/23.9edcc0b3.js"><link rel="prefetch" href="/Markwon/assets/js/24.073942b3.js"><link rel="prefetch" href="/Markwon/assets/js/26.87c7e366.js"><link rel="prefetch" href="/Markwon/assets/js/27.a6f7a96f.js"><link rel="prefetch" href="/Markwon/assets/js/28.c0caacb4.js"><link rel="prefetch" href="/Markwon/assets/js/29.230c7321.js"><link rel="prefetch" href="/Markwon/assets/js/30.45e92827.js"><link rel="prefetch" href="/Markwon/assets/js/31.3a2ff699.js"><link rel="prefetch" href="/Markwon/assets/js/32.662e2ab9.js"><link rel="prefetch" href="/Markwon/assets/js/33.d83b2cb7.js"><link rel="prefetch" href="/Markwon/assets/js/34.4b19ef85.js"><link rel="prefetch" href="/Markwon/assets/js/35.1684da38.js"><link rel="prefetch" href="/Markwon/assets/js/36.9852715d.js"><link rel="prefetch" href="/Markwon/assets/js/37.e98b3352.js"><link rel="prefetch" href="/Markwon/assets/js/38.09771599.js"><link rel="prefetch" href="/Markwon/assets/js/39.37003a65.js"><link rel="prefetch" href="/Markwon/assets/js/40.bf595a01.js"><link rel="prefetch" href="/Markwon/assets/js/41.db50f781.js"><link rel="prefetch" href="/Markwon/assets/js/43.78500964.js"><link rel="prefetch" href="/Markwon/assets/js/44.60fec7f9.js"><link rel="prefetch" href="/Markwon/assets/js/45.78224b99.js"><link rel="prefetch" href="/Markwon/assets/js/46.9a7f306b.js"><link rel="prefetch" href="/Markwon/assets/js/47.42b56911.js"><link rel="prefetch" href="/Markwon/assets/js/48.cceb75d4.js"><link rel="prefetch" href="/Markwon/assets/js/49.20507df8.js"><link rel="prefetch" href="/Markwon/assets/js/50.f89d88b1.js"><link rel="prefetch" href="/Markwon/assets/js/51.d7ac54ce.js"><link rel="prefetch" href="/Markwon/assets/js/52.394ded4e.js"><link rel="prefetch" href="/Markwon/assets/js/53.144cf408.js"><link rel="prefetch" href="/Markwon/assets/js/54.0f936c4f.js"><link rel="prefetch" href="/Markwon/assets/js/55.5b7382a9.js"><link rel="prefetch" href="/Markwon/assets/js/56.1cf2f788.js"><link rel="prefetch" href="/Markwon/assets/js/57.1b7dddc1.js"><link rel="prefetch" href="/Markwon/assets/js/58.5271aaaf.js"><link rel="prefetch" href="/Markwon/assets/js/59.7ef6ac9a.js"><link rel="prefetch" href="/Markwon/assets/js/60.9bbfa80f.js"><link rel="prefetch" href="/Markwon/assets/js/61.628c1500.js"><link rel="prefetch" href="/Markwon/assets/js/62.d4d206d7.js"><link rel="prefetch" href="/Markwon/assets/js/63.8ccf8bfc.js"><link rel="prefetch" href="/Markwon/assets/js/64.7672a52b.js"><link rel="prefetch" href="/Markwon/assets/js/65.c4f000dc.js"><link rel="prefetch" href="/Markwon/assets/js/66.4a29728a.js"><link rel="prefetch" href="/Markwon/assets/js/67.7331c7c7.js"><link rel="prefetch" href="/Markwon/assets/js/68.9d1d2ae1.js"><link rel="prefetch" href="/Markwon/assets/js/69.fd31295a.js"><link rel="prefetch" href="/Markwon/assets/js/70.fac8f892.js"><link rel="prefetch" href="/Markwon/assets/js/71.c3fcfb65.js"><link rel="prefetch" href="/Markwon/assets/js/72.d2389fc9.js"><link rel="prefetch" href="/Markwon/assets/js/73.6ce21170.js"><link rel="prefetch" href="/Markwon/assets/js/74.2ad91074.js"><link rel="prefetch" href="/Markwon/assets/js/75.1d59d27c.js"><link rel="prefetch" href="/Markwon/assets/js/76.f3844391.js"><link rel="prefetch" href="/Markwon/assets/js/77.4e5a82c3.js"><link rel="prefetch" href="/Markwon/assets/js/78.ff7203ee.js"><link rel="prefetch" href="/Markwon/assets/js/79.b1718a0d.js"><link rel="prefetch" href="/Markwon/assets/js/80.802db0eb.js"><link rel="prefetch" href="/Markwon/assets/js/81.9edd3cd9.js"><link rel="prefetch" href="/Markwon/assets/js/82.52f04a34.js"><link rel="prefetch" href="/Markwon/assets/js/83.3bd397c0.js"><link rel="prefetch" href="/Markwon/assets/js/84.a9af8a34.js"><link rel="prefetch" href="/Markwon/assets/js/85.2a0d8d40.js">
|
||
<link rel="stylesheet" href="/Markwon/assets/css/0.styles.3fbbce9e.css">
|
||
</head>
|
||
<body>
|
||
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/Markwon/" class="home-link router-link-active"><!----> <span class="site-name">Markwon</span></a> <div class="links" style="max-width:nullpx;"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/Markwon/docs/v4/install.html" class="nav-link">Install</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">API Version</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>Latest</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/Markwon/" class="nav-link">4.x.x</a></li></ul></li><li class="dropdown-item"><h4>Legacy</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/Markwon/docs/v3/install.html" class="nav-link">3.x.x</a></li><li class="dropdown-subitem"><a href="/Markwon/docs/v2/" class="nav-link router-link-active">2.x.x</a></li></ul></li></ul></div></div><div class="nav-item"><a href="https://github.com/noties/Markwon/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
Changelog
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/noties/Markwon" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
Github
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/Markwon/docs/v4/install.html" class="nav-link">Install</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">API Version</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>Latest</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/Markwon/" class="nav-link">4.x.x</a></li></ul></li><li class="dropdown-item"><h4>Legacy</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/Markwon/docs/v3/install.html" class="nav-link">3.x.x</a></li><li class="dropdown-subitem"><a href="/Markwon/docs/v2/" class="nav-link router-link-active">2.x.x</a></li></ul></li></ul></div></div><div class="nav-item"><a href="https://github.com/noties/Markwon/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
Changelog
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><a href="https://github.com/noties/Markwon" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
Github
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav> <ul class="sidebar-links"><li><a href="/Markwon/docs/v2/getting-started.html" class="sidebar-link">Getting started</a></li><li><a href="/Markwon/docs/v2/install.html" class="sidebar-link">Installation</a></li><li><a href="/Markwon/docs/v2/configure.html" class="sidebar-link">Configuration</a></li><li><a href="/Markwon/docs/v2/theme.html" class="sidebar-link">Theme</a></li><li><a href="/Markwon/docs/v2/factory.html" class="sidebar-link">Factory</a></li><li><a href="/Markwon/docs/v2/image-loader.html" class="sidebar-link">Images</a></li><li><a href="/Markwon/docs/v2/syntax-highlight.html" class="sidebar-link">Syntax highlight</a></li><li><a href="/Markwon/docs/v2/html.html" class="active sidebar-link">HTML</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#parser" class="sidebar-link">Parser</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#empty-tag-replacement" class="sidebar-link">Empty tag replacement</a></li><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#non-closed-tags" class="sidebar-link">Non-closed tags</a></li><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#implementation-note" class="sidebar-link">Implementation note</a></li></ul></li><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#renderer" class="sidebar-link">Renderer</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#custom-tag-handler" class="sidebar-link">Custom tag handler</a></li></ul></li><li class="sidebar-sub-header"><a href="/Markwon/docs/v2/html.html#exclude-html-parsing" class="sidebar-link">Exclude HTML parsing</a></li></ul></li><li><a href="/Markwon/docs/v2/view.html" class="sidebar-link">MarkwonView</a></li></ul> </div> <div class="page"> <div class="content"><h1 id="html"><a href="#html" aria-hidden="true" class="header-anchor">#</a> HTML <span class="badge tip top" data-v-099ab69c>2.0.0</span></h1> <div class="warning custom-block"><p class="custom-block-title">WARNING</p> <p>This is documentation for <u>legacy</u> versions. For the most current version <a href="/Markwon/">click here.</a></p></div> <p>Starting with version <code>2.0.0</code> <code>Markwon</code> brings the whole HTML parsing/rendering
|
||
stack <em>on-site</em>. The main reason for this are <em>special</em> definitions of HTML nodes
|
||
by <a href="https://spec.commonmark.org/0.28/" target="_blank" rel="noopener noreferrer">
|
||
commonmark spec
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>. More specifically: <a href="https://spec.commonmark.org/0.28/#raw-html" target="_blank" rel="noopener noreferrer">
|
||
inline
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>
|
||
and <a href="https://spec.commonmark.org/0.28/#html-blocks" target="_blank" rel="noopener noreferrer">
|
||
block
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>.
|
||
These two are <em>a bit</em> different from <em>native</em> HTML understanding.
|
||
Well, they are <em>completely</em> different and share only the same names as
|
||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements" target="_blank" rel="noopener noreferrer">
|
||
HTML-inline
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements" target="_blank" rel="noopener noreferrer">
|
||
HTML-block
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>
|
||
elements. This leads to situations when for example an <code><i></code> tag is considered
|
||
a block when it's used like this:</p> <div class="language-markdown extra-class"><pre class="language-markdown"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span><span class="token punctuation">></span></span>
|
||
Hello from italics tag
|
||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span>
|
||
</code></pre></div><div class="tip custom-block"><p class="custom-block-title">A bit of background</p> <br> <a href="https://github.com/noties/Markwon/issues/52" target="_blank" rel="noopener noreferrer">This issue<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> had brought attention to differences between HTML & commonmark implementations. <br><br></div> <p>Let's modify code snippet above <em>a bit</em>:</p> <div class="language-markdown extra-class"><div class="highlight-lines"><br><br><div class="highlighted"> </div><br><br></div><pre class="language-markdown"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span><span class="token punctuation">></span></span>
|
||
Hello from italics tag
|
||
|
||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span>
|
||
</code></pre></div><p>We have just added a <code>new-line</code> before closing <code></i></code> tag. And this
|
||
changes everything as now, according to the <a href="https://spec.commonmark.org/dingus/" target="_blank" rel="noopener noreferrer">
|
||
commonmark dingus
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>,
|
||
we have 2 HtmlBlocks: one before <code>new-line</code> (containing open <code><i></code> tag and text content)
|
||
and one after (containing as little as closing <code></i></code> tag).</p> <p>If we modify code snippet <em>a bit</em> again:</p> <div class="language-markdown extra-class"><div class="highlight-lines"><br><br><br><div class="highlighted"> </div><br></div><pre class="language-markdown"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span><span class="token punctuation">></span></span>
|
||
Hello from italics tag
|
||
|
||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>b</span><span class="token punctuation">></span></span>bold><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>b</span><span class="token punctuation">></span></span>
|
||
</code></pre></div><p>We will have 1 HtmlBlock (from previous snippet) and a bunch of HtmlInlines:</p> <ul><li>HtmlInline (<code><i></code>)</li> <li>HtmlInline (<code><b></code>)</li> <li>Text (<code>bold</code>)</li> <li>HtmlInline (<code></b></code>)</li></ul> <p>Those <em>little</em> differences render <code>Html.fromHtml</code> (which was used in <code>1.x.x</code> versions)
|
||
useless. And actually it renders most of the HTML parsers implementations useless,
|
||
as most of them do not allow processing of HTML fragments in a raw fashion
|
||
without <em>fixing</em> content on-the-fly.</p> <p>Both <code>TagSoup</code> and <code>Jsoup</code> HTML parsers (that were considered for this project) are built to deal with
|
||
<em>malicious</em> HTML code (<em>all HTML code</em>? 😶). So, when supplied
|
||
with a <code><i>italic</code> fragment they will make it <code><i>italic</i></code>.
|
||
And it's a good thing, but consider these fragments for the sake of markdown:</p> <ul><li><code><i>italic</code></li> <li><code><b>bold italic</code></li> <li><code></b><i></code></li></ul> <p>We will get:</p> <ul><li><code><i>italic </i></code></li> <li><code><b>bold italic</b></code></li></ul> <p><em><sup>*</sup> Or to be precise: <code><html><head></head><body><i>italic </i></body></html></code> &
|
||
<code><html><head></head><body><b>bold italic</b></body></html></code></em></p> <p>Which will be rendered in a final document:</p> <table><thead><tr><th>expected</th> <th>actual</th></tr></thead> <tbody><tr><td><i>italic <b>bold italic</b></i></td> <td><i>italic </i><b>bold italic</b></td></tr></tbody></table> <p>This might seem like a minor problem, but add more tags to a document,
|
||
introduce some deeply nested structures, spice openning and closing tags up
|
||
by adding markdown markup between them and finally write <em>malicious</em> HTML code 😆!</p> <p>There is no such problem on the <em>frontend</em> for which commonmark specification is mostly
|
||
aimed as <em>frontend</em> runs in a web-browser environment. After all <em>parsed</em> markdown
|
||
will become HTML tags (most common usage). And web-browser will know how to render final result.</p> <p>We, on the other hand, do not posess HTML heritage (<em>thank 🤖!</em>), but still
|
||
want to display some HTML to style resulting markdown a bit. That's why <code>Markwon</code>
|
||
incorporated own HTML parsing logic. It is based on the <a href="https://github.com/jhy/jsoup/" target="_blank" rel="noopener noreferrer">
|
||
Jsoup
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> project.
|
||
And makes usage of the <code>Tokekiser</code> class that allows to <em>tokenise</em> input HTML.
|
||
All other code that doesn't follow this purpose was removed. It's safe to use
|
||
in projects that already have <code>jsoup</code> dependency as <code>Markwon</code> repackaged <strong>jsoup</strong> source classes
|
||
(which could be found <a href="https://github.com/noties/Markwon/tree/master/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/jsoup" target="_blank" rel="noopener noreferrer">
|
||
here
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>)</p> <h2 id="parser"><a href="#parser" aria-hidden="true" class="header-anchor">#</a> Parser</h2> <p>There are no additional steps to configure HTML parsing. It's enabled by default.
|
||
If you wish to <em>exclude</em> it, please follow the <a href="#exclude-html-parsing">exclude</a> section below.</p> <p>The key class here is: <code>MarkwonHtmlParser</code> that is defined in <code>markwon-html-parser-api</code> module.
|
||
<code>markwon-html-parser-api</code> is a simple module that defines HTML parsing contract and
|
||
does not provide implementation.</p> <p>To change what implementation <code>Markwon</code> should use, <code>SpannableConfiguration</code> can be used:</p> <div class="language-java extra-class"><div class="highlight-lines"><br><div class="highlighted"> </div><br><br></div><pre class="language-java"><code>SpannableConfiguration<span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span>
|
||
<span class="token punctuation">.</span><span class="token function">htmlParser</span><span class="token punctuation">(</span>MarkwonHtmlParser<span class="token punctuation">)</span>
|
||
<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><p><code>markwon-html-parser-impl</code> on the other hand provides <code>MarkwonHtmlParser</code> implementation.
|
||
It's called <code>MarkwonHtmlParserImpl</code>. It can be created like this:</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">final</span> MarkwonHtmlParser htmlParser <span class="token operator">=</span> MarkwonHtmlParserImpl<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token comment">// or</span>
|
||
<span class="token keyword">final</span> MarkwonHtmlParser htmlParser <span class="token operator">=</span> MarkwonHtmlParserImpl<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>HtmlEmptyTagReplacement<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><h3 id="empty-tag-replacement"><a href="#empty-tag-replacement" aria-hidden="true" class="header-anchor">#</a> Empty tag replacement</h3> <p>In order to append text content for self-closing, void or just <em>empty</em> HTML tags,
|
||
<code>HtmlEmptyTagReplacement</code> can be used. As we cannot set Span for empty content,
|
||
we must represent empty tag with text during parsing stage (if we want it to be represented).</p> <p>Consider this:</p> <ul><li><code><img src="me-sad.JPG"></code></li> <li><code><br /></code></li> <li><code><who-am-i></who-am-i></code></li></ul> <p>By default (<code>HtmlEmptyTagReplacement.create()</code>) will handle <code>img</code> and <code>br</code> tags.
|
||
<code>img</code> will be replaced with <code>alt</code> property if it is present and <code>\uFFFC</code> if it is not.
|
||
And <code>br</code> will insert a new line.</p> <h3 id="non-closed-tags"><a href="#non-closed-tags" aria-hidden="true" class="header-anchor">#</a> Non-closed tags</h3> <p>It's possible that your HTML can contain non-closed tags. By default <code>Markwon</code> will ignore them,
|
||
but if you wish to get a bit closer to a web-browser experience, you can allow this behaviour:</p> <div class="language-java extra-class"><div class="highlight-lines"><br><div class="highlighted"> </div><br><br></div><pre class="language-java"><code>SpannableConfiguration<span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span>
|
||
<span class="token punctuation">.</span><span class="token function">htmlAllowNonClosedTags</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><div class="warning custom-block"><p class="custom-block-title">Note</p> <p>If there is (for example) an <code><i></code> tag at the start of a document and it's not closed
|
||
and <code>Markwon</code> is configured to <strong>not</strong> ignore non-closed tags (<code>.htmlAllowNonClosedTags(true)</code>),
|
||
it will make the whole document in italics</p></div> <h3 id="implementation-note"><a href="#implementation-note" aria-hidden="true" class="header-anchor">#</a> Implementation note</h3> <p><code>MarkwonHtmlParserImpl</code> does not create a unified HTML node. Instead it creates
|
||
2 collections: inline tags and block tags. Inline tags are represented as a <code>List</code>
|
||
of inline tags (<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements" target="_blank" rel="noopener noreferrer">
|
||
reference
|
||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>). And
|
||
block tags are structured in a tree. This helps to achieve <em>browser</em>-like behaviour,
|
||
when open inline tag is applied to all content (even if inside blocks) until closing tag.
|
||
All tags that are not <em>inline</em> are considered to be <em>block</em> ones.</p> <h2 id="renderer"><a href="#renderer" aria-hidden="true" class="header-anchor">#</a> Renderer</h2> <p>Unlike <code>MarkwonHtmlParser</code> <code>Markwon</code> comes with a <code>MarkwonHtmlRenderer</code> by default.</p> <p>Default implementation can be obtain like this:</p> <div class="language-java extra-class"><pre class="language-java"><code>MarkwonHtmlRenderer<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><p>Default instance have these tags <em>handled</em>:</p> <ul><li>emphasis
|
||
<ul><li><code>i</code></li> <li><code>em</code></li> <li><code>cite</code></li> <li><code>dfn</code></li></ul></li> <li>strong emphasis
|
||
<ul><li><code>b</code></li> <li><code>strong</code></li></ul></li> <li><code>sup</code> (super script)</li> <li><code>sub</code> (sub script)</li> <li>underline
|
||
<ul><li><code>u</code></li> <li><code>ins</code></li></ul></li> <li>strike through
|
||
<ul><li><code>del</code></li> <li><code>s</code></li> <li><code>strike</code></li></ul></li> <li><code>a</code> (link)</li> <li><code>ul</code> (unordered list)</li> <li><code>ol</code> (ordered list)</li> <li><code>img</code> (image)</li> <li><code>blockquote</code> (block quote)</li> <li><code>h{1-6}</code> (heading)</li></ul> <p>If you wish to <em>extend</em> default handling (or override existing),
|
||
<code>#builderWithDefaults</code> factory method can be used:</p> <div class="language-java extra-class"><pre class="language-java"><code>MarkwonHtmlRenderer<span class="token punctuation">.</span><span class="token function">builderWithDefaults</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><p>For a completely <em>clean</em> configurable instance <code>#builder</code> method can be used:</p> <div class="language-java extra-class"><pre class="language-java"><code>MarkwonHtmlRenderer<span class="token punctuation">.</span><span class="token function">builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre></div><h3 id="custom-tag-handler"><a href="#custom-tag-handler" aria-hidden="true" class="header-anchor">#</a> Custom tag handler</h3> <p>To configure <code>MarkwonHtmlRenderer</code> to handle tags differently or
|
||
create a new tag handler - <code>TagHandler</code> can be used</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">TagHandler</span> <span class="token punctuation">{</span>
|
||
|
||
<span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">void</span> <span class="token function">handle</span><span class="token punctuation">(</span>
|
||
<span class="token annotation punctuation">@NonNull</span> SpannableConfiguration configuration<span class="token punctuation">,</span>
|
||
<span class="token annotation punctuation">@NonNull</span> SpannableBuilder builder<span class="token punctuation">,</span>
|
||
<span class="token annotation punctuation">@NonNull</span> HtmlTag tag
|
||
<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre></div><p>For the most simple <em>inline</em> tag handler a <code>SimpleTagHandler</code> can be used:</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">SimpleTagHandler</span> <span class="token keyword">extends</span> <span class="token class-name">TagHandler</span> <span class="token punctuation">{</span>
|
||
|
||
<span class="token annotation punctuation">@Nullable</span>
|
||
<span class="token keyword">public</span> <span class="token keyword">abstract</span> Object <span class="token function">getSpans</span><span class="token punctuation">(</span><span class="token annotation punctuation">@NonNull</span> SpannableConfiguration configuration<span class="token punctuation">,</span> <span class="token annotation punctuation">@NonNull</span> HtmlTag tag<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre></div><p>For example, <code>EmphasisHandler</code>:</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">EmphasisHandler</span> <span class="token keyword">extends</span> <span class="token class-name">SimpleTagHandler</span> <span class="token punctuation">{</span>
|
||
<span class="token annotation punctuation">@Nullable</span>
|
||
<span class="token annotation punctuation">@Override</span>
|
||
<span class="token keyword">public</span> Object <span class="token function">getSpans</span><span class="token punctuation">(</span><span class="token annotation punctuation">@NonNull</span> SpannableConfiguration configuration<span class="token punctuation">,</span> <span class="token annotation punctuation">@NonNull</span> HtmlTag tag<span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
<span class="token keyword">return</span> configuration<span class="token punctuation">.</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">emphasis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre></div><p>If you wish to handle a <em>block</em> HTML node (for example <code><ul><li>First<li>Second</ul></code>) refer
|
||
to <code>ListHandler</code> source code for reference.</p> <div class="warning custom-block"><p class="custom-block-title">WARNING</p> <p>The most important thing when implementing custom <code>TagHandler</code> is to know
|
||
what type of <code>HtmlTag</code> we are dealing with. There are 2: inline & block.
|
||
Inline tag cannot contain children. Block <em>can</em> contain children. And they
|
||
<em>most likely</em> should also be visited and <em>handled</em> by registered <code>TagHandler</code> (if any)
|
||
accordingly. See <code>TagHandler#visitChildren(configuration, builder, child);</code></p></div> <h4 id="css-inline-style-parser"><a href="#css-inline-style-parser" aria-hidden="true" class="header-anchor">#</a> Css inline style parser</h4> <p>When implementing own <code>TagHandler</code> you might want to inspect inline CSS styles
|
||
of a HTML element. <code>Markwon</code> provides an utility parser for that purpose:</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">final</span> CssInlineStyleParser inlineStyleParser <span class="token operator">=</span> CssInlineStyleParser<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token keyword">for</span> <span class="token punctuation">(</span>CssProperty property<span class="token operator">:</span> inlineStyleParser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token string">"width: 100%; height: 100%;"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
<span class="token comment">// [0] = CssProperty({width=100%}),</span>
|
||
<span class="token comment">// [1] = CssProperty({height=100%})</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre></div><h2 id="exclude-html-parsing"><a href="#exclude-html-parsing" aria-hidden="true" class="header-anchor">#</a> Exclude HTML parsing</h2> <p>If you wish to exclude HTML parsing altogether, you can manually
|
||
exclude <code>markwon-html-parser-impl</code> artifact from your projects compile classpath.
|
||
This can be beneficial if you know that markdown input won't contain
|
||
HTML and/or you wish to ignore it. Excluding HTML parsing
|
||
can speed up <code>Markwon</code> parsing and will decrease final size of
|
||
<code>Markwon</code> dependency by around <code>100kb</code>.</p> <a href="http://search.maven.org/#search|ga|1|g%3A%22ru.noties.markwon%22%20AND%20a%3A%22markwon%22"><img src="https://img.shields.io/maven-central/v/ru.noties.markwon/markwon.svg?label=markwon" alt="markwon"></a> <div class="language-groovy extra-class"><pre class="language-groovy"><code>dependencies <span class="token punctuation">{</span>
|
||
<span class="token function">implementation</span><span class="token punctuation">(</span><span class="token string gstring">"ru.noties:markwon:<span class="token expression"><span class="token punctuation">$</span><span class="token punctuation">{</span>markwonVersion<span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
exclude module<span class="token punctuation">:</span> <span class="token string">'markwon-html-parser-impl'</span>
|
||
<span class="token punctuation">}</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre></div><p>Excluding <code>markwon-html-parser-impl</code> this way will result in
|
||
<code>MarkwonHtmlParser#noOp</code> implementation. No further steps are
|
||
required.</p> <div class="warning custom-block"><p class="custom-block-title">Note</p> <p>Excluding <code>markwon-html-parser-impl</code> won't remove <em>all</em> the content between
|
||
HTML tags. It will if <code>commonmark</code> decides that a specific fragment is a
|
||
<code>HtmlBlock</code>, but it won't if fragment is considered a <code>HtmlInline</code> as <code>HtmlInline</code>
|
||
does not contain content (just a tag definition).</p></div></div> <div class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">6/17/2019, 2:08:33 PM</span></div></div> <div class="page-nav"><p class="inner"><span class="prev">
|
||
←
|
||
<a href="/Markwon/docs/v2/syntax-highlight.html" class="prev">
|
||
Syntax highlight
|
||
</a></span> <span class="next"><a href="/Markwon/docs/v2/view.html">
|
||
MarkwonView
|
||
</a>
|
||
→
|
||
</span></p></div> </div> <!----></div></div>
|
||
<script src="/Markwon/assets/js/25.507307eb.js" defer></script><script src="/Markwon/assets/js/3.eaac0903.js" defer></script><script src="/Markwon/assets/js/12.98308542.js" defer></script><script src="/Markwon/assets/js/9.7d018a47.js" defer></script><script src="/Markwon/assets/js/app.bdfd2bc6.js" defer></script>
|
||
</body>
|
||
</html>
|