19
19
from ..preprocessors import Preprocessor
20
20
from ..postprocessors import RawHtmlPostprocessor
21
21
from .. import util
22
- from ..htmlparser import HTMLExtractor
22
+ from ..htmlparser import HTMLExtractor , blank_line_re
23
23
import xml .etree .ElementTree as etree
24
24
25
25
@@ -85,17 +85,9 @@ def get_state(self, tag, attrs):
85
85
else : # pragma: no cover
86
86
return None
87
87
88
- def at_line_start (self ):
89
- """At line start."""
90
-
91
- value = super ().at_line_start ()
92
- if not value and self .cleandoc and self .cleandoc [- 1 ].endswith ('\n ' ):
93
- value = True
94
- return value
95
-
96
88
def handle_starttag (self , tag , attrs ):
97
89
# Handle tags that should always be empty and do not specify a closing tag
98
- if tag in self .empty_tags :
90
+ if tag in self .empty_tags and ( self . at_line_start () or self . intail ) :
99
91
attrs = {key : value if value is not None else key for key , value in attrs }
100
92
if "markdown" in attrs :
101
93
attrs .pop ('markdown' )
@@ -106,13 +98,12 @@ def handle_starttag(self, tag, attrs):
106
98
self .handle_empty_tag (data , True )
107
99
return
108
100
109
- if tag in self .block_level_tags :
101
+ if tag in self .block_level_tags and ( self . at_line_start () or self . intail ) :
110
102
# Valueless attr (ex: `<tag checked>`) results in `[('checked', None)]`.
111
103
# Convert to `{'checked': 'checked'}`.
112
104
attrs = {key : value if value is not None else key for key , value in attrs }
113
105
state = self .get_state (tag , attrs )
114
-
115
- if self .inraw or (state in [None , 'off' ] and not self .mdstack ) or not self .at_line_start ():
106
+ if self .inraw or (state in [None , 'off' ] and not self .mdstack ):
116
107
# fall back to default behavior
117
108
attrs .pop ('markdown' , None )
118
109
super ().handle_starttag (tag , attrs )
@@ -134,6 +125,9 @@ def handle_starttag(self, tag, attrs):
134
125
self .handle_data (self .md .htmlStash .store (text ))
135
126
else :
136
127
self .handle_data (text )
128
+ if tag in self .CDATA_CONTENT_ELEMENTS :
129
+ # This is presumably a standalone tag in a code span (see #1036).
130
+ self .clear_cdata_mode ()
137
131
138
132
def handle_endtag (self , tag ):
139
133
if tag in self .block_level_tags :
@@ -159,6 +153,11 @@ def handle_endtag(self, tag):
159
153
self .cleandoc .append (self .md .htmlStash .store (element ))
160
154
self .cleandoc .append ('\n \n ' )
161
155
self .state = []
156
+ # Check if element has a tail
157
+ if not blank_line_re .match (
158
+ self .rawdata [self .line_offset + self .offset + len (self .get_endtag_text (tag )):]):
159
+ # More content exists after endtag.
160
+ self .intail = True
162
161
else :
163
162
# Treat orphan closing tag as a span level tag.
164
163
text = self .get_endtag_text (tag )
@@ -191,6 +190,8 @@ def handle_startendtag(self, tag, attrs):
191
190
self .handle_empty_tag (data , is_block = self .md .is_block_level (tag ))
192
191
193
192
def handle_data (self , data ):
193
+ if self .intail and '\n ' in data :
194
+ self .intail = False
194
195
if self .inraw or not self .mdstack :
195
196
super ().handle_data (data )
196
197
else :
0 commit comments