Skip to content

Commit 1627b92

Browse files
authored
Migrate changelog markdown post-processing to HTML-based elements. (#8599)
1 parent bb6ff3b commit 1627b92

File tree

2 files changed

+43
-28
lines changed

2 files changed

+43
-28
lines changed

app/lib/shared/markdown.dart

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ String markdownToHtml(
5252
urlResolverFn: urlResolverFn,
5353
relativeFrom: relativeFrom,
5454
);
55-
if (isChangelog) {
56-
nodes = _groupChangelogNodes(nodes).toList();
57-
}
58-
return _renderSafeHtml(nodes, disableHashIds: disableHashIds);
55+
return _renderSafeHtml(
56+
nodes,
57+
isChangelog: isChangelog,
58+
disableHashIds: disableHashIds,
59+
);
5960
} catch (e, st) {
6061
_logger.shout('Error rendering markdown.', e, st);
6162
// safe content inside the <pre> element
@@ -96,11 +97,13 @@ List<m.Node> _rewriteRelativeUrls(
9697
/// Adds hash link HTML to header blocks.
9798
String _renderSafeHtml(
9899
List<m.Node> nodes, {
100+
required bool isChangelog,
99101
required bool disableHashIds,
100102
}) {
101103
final rawHtml = m.renderToHtml(nodes);
102104
final processedHtml = _postProcessHtml(
103105
rawHtml,
106+
isChangelog: isChangelog,
104107
disableHashIds: disableHashIds,
105108
);
106109

@@ -127,9 +130,16 @@ String _renderSafeHtml(
127130

128131
String _postProcessHtml(
129132
String rawHtml, {
133+
required bool isChangelog,
130134
required bool disableHashIds,
131135
}) {
132-
final root = html_parser.parseFragment(rawHtml);
136+
var root = html_parser.parseFragment(rawHtml);
137+
138+
if (isChangelog) {
139+
final oldNodes = [...root.nodes];
140+
root = html.DocumentFragment();
141+
_groupChangelogNodes(oldNodes).forEach(root.append);
142+
}
133143

134144
// Filter unsafe urls on some of the elements.
135145
_UnsafeUrlFilter().visit(root);
@@ -333,39 +343,44 @@ class _TaskListRewriteTreeVisitor extends html_parsing.TreeVisitor {
333343
/// {{log entries in their original HTML format}}
334344
/// </div>
335345
/// </div>
336-
Iterable<m.Node> _groupChangelogNodes(List<m.Node> nodes) sync* {
337-
m.Element? lastContentDiv;
346+
Iterable<html.Node> _groupChangelogNodes(List<html.Node> nodes) sync* {
347+
html.Element? lastContentDiv;
338348
String? firstHeaderTag;
339349
for (final node in nodes) {
340-
final nodeTag = node is m.Element ? node.tag : null;
350+
final nodeTag = node is html.Element ? node.localName : null;
341351
final isNewHeaderTag = firstHeaderTag == null &&
342352
nodeTag != null &&
343353
_structuralHeaderTags.contains(nodeTag);
344354
final matchesFirstHeaderTag =
345355
firstHeaderTag != null && nodeTag == firstHeaderTag;
346-
final mayBeVersion = node is m.Element &&
356+
final mayBeVersion = node is html.Element &&
347357
(isNewHeaderTag || matchesFirstHeaderTag) &&
348-
node.children!.isNotEmpty &&
349-
node.children!.first is m.Text;
350-
final versionText =
351-
mayBeVersion ? node.children!.first.textContent.trim() : null;
358+
node.nodes.isNotEmpty &&
359+
node.nodes.first is html.Text;
360+
final versionText = mayBeVersion ? node.nodes.first.text?.trim() : null;
352361
final version = mayBeVersion ? _extractVersion(versionText) : null;
353362
if (version != null) {
354363
firstHeaderTag ??= nodeTag;
355-
final titleElem = m.Element('h2', [m.Text(versionText!)])
364+
final titleElem = html.Element.tag('h2')
356365
..attributes['class'] = 'changelog-version'
357-
..generatedId = (node as m.Element).generatedId;
366+
..attributes['id'] = node.attributes['id']!
367+
..append(html.Text(versionText!));
358368

359-
lastContentDiv = m.Element('div', [])
369+
lastContentDiv = html.Element.tag('div')
360370
..attributes['class'] = 'changelog-content';
361371

362-
yield m.Element('div', [
363-
titleElem,
364-
lastContentDiv,
365-
])
366-
..attributes['class'] = 'changelog-entry';
372+
yield html.Element.tag('div')
373+
..attributes['class'] = 'changelog-entry'
374+
..append(html.Text('\n'))
375+
..append(titleElem)
376+
..append(html.Text('\n'))
377+
..append(lastContentDiv);
367378
} else if (lastContentDiv != null) {
368-
lastContentDiv.children!.add(node);
379+
final lastChild = lastContentDiv.nodes.lastOrNull;
380+
if (lastChild is html.Element && lastChild.localName == 'div') {
381+
lastContentDiv.append(html.Text('\n'));
382+
}
383+
lastContentDiv.append(node);
369384
} else {
370385
yield node;
371386
}

app/test/shared/markdown_test.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,8 @@ void main() {
304304
'<div class="changelog-content">\n'
305305
'<ul>\n'
306306
'<li>change1</li>\n'
307-
'</ul>\n'
308-
'</div>\n'
307+
'</ul>'
308+
'</div>'
309309
'</div>\n');
310310
});
311311

@@ -324,13 +324,13 @@ void main() {
324324
'<li>\n<p>change1</p>\n</li>\n'
325325
'<li>\n<p>change2</p>\n</li>\n'
326326
'</ul>\n'
327-
'</div>\n'
328-
'</div>\n'
327+
'</div>'
328+
'</div>'
329329
'<div class="changelog-entry">\n'
330330
'<h2 class="changelog-version hash-header" id="090">0.9.0 <a href="#090" class="hash-link">#</a></h2>\n'
331331
'<div class="changelog-content">\n'
332-
'<p>Mostly refactoring</p>\n'
333-
'</div>\n'
332+
'<p>Mostly refactoring</p>'
333+
'</div>'
334334
'</div>\n');
335335
});
336336

0 commit comments

Comments
 (0)