Remove <base> tag, use hrefs prepended with base (#2098)
* Remove <base> tag, use hrefs prepended with base
* Add tests for relative hrefs in doc comments
* Add a CLI flag (hidden) to use the legacy behavior
* Detailed comment regarding usage of the placeholder
* Fix placeholder string in header and footer partials
diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart
index 223ed30..409f876 100644
--- a/lib/src/dartdoc_options.dart
+++ b/lib/src/dartdoc_options.dart
@@ -1422,6 +1422,9 @@
excludePackages.any((pattern) => name == pattern);
String get templatesDir => optionSet['templatesDir'].valueAt(context);
+
+ // TODO(jdkoren): temporary while we confirm href base behavior doesn't break important clients
+ bool get useBaseHref => optionSet['useBaseHref'].valueAt(context);
}
/// Instantiate dartdoc's configuration file and options parser with the
@@ -1635,6 +1638,14 @@
'property, top_level_constant, top_level_property, typedef. Partial templates are '
'supported; they must begin with an underscore, and references to them must omit the '
'leading underscore (e.g. use {{>foo}} to reference the partial template _foo.html).'),
+ DartdocOptionArgOnly<bool>('useBaseHref', false,
+ help:
+ 'Use <base href> in generated files (legacy behavior). This option '
+ 'is temporary and support will be removed in the future. Use only '
+ 'if the default behavior breaks links between your documentation '
+ 'pages, and please file an issue on Github.',
+ negatable: false,
+ hide: true),
// TODO(jcollins-g): refactor so there is a single static "create" for
// each DartdocOptionContext that traverses the inheritance tree itself.
]
diff --git a/lib/src/html/html_generator.dart b/lib/src/html/html_generator.dart
index ca9b0c6..8cac333 100644
--- a/lib/src/html/html_generator.dart
+++ b/lib/src/html/html_generator.dart
@@ -142,13 +142,17 @@
@override
final String toolVersion;
+ @override
+ final bool useBaseHref;
+
HtmlGeneratorOptions(
{this.url,
this.relCanonicalPrefix,
this.faviconPath,
String toolVersion,
this.prettyIndexJson = false,
- this.templatesDir})
+ this.templatesDir,
+ this.useBaseHref = false})
: this.toolVersion = toolVersion ?? 'unknown';
}
@@ -166,7 +170,8 @@
toolVersion: dartdocVersion,
faviconPath: config.favicon,
prettyIndexJson: config.prettyIndexJson,
- templatesDir: config.templatesDir);
+ templatesDir: config.templatesDir,
+ useBaseHref: config.useBaseHref);
return [
await HtmlGenerator.create(
diff --git a/lib/src/html/html_generator_instance.dart b/lib/src/html/html_generator_instance.dart
index 0ac5d7f..b82bbc4 100644
--- a/lib/src/html/html_generator_instance.dart
+++ b/lib/src/html/html_generator_instance.dart
@@ -76,6 +76,9 @@
});
String json = encoder.convert(indexItems);
+ if (!_options.useBaseHref) {
+ json = json.replaceAll(HTMLBASE_PLACEHOLDER, '');
+ }
_writer(path.join('categories.json'), '${json}\n');
}
@@ -118,6 +121,9 @@
});
String json = encoder.convert(indexItems);
+ if (!_options.useBaseHref) {
+ json = json.replaceAll(HTMLBASE_PLACEHOLDER, '');
+ }
_writer(path.join('index.json'), '${json}\n');
}
@@ -412,6 +418,10 @@
// Replaces '/' separators with proper separators for the platform.
String outFile = path.joinAll(filename.split('/'));
String content = template.renderString(data);
+
+ if (!_options.useBaseHref) {
+ content = content.replaceAll(HTMLBASE_PLACEHOLDER, data.htmlBase);
+ }
_writer(outFile, content,
element: data.self is Warnable ? data.self : null);
if (data.self is Indexable) _indexedElements.add(data.self as Indexable);
diff --git a/lib/src/html/template_data.dart b/lib/src/html/template_data.dart
index 2127c29..0bcef5e 100644
--- a/lib/src/html/template_data.dart
+++ b/lib/src/html/template_data.dart
@@ -8,6 +8,7 @@
abstract class HtmlOptions {
String get relCanonicalPrefix;
String get toolVersion;
+ bool get useBaseHref;
}
abstract class TemplateData<T extends Documentable> {
@@ -38,6 +39,7 @@
T get self;
String get version => htmlOptions.toolVersion;
String get relCanonicalPrefix => htmlOptions.relCanonicalPrefix;
+ bool get useBaseHref => htmlOptions.useBaseHref;
String _layoutTitle(String name, String kind, bool isDeprecated) =>
_renderHelper.composeLayoutTitle(name, kind, isDeprecated);
@@ -67,9 +69,9 @@
bool get hasHomepage => package.hasHomepage;
String get homepage => package.homepage;
- /// `null` for packages because they are at the root – not needed
+ /// empty for packages because they are at the root – not needed
@override
- String get htmlBase => null;
+ String get htmlBase => '';
}
class CategoryTemplateData extends TemplateData<Category> {
@@ -83,7 +85,7 @@
String get title => '${category.name} ${category.kind} - Dart API';
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
@override
String get layoutTitle => _layoutTitle(category.name, category.kind, false);
@@ -109,7 +111,7 @@
@override
String get title => '${library.name} library - Dart API';
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
@override
String get metaDescription =>
'${library.name} library API docs, for the Dart programming language.';
@@ -164,7 +166,7 @@
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
Class get objectType {
if (_objectType != null) {
@@ -207,7 +209,7 @@
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
}
class ConstructorTemplateData extends TemplateData<Constructor> {
@@ -235,7 +237,7 @@
List get navLinksWithGenerics => [clazz];
@override
@override
- String get htmlBase => '../..';
+ String get htmlBase => '../../';
@override
String get title => '${constructor.name} constructor - ${clazz.name} class - '
'${library.name} library - Dart API';
@@ -279,7 +281,7 @@
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
}
class MethodTemplateData extends TemplateData<Method> {
@@ -317,7 +319,7 @@
@override
List get navLinksWithGenerics => [container];
@override
- String get htmlBase => '../..';
+ String get htmlBase => '../../';
}
class PropertyTemplateData extends TemplateData<Field> {
@@ -356,7 +358,7 @@
@override
List get navLinksWithGenerics => [container];
@override
- String get htmlBase => '../..';
+ String get htmlBase => '../../';
String get type => 'property';
}
@@ -400,7 +402,7 @@
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
}
class TopLevelPropertyTemplateData extends TemplateData<TopLevelVariable> {
@@ -431,7 +433,7 @@
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
- String get htmlBase => '..';
+ String get htmlBase => '../';
String get _type => 'property';
}
diff --git a/lib/src/model/package.dart b/lib/src/model/package.dart
index 7771d3e..b712e92 100644
--- a/lib/src/model/package.dart
+++ b/lib/src/model/package.dart
@@ -14,6 +14,17 @@
final RegExp substituteNameVersion = RegExp(r'%([bnv])%');
+// All hrefs are emitted as relative paths from the output root. We are unable
+// to compute them from the page we are generating, and many properties computed
+// using hrefs are memoized anyway. To build complete relative hrefs, we emit
+// the href with this placeholder, and then replace it with the current page's
+// base href afterwards.
+// See https://github.com/dart-lang/dartdoc/issues/2090 for further context.
+// TODO: Find an approach that doesn't require doing this.
+// Unlikely to be mistaken for an identifier, html tag, or something else that
+// might reasonably exist normally.
+final String HTMLBASE_PLACEHOLDER = '\%\%__HTMLBASE_dartdoc_internal__\%\%';
+
/// A [LibraryContainer] that contains [Library] objects related to a particular
/// package.
class Package extends LibraryContainer
@@ -206,7 +217,7 @@
});
if (!_baseHref.endsWith('/')) _baseHref = '${_baseHref}/';
} else {
- _baseHref = '';
+ _baseHref = config.useBaseHref ? '' : HTMLBASE_PLACEHOLDER;
}
}
return _baseHref;
diff --git a/lib/templates/_footer.html b/lib/templates/_footer.html
index c20bd74..bac8322 100644
--- a/lib/templates/_footer.html
+++ b/lib/templates/_footer.html
@@ -11,11 +11,12 @@
<!-- footer-text placeholder -->
</footer>
+{{! TODO(jdkoren): unwrap ^useBaseHref sections when the option is removed.}}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
-<script src="static-assets/typeahead.bundle.min.js"></script>
-<script src="static-assets/highlight.pack.js"></script>
-<script src="static-assets/URI.js"></script>
-<script src="static-assets/script.js"></script>
+<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/typeahead.bundle.min.js"></script>
+<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/highlight.pack.js"></script>
+<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/URI.js"></script>
+<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/script.js"></script>
<!-- footer placeholder -->
</body>
diff --git a/lib/templates/_head.html b/lib/templates/_head.html
index 5fffa11..15580a9 100644
--- a/lib/templates/_head.html
+++ b/lib/templates/_head.html
@@ -12,16 +12,20 @@
{{ #relCanonicalPrefix }}
<link rel="canonical" href="{{{relCanonicalPrefix}}}/{{{self.href}}}">
{{ /relCanonicalPrefix}}
+
+ {{#useBaseHref}}{{! TODO(jdkoren): remove when the useBaseHref option is removed.}}
{{#htmlBase}}
<!-- required because all the links are pseudo-absolute -->
<base href="{{{htmlBase}}}">
{{/htmlBase}}
+ {{/useBaseHref}}
+ {{! TODO(jdkoren): unwrap ^useBaseHref sections when the option is removed.}}
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500,400i,400,300|Source+Sans+Pro:400,300,700" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
- <link rel="stylesheet" href="static-assets/github.css">
- <link rel="stylesheet" href="static-assets/styles.css">
- <link rel="icon" href="static-assets/favicon.png">
+ <link rel="stylesheet" href="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/github.css">
+ <link rel="stylesheet" href="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/styles.css">
+ <link rel="icon" href="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/favicon.png">
<!-- header placeholder -->
</head>
diff --git a/test/model_special_cases_test.dart b/test/model_special_cases_test.dart
index 8abf5af..7866edc 100644
--- a/test/model_special_cases_test.dart
+++ b/test/model_special_cases_test.dart
@@ -356,7 +356,8 @@
hashCode.inheritance.any((c) => c.name == 'Interceptor'), isTrue);
// If EventTarget really does start implementing hashCode, this will
// fail.
- expect(hashCode.href, equals('dart-core/Object/hashCode.html'));
+ expect(hashCode.href,
+ equals('${HTMLBASE_PLACEHOLDER}dart-core/Object/hashCode.html'));
expect(
hashCode.canonicalEnclosingContainer, equals(objectModelElement));
expect(
@@ -387,7 +388,8 @@
test('sdk library have formatted names', () {
expect(dartAsyncLib.name, 'dart:async');
expect(dartAsyncLib.dirName, 'dart-async');
- expect(dartAsyncLib.href, 'dart-async/dart-async-library.html');
+ expect(dartAsyncLib.href,
+ '${HTMLBASE_PLACEHOLDER}dart-async/dart-async-library.html');
});
});
diff --git a/test/model_test.dart b/test/model_test.dart
index edae9ae..c044f03 100644
--- a/test/model_test.dart
+++ b/test/model_test.dart
@@ -251,18 +251,24 @@
test('can invoke a tool and add a reference link', () {
expect(invokeTool.documentation,
contains('Yes it is a [Dog]! Is not a [ToolUser].'));
- expect(invokeTool.documentationAsHtml,
- contains('<a href="ex/ToolUser-class.html">ToolUser</a>'));
- expect(invokeTool.documentationAsHtml,
- contains('<a href="ex/Dog-class.html">Dog</a>'));
+ expect(
+ invokeTool.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/ToolUser-class.html">ToolUser</a>'));
+ expect(
+ invokeTool.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Dog-class.html">Dog</a>'));
});
test(r'can invoke a tool with no $INPUT or args', () {
expect(invokeToolNoInput.documentation, contains('Args: []'));
expect(invokeToolNoInput.documentation,
isNot(contains('This text should not appear in the output')));
expect(invokeToolNoInput.documentation, isNot(contains('[Dog]')));
- expect(invokeToolNoInput.documentationAsHtml,
- isNot(contains('<a href="ex/Dog-class.html">Dog</a>')));
+ expect(
+ invokeToolNoInput.documentationAsHtml,
+ isNot(contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Dog-class.html">Dog</a>')));
});
test('can invoke a tool multiple times in one comment block', () {
RegExp envLine = RegExp(r'^Env: \{', multiLine: true);
@@ -372,14 +378,14 @@
expect(
renderer.renderCategoryLabel(category),
'<span class="category superb cp-0 linked" title="This is part of the Superb Topic.">'
- '<a href="topics/Superb-topic.html">Superb</a></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}topics/Superb-topic.html">Superb</a></span>');
});
test('CategoryRendererHtml renders linkedName', () {
Category category = packageGraph.publicPackages.first.categories.first;
CategoryRendererHtml renderer = CategoryRendererHtml();
expect(renderer.renderLinkedName(category),
- '<a href="topics/Superb-topic.html">Superb</a>');
+ '<a href="${HTMLBASE_PLACEHOLDER}topics/Superb-topic.html">Superb</a>');
});
});
@@ -963,14 +969,14 @@
test('Verify links inside of table headers', () {
expect(
docsAsHtml.contains(
- '<th><a href="fake/Annotation-class.html">Annotation</a></th>'),
+ '<th><a href="${HTMLBASE_PLACEHOLDER}fake/Annotation-class.html">Annotation</a></th>'),
isTrue);
});
test('Verify links inside of table body', () {
expect(
docsAsHtml.contains(
- '<tbody><tr><td><a href="fake/DocumentWithATable/foo-constant.html">foo</a></td>'),
+ '<tbody><tr><td><a href="${HTMLBASE_PLACEHOLDER}fake/DocumentWithATable/foo-constant.html">foo</a></td>'),
isTrue);
});
@@ -995,49 +1001,49 @@
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to library: <a href="mylibpub/mylibpub-library.html">renamedLib</a>'));
+ 'Link to library: <a href="${HTMLBASE_PLACEHOLDER}mylibpub/mylibpub-library.html">renamedLib</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to constructor (implied): <a href="mylibpub/YetAnotherHelper/YetAnotherHelper.html">new renamedLib.YetAnotherHelper()</a>'));
+ 'Link to constructor (implied): <a href="${HTMLBASE_PLACEHOLDER}mylibpub/YetAnotherHelper/YetAnotherHelper.html">new renamedLib.YetAnotherHelper()</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to constructor (implied, no new): <a href="mylibpub/YetAnotherHelper/YetAnotherHelper.html">renamedLib.YetAnotherHelper()</a>'));
+ 'Link to constructor (implied, no new): <a href="${HTMLBASE_PLACEHOLDER}mylibpub/YetAnotherHelper/YetAnotherHelper.html">renamedLib.YetAnotherHelper()</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to class: <a href="mylibpub/YetAnotherHelper-class.html">renamedLib.YetAnotherHelper</a>'));
+ 'Link to class: <a href="${HTMLBASE_PLACEHOLDER}mylibpub/YetAnotherHelper-class.html">renamedLib.YetAnotherHelper</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to constructor (direct): <a href="mylibpub/YetAnotherHelper/YetAnotherHelper.html">renamedLib.YetAnotherHelper.YetAnotherHelper</a>'));
+ 'Link to constructor (direct): <a href="${HTMLBASE_PLACEHOLDER}mylibpub/YetAnotherHelper/YetAnotherHelper.html">renamedLib.YetAnotherHelper.YetAnotherHelper</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to class member: <a href="mylibpub/YetAnotherHelper/getMoreContents.html">renamedLib.YetAnotherHelper.getMoreContents</a>'));
+ 'Link to class member: <a href="${HTMLBASE_PLACEHOLDER}mylibpub/YetAnotherHelper/getMoreContents.html">renamedLib.YetAnotherHelper.getMoreContents</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to function: <a href="mylibpub/helperFunction.html">renamedLib.helperFunction</a>'));
+ 'Link to function: <a href="${HTMLBASE_PLACEHOLDER}mylibpub/helperFunction.html">renamedLib.helperFunction</a>'));
expect(
aFunctionUsingRenamedLib.documentationAsHtml,
contains(
- 'Link to overlapping prefix: <a href="csspub/theOnlyThingInTheLibrary.html">renamedLib2.theOnlyThingInTheLibrary</a>'));
+ 'Link to overlapping prefix: <a href="${HTMLBASE_PLACEHOLDER}csspub/theOnlyThingInTheLibrary.html">renamedLib2.theOnlyThingInTheLibrary</a>'));
});
test('operator [] reference within a class works', () {
expect(
docsAsHtml,
contains(
- '<a href="fake/BaseForDocComments/operator_get.html">operator []</a> '));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/BaseForDocComments/operator_get.html">operator []</a> '));
});
test('operator [] reference outside of a class works', () {
expect(
docsAsHtml,
contains(
- '<a href="fake/SpecialList/operator_get.html">SpecialList.operator []</a> '));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/SpecialList/operator_get.html">SpecialList.operator []</a> '));
}, skip: 'https://github.com/dart-lang/dartdoc/issues/1285');
test('codeifies a class from the SDK', () {
@@ -1052,7 +1058,7 @@
expect(
docsAsHtml,
contains(
- '<a href="fake/BaseForDocComments-class.html">BaseForDocComments</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/BaseForDocComments-class.html">BaseForDocComments</a>'));
});
test(
@@ -1061,7 +1067,7 @@
expect(
docsAsHtml,
contains(
- '<a href="anonymous_library/doesStuff.html">doesStuff</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}anonymous_library/doesStuff.html">doesStuff</a>'));
});
test(
@@ -1069,10 +1075,14 @@
() {
final Class helperClass =
exLibrary.classes.firstWhere((c) => c.name == 'Helper');
- expect(helperClass.documentationAsHtml,
- contains('<a href="ex/Apple-class.html">Apple</a>'));
- expect(helperClass.documentationAsHtml,
- contains('<a href="ex/B-class.html">ex.B</a>'));
+ expect(
+ helperClass.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>'));
+ expect(
+ helperClass.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/B-class.html">ex.B</a>'));
});
test('link to override method in implementer from base class', () {
@@ -1081,7 +1091,7 @@
expect(
helperClass.documentationAsHtml,
contains(
- '<a href="override_class/BoxConstraints/debugAssertIsValid.html">BoxConstraints.debugAssertIsValid</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}override_class/BoxConstraints/debugAssertIsValid.html">BoxConstraints.debugAssertIsValid</a>'));
});
test(
@@ -1090,7 +1100,7 @@
expect(
docsAsHtml,
contains(
- '<a href="two_exports/BaseClass-class.html">BaseClass</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}two_exports/BaseClass-class.html">BaseClass</a>'));
});
test(
@@ -1099,30 +1109,35 @@
expect(
docsAsHtml,
contains(
- '<a href="fake/NAME_WITH_TWO_UNDERSCORES-constant.html">NAME_WITH_TWO_UNDERSCORES</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/NAME_WITH_TWO_UNDERSCORES-constant.html">NAME_WITH_TWO_UNDERSCORES</a>'));
});
test('links to a method in this class', () {
expect(
docsAsHtml,
contains(
- '<a href="fake/BaseForDocComments/anotherMethod.html">anotherMethod</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/BaseForDocComments/anotherMethod.html">anotherMethod</a>'));
});
test('links to a top-level function in this library', () {
expect(
docsAsHtml,
contains(
- '<a class="deprecated" href="fake/topLevelFunction.html">topLevelFunction</a>'));
+ '<a class="deprecated" href="${HTMLBASE_PLACEHOLDER}fake/topLevelFunction.html">topLevelFunction</a>'));
});
test('links to top-level function from an imported library', () {
expect(
- docsAsHtml, contains('<a href="ex/function1.html">function1</a>'));
+ docsAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/function1.html">function1</a>'));
});
test('links to a class from an imported lib', () {
- expect(docsAsHtml, contains('<a href="ex/Apple-class.html">Apple</a>'));
+ expect(
+ docsAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>'));
});
test(
@@ -1131,14 +1146,14 @@
expect(
docsAsHtml,
contains(
- '<a href="fake/incorrectDocReference-constant.html">incorrectDocReference</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/incorrectDocReference-constant.html">incorrectDocReference</a>'));
});
test('links to a top-level const from an imported lib', () {
expect(
docsAsHtml,
contains(
- '<a href="ex/incorrectDocReferenceFromEx-constant.html">incorrectDocReferenceFromEx</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/incorrectDocReferenceFromEx-constant.html">incorrectDocReferenceFromEx</a>'));
});
test('links to a top-level variable with a prefix from an imported lib',
@@ -1146,27 +1161,42 @@
expect(
docsAsHtml,
contains(
- '<a href="csspub/theOnlyThingInTheLibrary.html">css.theOnlyThingInTheLibrary</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}csspub/theOnlyThingInTheLibrary.html">css.theOnlyThingInTheLibrary</a>'));
});
test('links to a name with a single underscore', () {
expect(
docsAsHtml,
contains(
- '<a href="fake/NAME_SINGLEUNDERSCORE-constant.html">NAME_SINGLEUNDERSCORE</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/NAME_SINGLEUNDERSCORE-constant.html">NAME_SINGLEUNDERSCORE</a>'));
});
test('correctly escapes type parameters in links', () {
expect(
docsAsHtml,
contains(
- '<a href="fake/ExtraSpecialList-class.html">ExtraSpecialList<Object></a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ExtraSpecialList-class.html">ExtraSpecialList<Object></a>'));
});
test('correctly escapes type parameters in broken links', () {
expect(docsAsHtml,
contains('<code>ThisIsNotHereNoWay<MyType></code>'));
});
+
+ test('leaves relative href resulting in a broken link', () {
+ // Dartdoc does emit a brokenLink warning for this.
+ expect(docsAsHtml,
+ contains('<a href="SubForDocComments/localMethod.html">link</a>'));
+ });
+
+ test('leaves relative href resulting in a working link', () {
+ // Ideally doc comments should not make assumptions about Dartdoc output
+ // files, but unfortunately some do...
+ expect(
+ docsAsHtml,
+ contains(
+ '<a href="../SubForDocComments/localMethod.html">link</a>'));
+ });
});
test('multi-underscore names in brackets do not become italicized', () {
@@ -1174,7 +1204,7 @@
expect(
short.documentationAsHtml,
contains(
- '<a href="fake/NAME_WITH_TWO_UNDERSCORES-constant.html">NAME_WITH_TWO_UNDERSCORES</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/NAME_WITH_TWO_UNDERSCORES-constant.html">NAME_WITH_TWO_UNDERSCORES</a>'));
});
test('still has brackets inside code blocks', () {
@@ -1227,7 +1257,7 @@
test('single ref to class', () {
expect(
B.documentationAsHtml.contains(
- '<p>Extends class <a href="ex/Apple-class.html">Apple</a>, use <a href="ex/Apple/Apple.html">new Apple</a> or <a href="ex/Apple/Apple.fromString.html">new Apple.fromString</a></p>'),
+ '<p>Extends class <a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>, use <a href="${HTMLBASE_PLACEHOLDER}ex/Apple/Apple.html">new Apple</a> or <a href="${HTMLBASE_PLACEHOLDER}ex/Apple/Apple.fromString.html">new Apple.fromString</a></p>'),
isTrue);
});
@@ -1243,27 +1273,38 @@
expect(extendedClass, isNotNull);
String resolved = extendedClass.documentationAsHtml;
expect(resolved, isNotNull);
- expect(resolved,
- contains('<a href="two_exports/BaseClass-class.html">BaseClass</a>'));
- expect(resolved,
- contains('Linking over to <a href="ex/Apple-class.html">Apple</a>'));
+ expect(
+ resolved,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}two_exports/BaseClass-class.html">BaseClass</a>'));
+ expect(
+ resolved,
+ contains(
+ 'Linking over to <a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>'));
});
test('references to class and constructors', () {
String comment = B.documentationAsHtml;
- expect(comment,
- contains('Extends class <a href="ex/Apple-class.html">Apple</a>'));
- expect(
- comment, contains('use <a href="ex/Apple/Apple.html">new Apple</a>'));
expect(
comment,
contains(
- '<a href="ex/Apple/Apple.fromString.html">new Apple.fromString</a>'));
+ 'Extends class <a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>'));
+ expect(
+ comment,
+ contains(
+ 'use <a href="${HTMLBASE_PLACEHOLDER}ex/Apple/Apple.html">new Apple</a>'));
+ expect(
+ comment,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Apple/Apple.fromString.html">new Apple.fromString</a>'));
});
test('reference to class from another library', () {
String comment = superAwesomeClass.documentationAsHtml;
- expect(comment, contains('<a href="ex/Apple-class.html">Apple</a>'));
+ expect(
+ comment,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/Apple-class.html">Apple</a>'));
});
test('reference to method', () {
@@ -1271,7 +1312,7 @@
expect(
comment,
equals(
- '<p>link to method from class <a href="ex/Apple/m.html">Apple.m</a></p>'));
+ '<p>link to method from class <a href="${HTMLBASE_PLACEHOLDER}ex/Apple/m.html">Apple.m</a></p>'));
});
test(
@@ -1284,11 +1325,11 @@
expect(
notAMethodFromPrivateClass.documentationAsHtml,
contains(
- '<a href="fake/InheritingClassOne/aMethod.html">fake.InheritingClassOne.aMethod</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/InheritingClassOne/aMethod.html">fake.InheritingClassOne.aMethod</a>'));
expect(
notAMethodFromPrivateClass.documentationAsHtml,
contains(
- '<a href="fake/InheritingClassTwo/aMethod.html">fake.InheritingClassTwo.aMethod</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/InheritingClassTwo/aMethod.html">fake.InheritingClassTwo.aMethod</a>'));
});
test('legacy code blocks render correctly', () {
@@ -1451,35 +1492,35 @@
expect(
overrideByModifierClass.oneLineDoc,
contains(
- '<a href=\"fake/ModifierClass-class.html\">ModifierClass</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ModifierClass-class.html">ModifierClass</a>'));
expect(
overrideByModifierClass.canonicalModelElement.documentationAsHtml,
contains(
- '<a href=\"fake/ModifierClass-class.html\">ModifierClass</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ModifierClass-class.html">ModifierClass</a>'));
expect(
overrideByGenericMixin.oneLineDoc,
contains(
- '<a href=\"fake/GenericMixin-mixin.html\">GenericMixin</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/GenericMixin-mixin.html">GenericMixin</a>'));
expect(
overrideByGenericMixin.canonicalModelElement.documentationAsHtml,
contains(
- '<a href=\"fake/GenericMixin-mixin.html\">GenericMixin</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/GenericMixin-mixin.html">GenericMixin</a>'));
expect(
overrideByBoth.oneLineDoc,
contains(
- '<a href=\"fake/ModifierClass-class.html\">ModifierClass</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ModifierClass-class.html">ModifierClass</a>'));
expect(
overrideByBoth.oneLineDoc,
contains(
- '<a href=\"fake/GenericMixin-mixin.html\">GenericMixin</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/GenericMixin-mixin.html">GenericMixin</a>'));
expect(
overrideByBoth.canonicalModelElement.documentationAsHtml,
contains(
- '<a href=\"fake/ModifierClass-class.html\">ModifierClass</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ModifierClass-class.html">ModifierClass</a>'));
expect(
overrideByBoth.canonicalModelElement.documentationAsHtml,
contains(
- '<a href=\"fake/GenericMixin-mixin.html\">GenericMixin</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/GenericMixin-mixin.html">GenericMixin</a>'));
});
});
@@ -1629,11 +1670,12 @@
});
test('exported class should have hrefs from the current library', () {
- expect(Dep.href, equals('ex/Deprecated-class.html'));
expect(
- Dep.instanceMethods[0].href, equals('ex/Deprecated/toString.html'));
- expect(
- Dep.instanceProperties[0].href, equals('ex/Deprecated/expires.html'));
+ Dep.href, equals('${HTMLBASE_PLACEHOLDER}ex/Deprecated-class.html'));
+ expect(Dep.instanceMethods[0].href,
+ equals('${HTMLBASE_PLACEHOLDER}ex/Deprecated/toString.html'));
+ expect(Dep.instanceProperties[0].href,
+ equals('${HTMLBASE_PLACEHOLDER}ex/Deprecated/expires.html'));
});
test('exported class should have linkedReturnType for the current library',
@@ -1641,8 +1683,10 @@
Method returnCool = Cool.instanceMethods
.firstWhere((m) => m.name == 'returnCool', orElse: () => null);
expect(returnCool, isNotNull);
- expect(returnCool.linkedReturnType,
- equals('<a href="fake/Cool-class.html">Cool</a>'));
+ expect(
+ returnCool.linkedReturnType,
+ equals(
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/Cool-class.html">Cool</a>'));
});
test('F has a single instance method', () {
@@ -1885,14 +1929,18 @@
() {
expect(extensionReferencer.documentationAsHtml,
contains('<code>_Shhh</code>'));
- expect(extensionReferencer.documentationAsHtml,
- contains('<a href="ex/FancyList.html">FancyList</a>'));
- expect(extensionReferencer.documentationAsHtml,
- contains('<a href="ex/AnExtension/call.html">AnExtension.call</a>'));
expect(
extensionReferencer.documentationAsHtml,
contains(
- '<a href="reexport_two/DocumentThisExtensionOnce.html">DocumentThisExtensionOnce</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/FancyList.html">FancyList</a>'));
+ expect(
+ extensionReferencer.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnExtension/call.html">AnExtension.call</a>'));
+ expect(
+ extensionReferencer.documentationAsHtml,
+ contains(
+ '<a href="${HTMLBASE_PLACEHOLDER}reexport_two/DocumentThisExtensionOnce.html">DocumentThisExtensionOnce</a>'));
});
test('has a fully qualified name', () {
@@ -1909,7 +1957,7 @@
test('member method has href', () {
s = ext.instanceMethods.firstWhere((m) => m.name == 's');
- expect(s.href, 'ex/AppleExtension/s.html');
+ expect(s.href, '${HTMLBASE_PLACEHOLDER}ex/AppleExtension/s.html');
});
test('has extended type', () {
@@ -2163,7 +2211,7 @@
expect(
params,
'<span class="parameter" id="addCallback-param-callback">'
- '<span class="type-annotation"><a href="fake/VoidCallback.html">VoidCallback</a></span> '
+ '<span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}fake/VoidCallback.html">VoidCallback</a></span> '
'<span class="parameter-name">callback</span></span><wbr>');
function =
@@ -2172,7 +2220,7 @@
expect(
params,
'<span class="parameter" id="addCallback2-param-callback">'
- '<span class="type-annotation"><a href="fake/Callback2.html">Callback2</a></span> '
+ '<span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}fake/Callback2.html">Callback2</a></span> '
'<span class="parameter-name">callback</span></span><wbr>');
});
@@ -2205,21 +2253,21 @@
// TODO(jcollins-g): really, these shouldn't be called "parameters" in
// the span class.
expect(explicitSetter.linkedReturnType,
- '<span class="parameter" id="explicitSetter=-param-f"><span class="type-annotation">dynamic</span> <span class="parameter-name">Function</span>(<span class="parameter" id="param-bar"><span class="type-annotation">int</span>, </span><wbr><span class="parameter" id="param-baz"><span class="type-annotation"><a href="fake/Cool-class.html">Cool</a></span>, </span><wbr><span class="parameter" id="param-macTruck"><span class="type-annotation">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span></span><wbr>)</span><wbr>');
+ '<span class="parameter" id="explicitSetter=-param-f"><span class="type-annotation">dynamic</span> <span class="parameter-name">Function</span>(<span class="parameter" id="param-bar"><span class="type-annotation">int</span>, </span><wbr><span class="parameter" id="param-baz"><span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}fake/Cool-class.html">Cool</a></span>, </span><wbr><span class="parameter" id="param-macTruck"><span class="type-annotation">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span></span><wbr>)</span><wbr>');
});
test('parameterized type from field is correctly displayed', () {
Field aField = TemplatedInterface.instanceProperties
.singleWhere((f) => f.name == 'aField');
expect(aField.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">Stream<span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">Stream<span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span>></span>');
});
test('parameterized type from inherited field is correctly displayed', () {
Field aInheritedField = TemplatedInterface.inheritedProperties
.singleWhere((f) => f.name == 'aInheritedField');
expect(aInheritedField.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
});
test(
@@ -2229,7 +2277,7 @@
.singleWhere((f) => f.name == 'aGetter')
.getter;
expect(aGetter.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">Map<span class="signature"><<wbr><span class="type-parameter">A</span>, <span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">String</span>></span></span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">Map<span class="signature"><<wbr><span class="type-parameter">A</span>, <span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">String</span>></span></span>></span></span>></span>');
});
test(
@@ -2239,7 +2287,7 @@
.singleWhere((f) => f.name == 'aInheritedGetter')
.getter;
expect(aInheritedGetter.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
});
test(
@@ -2249,11 +2297,11 @@
.singleWhere((f) => f.name == 'aInheritedSetter')
.setter;
expect(aInheritedSetter.allParameters.first.modelType.linkedName,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
// TODO(jcollins-g): really, these shouldn't be called "parameters" in
// the span class.
expect(aInheritedSetter.enclosingCombo.linkedReturnType,
- '<span class="parameter" id="aInheritedSetter=-param-thingToSet"><span class="type-annotation"><a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span></span><wbr>');
+ '<span class="parameter" id="aInheritedSetter=-param-thingToSet"><span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span></span><wbr>');
});
test(
@@ -2262,7 +2310,7 @@
Method aMethodInterface = TemplatedInterface.allInstanceMethods
.singleWhere((m) => m.name == 'aMethodInterface');
expect(aMethodInterface.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
});
test(
@@ -2271,7 +2319,7 @@
Method aInheritedMethod = TemplatedInterface.allInstanceMethods
.singleWhere((m) => m.name == 'aInheritedMethod');
expect(aInheritedMethod.linkedReturnType,
- '<a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
});
test(
@@ -2281,7 +2329,7 @@
.allInstanceMethods
.singleWhere((m) => m.name == 'aTypedefReturningMethodInterface');
expect(aTypedefReturningMethodInterface.linkedReturnType,
- '<a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">String</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">String</span>></span></span>></span>');
});
test(
@@ -2291,7 +2339,7 @@
.allInstanceMethods
.singleWhere((m) => m.name == 'aInheritedTypedefReturningMethod');
expect(aInheritedTypedefReturningMethod.linkedReturnType,
- '<a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
});
test('parameterized types for inherited operator is correctly displayed',
@@ -2300,11 +2348,11 @@
.inheritedOperators
.singleWhere((m) => m.name == 'operator +');
expect(aInheritedAdditionOperator.linkedReturnType,
- '<a href="ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span>');
expect(
ParameterRendererHtml()
.renderLinkedParams(aInheritedAdditionOperator.parameters),
- '<span class="parameter" id="+-param-other"><span class="type-annotation"><a href="ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span> <span class="parameter-name">other</span></span><wbr>');
+ '<span class="parameter" id="+-param-other"><span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature"><<wbr><span class="type-parameter">List<span class="signature"><<wbr><span class="type-parameter">int</span>></span></span>></span></span> <span class="parameter-name">other</span></span><wbr>');
});
test('', () {});
@@ -2409,14 +2457,17 @@
test(
'an inherited method from the core SDK has a href relative to the package class',
() {
- expect(inheritedClear.href, equals('ex/CatString/clear.html'));
+ expect(inheritedClear.href,
+ equals('${HTMLBASE_PLACEHOLDER}ex/CatString/clear.html'));
});
test(
'an inherited method has linked to enclosed class name when superclass not in package',
() {
- expect(inheritedClear.linkedName,
- equals('<a href="ex/CatString/clear.html">clear</a>'));
+ expect(
+ inheritedClear.linkedName,
+ equals(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/CatString/clear.html">clear</a>'));
});
test('has enclosing element', () {
@@ -2519,7 +2570,10 @@
});
test('if inherited, has a href relative to enclosed class', () {
- expect(plus.href, equals('ex/SpecializedDuration/operator_plus.html'));
+ expect(
+ plus.href,
+ equals(
+ '${HTMLBASE_PLACEHOLDER}ex/SpecializedDuration/operator_plus.html'));
});
test('if inherited and superclass not in package, link to enclosed class',
@@ -2527,7 +2581,7 @@
expect(
plus.linkedName,
equals(
- '<a href="ex/SpecializedDuration/operator_plus.html">operator +</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/SpecializedDuration/operator_plus.html">operator +</a>'));
});
});
@@ -2764,8 +2818,10 @@
expect(lengthX.oneLineDoc, equals('Returns a length.'));
// TODO(jdkoren): This is left here to have at least one literal matching
// test for extendedDocLink. Move this when extracting renderer tests.
- expect(lengthX.extendedDocLink,
- equals('<a href="fake/WithGetterAndSetter/lengthX.html">[...]</a>'));
+ expect(
+ lengthX.extendedDocLink,
+ equals(
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/WithGetterAndSetter/lengthX.html">[...]</a>'));
expect(lengthX.documentation, contains('the fourth dimension'));
expect(lengthX.documentation, isNot(contains('[...]')));
});
@@ -2776,14 +2832,17 @@
});
test('inherited property has a linked name to superclass in package', () {
- expect(mInB.linkedName, equals('<a href="ex/Apple/m.html">m</a>'));
+ expect(mInB.linkedName,
+ equals('<a href="${HTMLBASE_PLACEHOLDER}ex/Apple/m.html">m</a>'));
});
test(
'inherited property has linked name to enclosed class, if superclass is not in package',
() {
- expect(isEmpty.linkedName,
- equals('<a href="ex/CatString/isEmpty.html">isEmpty</a>'));
+ expect(
+ isEmpty.linkedName,
+ equals(
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/CatString/isEmpty.html">isEmpty</a>'));
});
test('inherited property has the enclosing class', () {
@@ -2917,7 +2976,7 @@
expect(
fieldWithTypedef.linkedReturnType,
equals(
- '<a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">bool</span>></span>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">bool</span>></span>'));
});
});
@@ -2988,7 +3047,7 @@
expect(
complicatedReturn.linkedReturnType,
equals(
- '<a href="fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature"><<wbr><span class="type-parameter">String Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">int</span></span><wbr>)</span></span>></span>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature"><<wbr><span class="type-parameter">String Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">int</span></span><wbr>)</span></span>></span>'));
});
test('@nodoc on simple property works', () {
@@ -3098,7 +3157,7 @@
test('substrings of the constant values type are not linked (#1535)', () {
expect(aName.constantValue,
- 'const <a href="ex/ExtendedShortName/ExtendedShortName.html">ExtendedShortName</a>("hello there")');
+ 'const <a href="${HTMLBASE_PLACEHOLDER}ex/ExtendedShortName/ExtendedShortName.html">ExtendedShortName</a>("hello there")');
});
test('constant field values are escaped', () {
@@ -3142,7 +3201,7 @@
test('MY_CAT is linked', () {
expect(cat.constantValue,
- 'const <a href="ex/ConstantCat/ConstantCat.html">ConstantCat</a>('tabby')');
+ 'const <a href="${HTMLBASE_PLACEHOLDER}ex/ConstantCat/ConstantCat.html">ConstantCat</a>('tabby')');
});
test('exported property', () {
@@ -3186,11 +3245,11 @@
expect(
referToADefaultConstructor.documentationAsHtml,
contains(
- '<a href="fake/ReferToADefaultConstructor-class.html">ReferToADefaultConstructor</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ReferToADefaultConstructor-class.html">ReferToADefaultConstructor</a>'));
expect(
referToADefaultConstructor.documentationAsHtml,
contains(
- '<a href="fake/ReferToADefaultConstructor/ReferToADefaultConstructor.html">ReferToADefaultConstructor.ReferToADefaultConstructor</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ReferToADefaultConstructor/ReferToADefaultConstructor.html">ReferToADefaultConstructor.ReferToADefaultConstructor</a>'));
});
test('displays generic parameters correctly', () {
@@ -3280,7 +3339,7 @@
expect(
ExtendsFutureVoid.linkedName,
equals(
- '<a href="fake/ExtendsFutureVoid-class.html">ExtendsFutureVoid</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ExtendsFutureVoid-class.html">ExtendsFutureVoid</a>'));
DefinedElementType FutureVoid = ExtendsFutureVoid.publicSuperChain
.firstWhere((c) => c.name == 'Future');
expect(
@@ -3293,7 +3352,7 @@
expect(
ImplementsFutureVoid.linkedName,
equals(
- '<a href="fake/ImplementsFutureVoid-class.html">ImplementsFutureVoid</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ImplementsFutureVoid-class.html">ImplementsFutureVoid</a>'));
DefinedElementType FutureVoid = ImplementsFutureVoid.publicInterfaces
.firstWhere((c) => c.name == 'Future');
expect(
@@ -3306,13 +3365,13 @@
expect(
ATypeTakingClassMixedIn.linkedName,
equals(
- '<a href="fake/ATypeTakingClassMixedIn-class.html">ATypeTakingClassMixedIn</a>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ATypeTakingClassMixedIn-class.html">ATypeTakingClassMixedIn</a>'));
DefinedElementType ATypeTakingClassVoid = ATypeTakingClassMixedIn.mixins
.firstWhere((c) => c.name == 'ATypeTakingClass');
expect(
ATypeTakingClassVoid.linkedName,
equals(
- '<a href="fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature"><<wbr><span class="type-parameter">void</span>></span>'));
+ '<a href="${HTMLBASE_PLACEHOLDER}fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature"><<wbr><span class="type-parameter">void</span>></span>'));
});
});
@@ -3355,7 +3414,7 @@
expect(
ParameterRendererHtml().renderLinkedParams(theConstructor.parameters),
equals(
- '<span class="parameter" id="-param-x"><span class="type-annotation"><a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">double</span>></span></span> <span class="parameter-name">x</span></span><wbr>'));
+ '<span class="parameter" id="-param-x"><span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature"><<wbr><span class="type-parameter">double</span>></span></span> <span class="parameter-name">x</span></span><wbr>'));
});
test('anonymous nested functions inside typedefs are handled', () {
@@ -3536,7 +3595,7 @@
expect(
params,
equals(
- '<span class="parameter" id="methodWithTypedefParam-param-p"><span class="type-annotation"><a href="ex/processMessage.html">processMessage</a></span> <span class="parameter-name">p</span></span><wbr>'));
+ '<span class="parameter" id="methodWithTypedefParam-param-p"><span class="type-annotation"><a href="${HTMLBASE_PLACEHOLDER}ex/processMessage.html">processMessage</a></span> <span class="parameter-name">p</span></span><wbr>'));
});
});
@@ -3615,7 +3674,7 @@
expect(
forAnnotation.annotations.first,
equals(
- '@<a href="ex/ForAnnotation-class.html">ForAnnotation</a>('my value')'));
+ '@<a href="${HTMLBASE_PLACEHOLDER}ex/ForAnnotation-class.html">ForAnnotation</a>('my value')'));
});
test('methods has the right annotation', () {
@@ -3628,7 +3687,7 @@
expect(
ctr.annotations[0],
equals(
- '@<a href="ex/Deprecated-class.html">Deprecated</a>("Internal use")'));
+ '@<a href="${HTMLBASE_PLACEHOLDER}ex/Deprecated-class.html">Deprecated</a>("Internal use")'));
});
});
diff --git a/testing/test_package/lib/fake.dart b/testing/test_package/lib/fake.dart
index 94ff87e..97a4795 100644
--- a/testing/test_package/lib/fake.dart
+++ b/testing/test_package/lib/fake.dart
@@ -887,6 +887,10 @@
/// Reference containing a type parameter [ExtraSpecialList<Object>]
///
/// Reference to something that doesn't exist containing a type parameter [ThisIsNotHereNoWay<MyType>]
+ ///
+ /// Link to a nonexistent file (erroneously expects base href): [link](SubForDocComments/localMethod.html)
+ ///
+ /// Link to an existing file: [link](../SubForDocComments/localMethod.html)
String doAwesomeStuff(int value) => null;
void anotherMethod() {}