OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Code for displaying the API as HTML. This is used both for generating a | 6 * Code for displaying the API as HTML. This is used both for generating a |
7 * full description of the API as a web page, and for generating doc comments | 7 * full description of the API as a web page, and for generating doc comments |
8 * in generated code. | 8 * in generated code. |
9 */ | 9 */ |
10 library to.html; | 10 library to.html; |
(...skipping 18 matching lines...) Expand all Loading... |
29 margin: 0 auto; | 29 margin: 0 auto; |
30 padding: 0 16px; | 30 padding: 0 16px; |
31 font-size: 16px; | 31 font-size: 16px; |
32 line-height: 1.5; | 32 line-height: 1.5; |
33 color: #111; | 33 color: #111; |
34 background-color: #fdfdfd; | 34 background-color: #fdfdfd; |
35 font-weight: 300; | 35 font-weight: 300; |
36 -webkit-font-smoothing: auto; | 36 -webkit-font-smoothing: auto; |
37 } | 37 } |
38 | 38 |
39 h1 { | |
40 text-align: center; | |
41 } | |
42 | |
43 h2, h3, h4, h5 { | 39 h2, h3, h4, h5 { |
44 margin-bottom: 0; | 40 margin-bottom: 0; |
45 } | 41 } |
46 | 42 |
47 h2.domain { | 43 h2.domain { |
48 border-bottom: 1px solid rgb(200, 200, 200); | 44 border-bottom: 1px solid rgb(200, 200, 200); |
49 margin-bottom: 0.5em; | 45 margin-bottom: 0.5em; |
50 } | 46 } |
51 | 47 |
52 h4 { | 48 h4 { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 104 } |
109 | 105 |
110 a { | 106 a { |
111 text-decoration: none; | 107 text-decoration: none; |
112 } | 108 } |
113 | 109 |
114 a:focus, a:hover { | 110 a:focus, a:hover { |
115 text-decoration: underline; | 111 text-decoration: underline; |
116 } | 112 } |
117 | 113 |
| 114 .deprecated { |
| 115 text-decoration: line-through; |
| 116 } |
| 117 |
118 /* Styles for index */ | 118 /* Styles for index */ |
119 | 119 |
120 .subindex ul { | 120 .subindex ul { |
121 padding-left: 0; | 121 padding-left: 0; |
122 margin-left: 0; | 122 margin-left: 0; |
123 | 123 |
124 -webkit-margin-before: 0; | 124 -webkit-margin-before: 0; |
125 -webkit-margin-start: 0; | 125 -webkit-margin-start: 0; |
126 -webkit-padding-start: 0; | 126 -webkit-padding-start: 0; |
127 | 127 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 | 193 |
194 void h3(void callback()) => element('h3', {}, callback); | 194 void h3(void callback()) => element('h3', {}, callback); |
195 void h4(void callback()) => element('h4', {}, callback); | 195 void h4(void callback()) => element('h4', {}, callback); |
196 void h5(void callback()) => element('h5', {}, callback); | 196 void h5(void callback()) => element('h5', {}, callback); |
197 void hangingIndent(void callback()) => | 197 void hangingIndent(void callback()) => |
198 element('div', {'class': 'hangingIndent'}, callback); | 198 element('div', {'class': 'hangingIndent'}, callback); |
199 void head(void callback()) => element('head', {}, callback); | 199 void head(void callback()) => element('head', {}, callback); |
200 void html(void callback()) => element('html', {}, callback); | 200 void html(void callback()) => element('html', {}, callback); |
201 void i(void callback()) => element('i', {}, callback); | 201 void i(void callback()) => element('i', {}, callback); |
202 void li(void callback()) => element('li', {}, callback); | 202 void li(void callback()) => element('li', {}, callback); |
203 void link(String id, void callback()) { | 203 void link(String id, void callback(), [Map<dynamic, String> attributes]) { |
204 element('a', {'href': '#$id'}, callback); | 204 attributes ??= {}; |
| 205 attributes['href'] = '#$id'; |
| 206 element('a', attributes, callback); |
205 } | 207 } |
206 | 208 |
207 void p(void callback()) => element('p', {}, callback); | 209 void p(void callback()) => element('p', {}, callback); |
208 void pre(void callback()) => element('pre', {}, callback); | 210 void pre(void callback()) => element('pre', {}, callback); |
209 void title(void callback()) => element('title', {}, callback); | 211 void title(void callback()) => element('title', {}, callback); |
210 void tt(void callback()) => element('tt', {}, callback); | 212 void tt(void callback()) => element('tt', {}, callback); |
211 void ul(void callback()) => element('ul', {}, callback); | 213 void ul(void callback()) => element('ul', {}, callback); |
| 214 void span(String cls, void callback()) => |
| 215 element('span', {'class': cls}, callback); |
212 } | 216 } |
213 | 217 |
214 /** | 218 /** |
215 * Visitor that generates HTML documentation of the API. | 219 * Visitor that generates HTML documentation of the API. |
216 */ | 220 */ |
217 class ToHtmlVisitor extends HierarchicalApiVisitor | 221 class ToHtmlVisitor extends HierarchicalApiVisitor |
218 with HtmlMixin, HtmlGenerator { | 222 with HtmlMixin, HtmlGenerator { |
219 /** | 223 /** |
220 * Set of types defined in the API. | 224 * Set of types defined in the API. |
221 */ | 225 */ |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 element( | 337 element( |
334 'li', | 338 'li', |
335 {}, | 339 {}, |
336 () => link('request_${request.longMethod}', | 340 () => link('request_${request.longMethod}', |
337 () => write(request.method))); | 341 () => write(request.method))); |
338 } | 342 } |
339 } | 343 } |
340 }); | 344 }); |
341 } | 345 } |
342 | 346 |
| 347 void generateDomainsHeader() { |
| 348 h1(() { |
| 349 write('Domains'); |
| 350 }); |
| 351 } |
| 352 |
343 void generateTableOfContents() { | 353 void generateTableOfContents() { |
344 ul(() { | 354 for (var domain in api.domains.where((domain) => !domain.experimental)) { |
345 writeln(); | 355 writeln(); |
346 | 356 |
347 for (var domain in api.domains.where((domain) => !domain.experimental)) { | 357 p(() { |
348 write(' '); | 358 link('domain_${domain.name}', () { |
349 li(() { | 359 write(_toTitleCase(domain.name)); |
350 link('domain_${domain.name}', () { | 360 }); |
351 write(_toTitleCase(domain.name)); | 361 }); |
| 362 |
| 363 ul(() { |
| 364 for (Request request in domain.requests) { |
| 365 li(() { |
| 366 link('request_${request.longMethod}', () { |
| 367 write(request.longMethod); |
| 368 }, request.deprecated ? {'class': 'deprecated'} : null); |
352 }); | 369 }); |
353 }); | 370 writeln(); |
354 writeln(); | 371 } |
355 } | 372 }); |
356 }); | 373 |
| 374 writeln(); |
| 375 } |
357 } | 376 } |
358 | 377 |
359 void generateTypesIndex(Set<String> types) { | 378 void generateTypesIndex(Set<String> types) { |
360 h3(() { | 379 h3(() { |
361 write("Types"); | 380 write("Types"); |
362 write(' ('); | 381 write(' ('); |
363 link('types', () => write('\u2191')); | 382 link('types', () => write('\u2191')); |
364 write(')'); | 383 write(')'); |
365 }); | 384 }); |
366 element('div', {'class': 'subindex'}, () { | 385 element('div', {'class': 'subindex'}, () { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 * elements that define the API appropriately. | 435 * elements that define the API appropriately. |
417 */ | 436 */ |
418 void translateHtml(dom.Element html, {bool squashParagraphs: false}) { | 437 void translateHtml(dom.Element html, {bool squashParagraphs: false}) { |
419 for (dom.Node node in html.nodes) { | 438 for (dom.Node node in html.nodes) { |
420 if (node is dom.Element) { | 439 if (node is dom.Element) { |
421 if (squashParagraphs && node.localName == 'p') { | 440 if (squashParagraphs && node.localName == 'p') { |
422 translateHtml(node, squashParagraphs: squashParagraphs); | 441 translateHtml(node, squashParagraphs: squashParagraphs); |
423 continue; | 442 continue; |
424 } | 443 } |
425 switch (node.localName) { | 444 switch (node.localName) { |
| 445 case 'domains': |
| 446 generateDomainsHeader(); |
| 447 break; |
426 case 'domain': | 448 case 'domain': |
427 visitDomain(apiMappings.domains[node]); | 449 visitDomain(apiMappings.domains[node]); |
428 break; | 450 break; |
429 case 'head': | 451 case 'head': |
430 head(() { | 452 head(() { |
431 translateHtml(node, squashParagraphs: squashParagraphs); | 453 translateHtml(node, squashParagraphs: squashParagraphs); |
432 element('link', { | 454 element('link', { |
433 'rel': 'stylesheet', | 455 'rel': 'stylesheet', |
434 'href': | 456 'href': |
435 'https://fonts.googleapis.com/css?family=Source+Code+Pro|Rob
oto:500,400italic,300,400', | 457 'https://fonts.googleapis.com/css?family=Source+Code+Pro|Rob
oto:500,400italic,300,400', |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 }); | 530 }); |
509 } | 531 } |
510 } | 532 } |
511 | 533 |
512 @override | 534 @override |
513 void visitNotification(Notification notification) { | 535 void visitNotification(Notification notification) { |
514 dt('notification', () { | 536 dt('notification', () { |
515 anchor('notification_${notification.longEvent}', () { | 537 anchor('notification_${notification.longEvent}', () { |
516 write(notification.longEvent); | 538 write(notification.longEvent); |
517 }); | 539 }); |
518 write(' ('); | |
519 link('notification_${notification.longEvent}', () { | |
520 write('#'); | |
521 }); | |
522 write(')'); | |
523 }); | 540 }); |
524 dd(() { | 541 dd(() { |
525 box(() { | 542 box(() { |
526 showType( | 543 showType( |
527 'notification', notification.notificationType, notification.params); | 544 'notification', notification.notificationType, notification.params); |
528 }); | 545 }); |
529 translateHtml(notification.html); | 546 translateHtml(notification.html); |
530 describePayload(notification.params, 'parameters:'); | 547 describePayload(notification.params, 'parameters:'); |
531 }); | 548 }); |
532 } | 549 } |
(...skipping 16 matching lines...) Expand all Loading... |
549 dl(() { | 566 dl(() { |
550 super.visitRefactorings(refactorings); | 567 super.visitRefactorings(refactorings); |
551 }); | 568 }); |
552 } | 569 } |
553 | 570 |
554 @override | 571 @override |
555 void visitRequest(Request request) { | 572 void visitRequest(Request request) { |
556 if (request.experimental) { | 573 if (request.experimental) { |
557 return; | 574 return; |
558 } | 575 } |
559 dt('request', () { | 576 dt(request.deprecated ? 'request deprecated' : 'request', () { |
560 anchor('request_${request.longMethod}', () { | 577 anchor('request_${request.longMethod}', () { |
561 write(request.longMethod); | 578 write(request.longMethod); |
562 }); | 579 }); |
563 write(' ('); | |
564 link('request_${request.longMethod}', () { | |
565 write('#'); | |
566 }); | |
567 write(')'); | |
568 }); | 580 }); |
569 dd(() { | 581 dd(() { |
570 box(() { | 582 box(() { |
571 showType('request', request.requestType, request.params); | 583 showType('request', request.requestType, request.params); |
572 br(); | 584 br(); |
573 showType('response', request.responseType, request.result); | 585 showType('response', request.responseType, request.result); |
574 }); | 586 }); |
575 translateHtml(request.html); | 587 translateHtml(request.html); |
576 describePayload(request.params, 'parameters:'); | 588 describePayload(request.params, 'parameters:'); |
577 describePayload(request.result, 'returns:'); | 589 describePayload(request.result, 'returns:'); |
578 }); | 590 }); |
579 } | 591 } |
580 | 592 |
581 @override | 593 @override |
582 void visitTypeDefinition(TypeDefinition typeDefinition) { | 594 void visitTypeDefinition(TypeDefinition typeDefinition) { |
583 if (typeDefinition.experimental) { | 595 if (typeDefinition.experimental) { |
584 return; | 596 return; |
585 } | 597 } |
586 dt('typeDefinition', () { | 598 dt( |
| 599 typeDefinition.deprecated |
| 600 ? 'typeDefinition deprecated' |
| 601 : 'typeDefinition', () { |
587 anchor('type_${typeDefinition.name}', () { | 602 anchor('type_${typeDefinition.name}', () { |
588 write('${typeDefinition.name}: '); | 603 write('${typeDefinition.name}: '); |
589 TypeVisitor typeVisitor = new TypeVisitor(api, short: true); | 604 TypeVisitor typeVisitor = new TypeVisitor(api, short: true); |
590 addAll(typeVisitor.collectHtml(() { | 605 addAll(typeVisitor.collectHtml(() { |
591 typeVisitor.visitTypeDecl(typeDefinition.type); | 606 typeVisitor.visitTypeDecl(typeDefinition.type); |
592 })); | 607 })); |
593 }); | 608 }); |
594 }); | 609 }); |
595 dd(() { | 610 dd(() { |
596 translateHtml(typeDefinition.html); | 611 translateHtml(typeDefinition.html); |
(...skipping 11 matching lines...) Expand all Loading... |
608 @override | 623 @override |
609 void visitTypeEnumValue(TypeEnumValue typeEnumValue) { | 624 void visitTypeEnumValue(TypeEnumValue typeEnumValue) { |
610 bool isDocumented = false; | 625 bool isDocumented = false; |
611 for (dom.Node node in typeEnumValue.html.nodes) { | 626 for (dom.Node node in typeEnumValue.html.nodes) { |
612 if ((node is dom.Element && node.localName != 'code') || | 627 if ((node is dom.Element && node.localName != 'code') || |
613 (node is dom.Text && node.text.trim().isNotEmpty)) { | 628 (node is dom.Text && node.text.trim().isNotEmpty)) { |
614 isDocumented = true; | 629 isDocumented = true; |
615 break; | 630 break; |
616 } | 631 } |
617 } | 632 } |
618 dt('value', () { | 633 dt(typeEnumValue.deprecated ? 'value deprecated' : 'value', () { |
619 write(typeEnumValue.value); | 634 write(typeEnumValue.value); |
620 }); | 635 }); |
621 if (isDocumented) { | 636 if (isDocumented) { |
622 dd(() { | 637 dd(() { |
623 translateHtml(typeEnumValue.html); | 638 translateHtml(typeEnumValue.html); |
624 }); | 639 }); |
625 } | 640 } |
626 } | 641 } |
627 | 642 |
628 @override | 643 @override |
(...skipping 10 matching lines...) Expand all Loading... |
639 void visitTypeObject(TypeObject typeObject) { | 654 void visitTypeObject(TypeObject typeObject) { |
640 dl(() { | 655 dl(() { |
641 super.visitTypeObject(typeObject); | 656 super.visitTypeObject(typeObject); |
642 }); | 657 }); |
643 } | 658 } |
644 | 659 |
645 @override | 660 @override |
646 void visitTypeObjectField(TypeObjectField typeObjectField) { | 661 void visitTypeObjectField(TypeObjectField typeObjectField) { |
647 dt('field', () { | 662 dt('field', () { |
648 b(() { | 663 b(() { |
649 write(typeObjectField.name); | 664 if (typeObjectField.deprecated) { |
| 665 span('deprecated', () { |
| 666 write(typeObjectField.name); |
| 667 }); |
| 668 } else { |
| 669 write(typeObjectField.name); |
| 670 } |
650 if (typeObjectField.value != null) { | 671 if (typeObjectField.value != null) { |
651 write(' = ${JSON.encode(typeObjectField.value)}'); | 672 write(' = ${JSON.encode(typeObjectField.value)}'); |
652 } else { | 673 } else { |
653 write(' ('); | 674 write(': '); |
654 if (typeObjectField.optional) { | |
655 gray(() { | |
656 write('optional'); | |
657 }); | |
658 write(' '); | |
659 } | |
660 TypeVisitor typeVisitor = new TypeVisitor(api, short: true); | 675 TypeVisitor typeVisitor = new TypeVisitor(api, short: true); |
661 addAll(typeVisitor.collectHtml(() { | 676 addAll(typeVisitor.collectHtml(() { |
662 typeVisitor.visitTypeDecl(typeObjectField.type); | 677 typeVisitor.visitTypeDecl(typeObjectField.type); |
663 })); | 678 })); |
664 write(')'); | 679 if (typeObjectField.optional) { |
| 680 gray(() => write(' (optional)')); |
| 681 } |
665 } | 682 } |
666 }); | 683 }); |
667 }); | 684 }); |
668 dd(() { | 685 dd(() { |
669 translateHtml(typeObjectField.html); | 686 translateHtml(typeObjectField.html); |
670 }); | 687 }); |
671 } | 688 } |
672 | 689 |
673 @override | 690 @override |
674 void visitTypeReference(TypeReference typeReference) {} | 691 void visitTypeReference(TypeReference typeReference) {} |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 bool verticalBarNeeded = false; | 809 bool verticalBarNeeded = false; |
793 for (TypeDecl choice in typeUnion.choices) { | 810 for (TypeDecl choice in typeUnion.choices) { |
794 if (verticalBarNeeded) { | 811 if (verticalBarNeeded) { |
795 write(' | '); | 812 write(' | '); |
796 } | 813 } |
797 visitTypeDecl(choice); | 814 visitTypeDecl(choice); |
798 verticalBarNeeded = true; | 815 verticalBarNeeded = true; |
799 } | 816 } |
800 } | 817 } |
801 } | 818 } |
OLD | NEW |