You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The HTML parser has been completely replaced. The new HTML parser is built on Python's html.parser.HTMLParser, which alleviates various bugs and simplifies maintenance of the code.
The md_in_html extension has been rebuilt on the new HTML Parser, which drastically simplifies it. Note that raw HTML elements with a markdown attribute defined are now converted to ElementTree Elements and are rendered by the serializer. Various bugs have been fixed.
Link reference parsing, abbreviation reference parsing and footnote reference parsing has all been moved from preprocessors to blockprocessors, which allows them to be nested within other block level elements. Specifically, this change was necessary to maintain the current behavior in the rebuilt md_in_html extension. A few random edge-case bugs (see the included tests) were resolved in the process.
Closes#595, closes#780, closes#830 and closes#1012.
The following tags have the `span` behavior by default: `address`, `dd`, `dt`, `h[1-6]`, `legend`, `li`, `p`, `td`,
50
+
and `th`.
53
51
54
-
Nested elements are more sensitive and must be used cautiously. To avoid
55
-
unexpected results:
52
+
For example, the following:
56
53
57
-
* Only nest elements within block mode elements.
58
-
* Follow the closing tag of inner elements with a blank line.
59
-
* Only have one level of nesting.
54
+
```
55
+
<p markdown="1">
56
+
This is not a *Markdown* Paragraph.
57
+
</p>
58
+
```
60
59
61
-
#### Complex Example:
60
+
... is rendered as:
62
61
63
-
```md
64
-
<div markdown="1" name="Example">
62
+
```html
63
+
<p>
64
+
This is not a <em>Markdown</em> Paragraph.
65
+
</p>
66
+
```
65
67
66
-
The text of the `Example` element.
68
+
### `markdown="block"` { #block }
67
69
68
-
<div markdown="1" name="DefaultBlockMode">
69
-
This text gets wrapped in `p` tags.
70
-
</div>
70
+
When the `markdown` attribute is set to `"block"`, then the parser will force the `block` behavior on the contents of
71
+
the element so long as it is one of the `block` or `span` tags.
71
72
72
-
The tail of the `DefaultBlockMode` subelement.
73
+
The content of a `block` element is parsed into block-level content. In other words, the text is rendered as
74
+
paragraphs, headers, lists, blockquotes, etc. Any inline syntax within those elements is processed as well.
73
75
74
-
<p markdown="1" name="DefaultSpanMode">
75
-
This text *is not* wrapped in additional `p` tags.
76
-
</p>
76
+
For example, the following:
77
77
78
-
The tail of the `DefaultSpanMode` subelement.
78
+
```
79
+
<section markdown="block">
80
+
# A header.
79
81
80
-
<div markdown="span" name="SpanModeOverride">
81
-
This `div` block is not wrapped in paragraph tags.
82
-
Note: Subelements are not required to have tail text.
83
-
</div>
82
+
A *Markdown* paragraph.
84
83
85
-
<p markdown="block" name="BlockModeOverride">
86
-
This `p` block *is* foolishly wrapped in further paragraph tags.
87
-
</p>
84
+
* A list item.
85
+
* A second list item.
88
86
89
-
The tail of the `BlockModeOverride` subelement.
87
+
</section>
88
+
```
89
+
90
+
... is rendered as:
91
+
92
+
```html
93
+
<section>
94
+
<h1>A header.</h1>
95
+
<p>A <em>Markdown</em> paragraph.</p>
96
+
<ul>
97
+
<li>A list item.</li>
98
+
<li>A second list item.</li>
99
+
</ul>
100
+
</section>
101
+
```
102
+
103
+
!!! warning
104
+
105
+
Forcing elements to be parsed as `block` elements when they are not by default could result in invalid HTML.
106
+
For example, one could force a `<p>` element to be nested within another `<p>` element. In most cases it is
107
+
recommended to use the default behavior of `markdown="1"`. Explicitly setting `markdown="block"` should be
108
+
reserved for advanced users who understand the HTML specification and how browsers parse and render HTML.
109
+
110
+
### `markdown="span"` { #span }
111
+
112
+
When the `markdown` attribute is set to `"span"`, then the parser will force the `span` behavior on the contents
113
+
of the element so long as it is one of the `block` or `span` tags.
114
+
115
+
The content of a `span` element is not parsed into block-level content. In other words, the content will not be
116
+
rendered as paragraphs, headers, etc. Only inline syntax will be rendered, such as links, strong, emphasis, etc.
117
+
118
+
For example, the following:
90
119
91
-
<div name="RawHtml">
92
-
Raw HTML blocks may also be nested.
120
+
```
121
+
<div markdown="span">
122
+
# *Not* a header
93
123
</div>
124
+
```
94
125
126
+
... is rendered as:
127
+
128
+
```html
129
+
<div>
130
+
# <em>Not</em> a header
95
131
</div>
132
+
```
133
+
134
+
### Ignored Elements
135
+
136
+
The following tags are always ignored, regardless of any `markdown` attribute: `canvas`, `math`, `option`, `pre`,
137
+
`script`, `style`, and `textarea`. All other raw HTML tags are treated as span-level tags and are not affected by this
138
+
extension.
139
+
140
+
### Nesting
96
141
97
-
This text is after the markdown in HTML.
142
+
When nesting multiple levels of raw HTML elements, a `markdown` attribute must be defined for each block-level
143
+
element. For any block-level element which does not have a `markdown` attribute, everything inside that element is
144
+
ignored, including child elements with `markdown` attributes.
145
+
146
+
For example, the following:
147
+
148
+
```
149
+
<article id="my-article" markdown="1">
150
+
# Article Title
151
+
152
+
A Markdown paragraph.
153
+
154
+
<section id="section-1" markdown="1">
155
+
## Section 1 Title
156
+
157
+
<p>Custom raw **HTML** which gets ignored.</p>
158
+
159
+
</section>
160
+
161
+
<section id="section-2" markdown="1">
162
+
## Section 2 Title
163
+
164
+
<p markdown="1">**Markdown** content.</p>
165
+
166
+
</section>
167
+
168
+
</article>
98
169
```
99
170
100
-
#### Complex Result:
171
+
... is rendered as:
101
172
102
173
```html
103
-
<divname="Example">
104
-
<p>The text of the <code>Example</code> element.</p>
105
-
<divname="DefaultBlockMode">
106
-
<p>This text gets wrapped in <code>p</code> tags.</p>
174
+
<articleid="my-article">
175
+
<h1>Article Title</h1>
176
+
<p>A Markdown paragraph.</p>
177
+
<sectionid="section-1">
178
+
<h2>Section 1 Title</h2>
179
+
<p>Custom raw **HTML** which gets ignored.</p>
180
+
</section>
181
+
<sectionid="section-2">
182
+
<h2>Section 2 Title</h2>
183
+
<p><strong>Markdown</strong> content.</p>
184
+
</section>
185
+
</article>
186
+
```
187
+
188
+
When the value of an element's `markdown` attribute is more permissive that its parent, then the parent's stricter
189
+
behavior is enforced. For example, a `block` element nested within a `span` element will be parsed using the `span`
190
+
behavior. However, if the value of an element's `markdown` attribute is the same as, or more restrictive than, its
191
+
parent, the the child element's behavior is observed. For example, a `block` element may contain either `block`
192
+
elements or `span` elements as children and each element will be parsed using the specified behavior.
193
+
194
+
### Tag Normalization
195
+
196
+
While the default behavior is for Markdown to not alter raw HTML, as this extension is parsing the content of raw HTML elements, it will do some normalization of the tags of block-level elements. For example, the following raw HTML:
197
+
198
+
```
199
+
<div markdown="1">
200
+
<p markdown="1">A Markdown paragraph with *no* closing tag.
201
+
<p>A raw paragraph with *no* closing tag.
107
202
</div>
108
-
<p>The tail of the <code>DefaultBlockMode</code> subelement.</p>
109
-
<pname="DefaultSpanMode">
110
-
This text <em>is not</em> wrapped in additional <code>p</code> tags.</p>
111
-
<p>The tail of the <code>DefaultSpanMode</code> subelement.</p>
112
-
<divname="SpanModeOverride">
113
-
This <code>div</code> block is not wrapped in paragraph tags.
114
-
Note: Subelements are not required to have tail text.</div>
115
-
<pname="BlockModeOverride">
116
-
<p>This <code>p</code> block <em>is</em> foolishly wrapped in further paragraph tags.</p>
203
+
```
204
+
205
+
... is rendered as:
206
+
207
+
```html
208
+
<div>
209
+
<p>A Markdown paragraph with <em>no</em> closing tag.
210
+
</p>
211
+
<p>A raw paragraph with *no* closing tag.
117
212
</p>
118
-
<p>The tail of the <code>BlockModeOverride</code> subelement.</p>
119
-
<divname="RawHtml">
120
-
Raw HTML blocks may also be nested.
121
213
</div>
214
+
```
122
215
123
-
</div>
124
-
<p>This text is after the markdown in HTML.</p>
216
+
Notice that the parser properly recognizes that an unclosed `<p>` tag ends when another `<p>` tag begins or when the
217
+
parent element ends. In both cases, a closing `</p>` was added to the end of the element, regardless of whether a
218
+
`markdown` attribute was assigned to the element.
219
+
220
+
To avoid any normalization, an element must not be a descendant of any block-level element which has a `markdown`
221
+
attribute defined.
222
+
223
+
!!! warning
224
+
225
+
The normalization behavior is only documented here so that document authors are not surprised when their carefully
226
+
crafted raw HTML is altered by Markdown. This extension should not be relied on to normalize and generate valid
227
+
HTML. For the best results, always include valid raw HTML (with both opening and closing tags) in your Markdown
228
+
documents.
229
+
230
+
## Usage
231
+
232
+
From the Python interpreter:
233
+
234
+
```pycon
235
+
>>> import markdown
236
+
>>> html = markdown.markdown(text, extensions=['md_in_html'])
0 commit comments