Skip to content

Commit 1c64091

Browse files
authored
Dartdoc SEO updates (#1420)
* Dartdoc: link to the package main page when it is the latest version. * Refactor canonical element handling * Add link rel='alternate' to the generated dartdoc header for non-latest package versions. * Adding noindex meta header to non-latest package versions. * Adding noindex meta header to below-class API pages.
1 parent c7a5d31 commit 1c64091

11 files changed

+72
-16
lines changed

app/lib/dartdoc/customization.dart

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,15 @@ class DartdocCustomizer {
4242

4343
String customizeHtml(String html) {
4444
final doc = html_parser.parse(html);
45-
_stripCanonicalUrl(doc);
45+
final canonical = doc.head.getElementsByTagName('link').firstWhere(
46+
(elem) => elem.attributes['rel'] == 'canonical',
47+
orElse: () => null,
48+
);
49+
_stripCanonicalUrl(canonical);
50+
_addAlternateUrl(doc.head, canonical);
4651
_addAnalyticsTracker(doc.head);
4752
final breadcrumbs = doc.body.querySelector('.breadcrumbs');
53+
final breadcrumbsDepth = breadcrumbs?.children?.length ?? 0;
4854
if (breadcrumbs != null) {
4955
_addPubSiteLogo(breadcrumbs);
5056
_addPubPackageLink(breadcrumbs);
@@ -57,22 +63,44 @@ class DartdocCustomizer {
5763
.where((e) => e.attributes['href'] == 'index.html')
5864
.forEach((e) => e.attributes['href'] = docRoot);
5965
}
66+
if (!isLatestStable || breadcrumbsDepth > 3) {
67+
_addMetaNoIndex(doc.head);
68+
}
6069
return doc.outerHtml;
6170
}
6271

63-
void _stripCanonicalUrl(Document doc) {
64-
doc.head
65-
.getElementsByTagName('link')
66-
.where((elem) => elem.attributes['rel'] == 'canonical')
67-
.forEach(
68-
(elem) {
69-
final href = elem.attributes['href'];
70-
if (href != null && href.endsWith('/index.html')) {
71-
elem.attributes['href'] =
72-
href.substring(0, href.length - 'index.html'.length);
73-
}
74-
},
75-
);
72+
void _stripCanonicalUrl(Element elem) {
73+
if (elem == null) return;
74+
final href = elem.attributes['href'];
75+
if (href != null && href.endsWith('/index.html')) {
76+
elem.attributes['href'] =
77+
href.substring(0, href.length - 'index.html'.length);
78+
}
79+
}
80+
81+
void _addAlternateUrl(Element head, Element canonical) {
82+
if (isLatestStable) return;
83+
84+
final link = new Element.tag('link');
85+
link.attributes['rel'] = 'alternate';
86+
link.attributes['href'] = pkgDocUrl(packageName, isLatest: true);
87+
88+
if (canonical == null) {
89+
head.append(link);
90+
return;
91+
}
92+
93+
head.insertBefore(link, canonical);
94+
head.insertBefore(new Text('\n '), canonical);
95+
}
96+
97+
void _addMetaNoIndex(Element head) {
98+
final meta = new Element.tag('meta');
99+
meta.attributes['name'] = 'robots';
100+
meta.attributes['content'] = 'noindex';
101+
102+
head.insertBefore(meta, head.firstChild);
103+
head.insertBefore(new Text('\n '), head.firstChild);
76104
}
77105

78106
void _addAnalyticsTracker(Element head) {
@@ -108,8 +136,8 @@ class DartdocCustomizer {
108136
}
109137

110138
void _addPubPackageLink(Element breadcrumbs) {
111-
final pubPackageLink =
112-
pkgPageUrl(packageName, version: packageVersion, includeHost: true);
139+
final pubPackageLink = pkgPageUrl(packageName,
140+
version: isLatestStable ? null : packageVersion, includeHost: true);
113141
final pubPackageText = '$packageName package';
114142
if (breadcrumbs.children.length == 1) {
115143
// we are on the index page
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- <meta name="robots" content="noindex">
2+
- <link rel="alternate" href="/documentation/pana/latest/">
3+
- <li><a href="https://pub.dartlang.org/packages/pana/versions/0.10.2+0">pana package</a></li>
4+
+ <li><a href="https://pub.dartlang.org/packages/pana">pana package</a></li>

app/test/dartdoc/golden/pana_0.10.2_index.out.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html><html lang="en"><head>
2+
<meta name="robots" content="noindex">
23
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-26406144-13"></script>
34
<script>
45
window.dataLayer = window.dataLayer || [];
@@ -12,6 +13,7 @@
1213
<meta name="generator" content="made with love by dartdoc 0.20.0">
1314
<meta name="description" content="pana API docs, for the Dart programming language.">
1415
<title>pana - Dart API docs</title>
16+
<link rel="alternate" href="/documentation/pana/latest/">
1517
<link rel="canonical" href="https://pub.dartlang.org/documentation/pana/0.10.2/">
1618

1719
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500,400i,400,300|Source+Sans+Pro:400,300,700" rel="stylesheet">
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
- <meta name="robots" content="noindex">
2+
- <link rel="alternate" href="/documentation/pana/latest/">
3+
- <li><a href="https://pub.dartlang.org/packages/pana/versions/0.10.2+0">pana package</a></li>
14
- <li><a href="/documentation/pana/0.10.2+0/">documentation</a></li>
5+
+ <li><a href="https://pub.dartlang.org/packages/pana">pana package</a></li>
26
+ <li><a href="/documentation/pana/latest/">documentation</a></li>

app/test/dartdoc/golden/pana_0.10.2_license_file_class.out.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html><html lang="en"><head>
2+
<meta name="robots" content="noindex">
23
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-26406144-13"></script>
34
<script>
45
window.dataLayer = window.dataLayer || [];
@@ -11,6 +12,7 @@
1112
<meta name="viewport" content="width=device-width, initial-scale=1">
1213
<meta name="description" content="API docs for the LicenseFile class from the pana library, for the Dart programming language.">
1314
<title>LicenseFile class - pana library - Dart API</title>
15+
<link rel="alternate" href="/documentation/pana/latest/">
1416
<link rel="canonical" href="https://pub.dartlang.org/documentation/pana/0.10.2/pana/LicenseFile-class.html">
1517
<!-- required because all the links are pseudo-absolute -->
1618
<base href="..">
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
- <link rel="alternate" href="/documentation/pana/latest/">
2+
- <li><a href="https://pub.dartlang.org/packages/pana/versions/0.10.2+0">pana package</a></li>
13
- <li><a href="/documentation/pana/0.10.2+0/">documentation</a></li>
4+
+ <li><a href="https://pub.dartlang.org/packages/pana">pana package</a></li>
25
+ <li><a href="/documentation/pana/latest/">documentation</a></li>

app/test/dartdoc/golden/pana_0.10.2_license_file_constructor.out.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html><html lang="en"><head>
2+
<meta name="robots" content="noindex">
23
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-26406144-13"></script>
34
<script>
45
window.dataLayer = window.dataLayer || [];
@@ -11,6 +12,7 @@
1112
<meta name="viewport" content="width=device-width, initial-scale=1">
1213
<meta name="description" content="API docs for the LicenseFile constructor from the Class LicenseFile class from the pana library, for the Dart programming language.">
1314
<title>LicenseFile constructor - LicenseFile class - pana library - Dart API</title>
15+
<link rel="alternate" href="/documentation/pana/latest/">
1416
<link rel="canonical" href="https://pub.dartlang.org/documentation/pana/0.10.2/pana/LicenseFile/LicenseFile.html">
1517
<!-- required because all the links are pseudo-absolute -->
1618
<base href="../..">
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
- <link rel="alternate" href="/documentation/pana/latest/">
2+
- <li><a href="https://pub.dartlang.org/packages/pana/versions/0.10.2+0">pana package</a></li>
13
- <li><a href="/documentation/pana/0.10.2+0/">documentation</a></li>
4+
+ <li><a href="https://pub.dartlang.org/packages/pana">pana package</a></li>
25
+ <li><a href="/documentation/pana/latest/">documentation</a></li>

app/test/dartdoc/golden/pana_0.10.2_license_file_name_field.out.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html><html lang="en"><head>
2+
<meta name="robots" content="noindex">
23
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-26406144-13"></script>
34
<script>
45
window.dataLayer = window.dataLayer || [];
@@ -11,6 +12,7 @@
1112
<meta name="viewport" content="width=device-width, initial-scale=1">
1213
<meta name="description" content="API docs for the name property from the LicenseFile class, for the Dart programming language.">
1314
<title>name property - LicenseFile class - pana library - Dart API</title>
15+
<link rel="alternate" href="/documentation/pana/latest/">
1416
<link rel="canonical" href="https://pub.dartlang.org/documentation/pana/0.10.2/pana/LicenseFile/name.html">
1517
<!-- required because all the links are pseudo-absolute -->
1618
<base href="../..">
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
- <meta name="robots" content="noindex">
2+
- <link rel="alternate" href="/documentation/pana/latest/">
3+
- <li><a href="https://pub.dartlang.org/packages/pana/versions/0.10.2+0">pana package</a></li>
14
- <li><a href="/documentation/pana/0.10.2+0/">documentation</a></li>
5+
+ <li><a href="https://pub.dartlang.org/packages/pana">pana package</a></li>
26
+ <li><a href="/documentation/pana/latest/">documentation</a></li>

app/test/dartdoc/golden/pana_0.10.2_pretty_json.out.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html><html lang="en"><head>
2+
<meta name="robots" content="noindex">
23
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-26406144-13"></script>
34
<script>
45
window.dataLayer = window.dataLayer || [];
@@ -11,6 +12,7 @@
1112
<meta name="viewport" content="width=device-width, initial-scale=1">
1213
<meta name="description" content="API docs for the prettyJson function from the pana library, for the Dart programming language.">
1314
<title>prettyJson function - pana library - Dart API</title>
15+
<link rel="alternate" href="/documentation/pana/latest/">
1416
<link rel="canonical" href="https://pub.dartlang.org/documentation/pana/0.10.2/pana/prettyJson.html">
1517
<!-- required because all the links are pseudo-absolute -->
1618
<base href="..">

0 commit comments

Comments
 (0)