Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 25 additions & 22 deletions app/lib/shared/markdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,11 @@ String _renderSafeHtml(
List<m.Node> nodes, {
required bool disableHashIds,
}) {
if (!disableHashIds) {
// add hash link HTML to header blocks
final hashLink = _HashLink();
nodes.forEach((node) => node.accept(hashLink));
}

final rawHtml = m.renderToHtml(nodes);
final processedHtml = _postProcessHtml(rawHtml);
final processedHtml = _postProcessHtml(
rawHtml,
disableHashIds: disableHashIds,
);

// Renders the sanitized HTML.
final html = sanitizeHtml(
Expand All @@ -128,7 +125,10 @@ String _renderSafeHtml(
return '$html\n';
}

String _postProcessHtml(String rawHtml) {
String _postProcessHtml(
String rawHtml, {
required bool disableHashIds,
}) {
final root = html_parser.parseFragment(rawHtml);

// Filter unsafe urls on some of the elements.
Expand All @@ -137,35 +137,38 @@ String _postProcessHtml(String rawHtml) {
// Transform GitHub task lists.
_TaskListRewriteTreeVisitor().visit(root);

if (!disableHashIds) {
// add hash link HTML to header blocks
_HashLink().visit(root);
}

return root.outerHtml;
}

/// Adds an extra <a href="#hash">#</a> element to h1, h2 and h3 elements.
class _HashLink implements m.NodeVisitor {
class _HashLink extends html_parsing.TreeVisitor {
@override
void visitText(m.Text text) {}
void visitElement(html.Element element) {
super.visitElement(element);

@override
bool visitElementBefore(m.Element element) => true;
final isHeaderWithHash = element.attributes.containsKey('id') &&
_structuralHeaderTags.contains(element.localName!);

@override
void visitElementAfter(m.Element element) {
final isHeaderWithHash = element.generatedId != null &&
_structuralHeaderTags.contains(element.tag);
if (isHeaderWithHash) {
_addHashLink(element, element.generatedId!);
_addHashLink(element, element.attributes['id']!);
}
}

void _addHashLink(m.Element element, String id) {
void _addHashLink(html.Element element, String id) {
final currentClasses = element.attributes['class'] ?? '';
element.attributes['class'] = '$currentClasses hash-header'.trim();
element.children!.addAll([
m.Text(' '),
m.Element('a', [m.Text('#')])
element.append(html.Text(' '));
element.append(
html.Element.tag('a')
..text = '#'
..attributes['href'] = '#$id'
..attributes['class'] = 'hash-link',
]);
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/help_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ <h3 class="foldable-button">
<img class="standalone-side-image" src="/static/hash-%%etag%%/img/packages-side.webp" alt="" width="400" height="400" role="presentation"/>
</div>
<div class="standalone-content">
<h1 class="hash-header" id="help">
<h1 id="help" class="hash-header">
Help
<a href="#help" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="oxygen">
<h1 id="oxygen" class="hash-header">
oxygen
<a href="#oxygen" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_page_discontinued.html
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="pkg">
<h1 id="pkg" class="hash-header">
pkg
<a href="#pkg" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_page_flutter_plugin.html
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="flutter_titanium">
<h1 id="flutter_titanium" class="hash-header">
flutter_titanium
<a href="#flutter_titanium" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_page_publisher.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="neon">
<h1 id="neon" class="hash-header">
neon
<a href="#neon" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_page_retracted.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="pkg">
<h1 id="pkg" class="hash-header">
pkg
<a href="#pkg" class="hash-link">#</a>
</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="pkg">
<h1 id="pkg" class="hash-header">
pkg
<a href="#pkg" class="hash-link">#</a>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion app/test/frontend/golden/pkg_show_version_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="oxygen">
<h1 id="oxygen" class="hash-header">
oxygen
<a href="#oxygen" class="hash-link">#</a>
</h1>
Expand Down
8 changes: 4 additions & 4 deletions app/test/shared/markdown_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void main() {

test('render link id and class', () {
expect(markdownToHtml('# ABC def'),
'<h1 class="hash-header" id="abc-def">ABC def <a href="#abc-def" class="hash-link">#</a></h1>\n');
'<h1 id="abc-def" class="hash-header">ABC def <a href="#abc-def" class="hash-link">#</a></h1>\n');
});

test('task list', () {
Expand Down Expand Up @@ -298,7 +298,7 @@ void main() {
'\n'
'- change1',
isChangelog: true),
'<h1 class="hash-header" id="changelog">Changelog <a href="#changelog" class="hash-link">#</a></h1>\n'
'<h1 id="changelog" class="hash-header">Changelog <a href="#changelog" class="hash-link">#</a></h1>\n'
'<div class="changelog-entry">\n'
'<h2 class="changelog-version hash-header" id="100">1.0.0 <a href="#100" class="hash-link">#</a></h2>\n'
'<div class="changelog-content">\n'
Expand All @@ -316,7 +316,7 @@ void main() {
'## 1.0.0\n\n- change1\n\n- change2\n\n'
'## 0.9.0\n\nMostly refactoring',
isChangelog: true),
'<h1 class="hash-header" id="changelog">Changelog <a href="#changelog" class="hash-link">#</a></h1>\n'
'<h1 id="changelog" class="hash-header">Changelog <a href="#changelog" class="hash-link">#</a></h1>\n'
'<div class="changelog-entry">\n'
'<h2 class="changelog-version hash-header" id="100">1.0.0 <a href="#100" class="hash-link">#</a></h2>\n'
'<div class="changelog-content">\n'
Expand Down Expand Up @@ -362,7 +362,7 @@ void main() {
expect(lines.where((l) => l.contains('changelog-version')), [
'<h2 class="changelog-version hash-header" id="210">2.1.0 <a href="#210" class="hash-link">#</a></h2>',
'<h2 class="changelog-version hash-header" id="200">2.0.0 <a href="#200" class="hash-link">#</a></h2>',
'<h2 class="changelog-version hash-header" id="100-2">1.0.0 <a href="#100" class="hash-link">#</a></h2>',
'<h2 class="changelog-version hash-header" id="100-2">1.0.0 <a href="#100-2" class="hash-link">#</a></h2>',
]);
});

Expand Down
2 changes: 1 addition & 1 deletion app/test/task/testdata/goldens/packages/oxygen.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="oxygen">
<h1 id="oxygen" class="hash-header">
oxygen
<a href="#oxygen" class="hash-link">#</a>
</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="oxygen">
<h1 id="oxygen" class="hash-header">
oxygen
<a href="#oxygen" class="hash-link">#</a>
</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ <h3 class="detail-lead-title">Metadata</h3>
<div class="detail-container detail-body-main">
<div class="detail-tabs-content">
<section class="tab-content detail-tab-readme-content -active markdown-body">
<h1 class="hash-header" id="oxygen">
<h1 id="oxygen" class="hash-header">
oxygen
<a href="#oxygen" class="hash-link">#</a>
</h1>
Expand Down
Loading