| Index: utils/dartdoc/dartdoc.dart
|
| diff --git a/utils/dartdoc/dartdoc.dart b/utils/dartdoc/dartdoc.dart
|
| index b6e02de9ed6780d5c8998afb288565decdea6185..56c941465158fd305a5b956d6a8c596e6bde664c 100644
|
| --- a/utils/dartdoc/dartdoc.dart
|
| +++ b/utils/dartdoc/dartdoc.dart
|
| @@ -24,9 +24,11 @@
|
| #import('markdown.dart', prefix: 'md');
|
|
|
| #source('comment_map.dart');
|
| -#source('files.dart');
|
| #source('utils.dart');
|
|
|
| +/** Path to generate HTML files into. */
|
| +final _outdir = 'docs';
|
| +
|
| /**
|
| * Generates completely static HTML containing everything you need to browse
|
| * the docs. The only client side behavior is trivial stuff like syntax
|
| @@ -133,6 +135,12 @@ class Dartdoc {
|
| /** The member that we're currently generating docs for. */
|
| Member _currentMember;
|
|
|
| + /** The path to the file currently being written to, relative to [outdir]. */
|
| + String _filePath;
|
| +
|
| + /** The file currently being written to. */
|
| + StringBuffer _file;
|
| +
|
| int _totalLibraries = 0;
|
| int _totalTypes = 0;
|
| int _totalMembers = 0;
|
| @@ -199,6 +207,29 @@ class Dartdoc {
|
| }
|
| }
|
|
|
| + startFile(String path) {
|
| + _filePath = path;
|
| + _file = new StringBuffer();
|
| + }
|
| +
|
| + endFile() {
|
| + String outPath = '$_outdir/$_filePath';
|
| + world.files.createDirectory(dirname(outPath), recursive: true);
|
| +
|
| + world.files.writeString(outPath, _file.toString());
|
| + _filePath = null;
|
| + _file = null;
|
| + }
|
| +
|
| + write(String s) {
|
| + _file.add(s);
|
| + }
|
| +
|
| + writeln(String s) {
|
| + write(s);
|
| + write('\n');
|
| + }
|
| +
|
| /**
|
| * Writes the page header with the given [title] and [breadcrumbs]. The
|
| * breadcrumbs are an interleaved list of links and titles. If a link is null,
|
| @@ -490,10 +521,16 @@ class Dartdoc {
|
| docConstructors(type);
|
| docMembers(type);
|
|
|
| + writeTypeFooter();
|
| writeFooter();
|
| endFile();
|
| }
|
|
|
| + /** Override this to write additional content at the end of a type's page. */
|
| + void writeTypeFooter() {
|
| + // Do nothing.
|
| + }
|
| +
|
| /**
|
| * Writes an inline type span for the given type. This is a little box with
|
| * an icon and the type's name. It's similar to how types appear in the
|
| @@ -706,6 +743,8 @@ class Dartdoc {
|
| } else if (name == ':negate') {
|
| // Dart uses 'negate' for prefix negate operators, not '!'.
|
| name = 'operator negate';
|
| + } else if (name == ':call') {
|
| + name = 'operator call';
|
| } else {
|
| // See if it's an operator.
|
| name = TokenKind.rawOperatorFromMethod(name);
|
| @@ -805,7 +844,7 @@ class Dartdoc {
|
| docCode(SourceSpan span, String comment, [bool showCode = false]) {
|
| writeln('<div class="doc">');
|
| if (comment != null) {
|
| - writeln(md.markdownToHtml(comment));
|
| + writeln(comment);
|
| }
|
|
|
| if (includeSource && showCode) {
|
| @@ -818,21 +857,79 @@ class Dartdoc {
|
| }
|
|
|
| /** Get the doc comment associated with the given type. */
|
| - String getTypeComment(Type type) => _comments.find(type.span);
|
| + String getTypeComment(Type type) {
|
| + String comment = _comments.find(type.span);
|
| + if (comment == null) return null;
|
| + return md.markdownToHtml(comment);
|
| + }
|
|
|
| /** Get the doc comment associated with the given method. */
|
| - String getMethodComment(MethodMember method) => _comments.find(method.span);
|
| + String getMethodComment(MethodMember method) {
|
| + String comment = _comments.find(method.span);
|
| + if (comment == null) return null;
|
| + return md.markdownToHtml(comment);
|
| + }
|
|
|
| /** Get the doc comment associated with the given field. */
|
| - String getFieldComment(FieldMember field) => _comments.find(field.span);
|
| + String getFieldComment(FieldMember field) {
|
| + String comment = _comments.find(field.span);
|
| + if (comment == null) return null;
|
| + return md.markdownToHtml(comment);
|
| + }
|
| +
|
| + /**
|
| + * Converts [fullPath] which is understood to be a full path from the root of
|
| + * the generated docs to one relative to the current file.
|
| + */
|
| + String relativePath(String fullPath) {
|
| + // Don't make it relative if it's an absolute path.
|
| + if (isAbsolute(fullPath)) return fullPath;
|
| +
|
| + // TODO(rnystrom): Walks all the way up to root each time. Shouldn't do
|
| + // this if the paths overlap.
|
| + return repeat('../', countOccurrences(_filePath, '/')) + fullPath;
|
| + }
|
| +
|
| + /** Gets whether or not the given URL is absolute or relative. */
|
| + bool isAbsolute(String url) {
|
| + // TODO(rnystrom): Why don't we have a nice type in the platform for this?
|
| + // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks
|
| + // a scheme to be relative.
|
| + return const RegExp(@'^\w+:').hasMatch(url);
|
| + }
|
| +
|
| + /** Gets the URL to the documentation for [library]. */
|
| + String libraryUrl(Library library) {
|
| + return '${sanitize(library.name)}.html';
|
| + }
|
| +
|
| + /** Gets the URL for the documentation for [type]. */
|
| + String typeUrl(Type type) {
|
| + // Always get the generic type to strip off any type parameters or
|
| + // arguments. If the type isn't generic, genericType returns `this`, so it
|
| + // works for non-generic types too.
|
| + return '${sanitize(type.library.name)}/${type.genericType.name}.html';
|
| + }
|
| +
|
| + /** Gets the URL for the documentation for [member]. */
|
| + String memberUrl(Member member) {
|
| + return '${typeUrl(member.declaringType)}#${member.name}';
|
| + }
|
| +
|
| + /** Gets the anchor id for the document for [member]. */
|
| + String memberAnchor(Member member) {
|
| + return '${member.name}';
|
| + }
|
|
|
| /**
|
| * Creates a hyperlink. Handles turning the [href] into an appropriate
|
| * relative path from the current file.
|
| */
|
| String a(String href, String contents, [String css]) {
|
| + // Mark outgoing external links, mainly so we can style them.
|
| + final rel = isAbsolute(href) ? ' ref="external"' : '';
|
| final cssClass = css == null ? '' : ' class="$css"';
|
| - return '<a href="${relativePath(href)}"$cssClass>$contents</a>';
|
| + return '<a href="${relativePath(href)}"$cssClass$rel>$contents</a>';
|
| }
|
|
|
| /**
|
|
|