├── .gitignore ├── README.md ├── pubspec.yaml ├── example ├── legacy │ ├── websocket.css │ ├── sunflower.css │ ├── websocket.html_snippet │ ├── hello_world.dart │ ├── sunflower.html_snippet │ ├── fibonacci.dart │ ├── websocket.dart │ └── sunflower.dart └── dart_2_1 │ ├── int_to_double.dart │ └── new_mixin_syntax.dart ├── .travis.yml ├── test ├── legacy │ ├── hello_world_test.dart │ └── fibonacci_test.dart └── dart_2_1 │ ├── int_to_double_test.dart │ └── new_mixin_syntax_test.dart ├── LICENSE ├── CONTRIBUTING.md ├── analysis_options.yaml └── tool └── builder.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | pubspec.lock 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/dart-lang/dartpad_examples.svg?branch=master)](https://travis-ci.org/dart-lang/dartpad_examples) 2 | 3 | Nothing to see here...yet... 4 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dartpad_examples 2 | 3 | environment: 4 | sdk: '>=2.1.0 <3.0.0' 5 | 6 | dev_dependencies: 7 | build: ^1.0.0 8 | build_runner: ^1.0.0 9 | build_web_compilers: '>=1.0.0 <3.0.0' 10 | path: ^1.0.0 11 | pedantic: ^1.0.0 12 | test: ^1.2.0 13 | -------------------------------------------------------------------------------- /example/legacy/websocket.css: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 the Dart project authors. All rights reserved. */ 2 | /* Use of this source code is governed by a BSD-style license */ 3 | /* that can be found in the LICENSE file. */ 4 | 5 | input { 6 | width: 250px; 7 | margin-left: 2em; 8 | } 9 | -------------------------------------------------------------------------------- /example/legacy/sunflower.css: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 the Dart project authors. All rights reserved. */ 2 | /* Use of this source code is governed by a BSD-style license */ 3 | /* that can be found in the LICENSE file. */ 4 | 5 | h2 { 6 | margin-bottom: 0; 7 | text-align: center; 8 | } 9 | 10 | div { 11 | text-align: center; 12 | } 13 | -------------------------------------------------------------------------------- /example/legacy/websocket.html_snippet: -------------------------------------------------------------------------------- 1 | 4 | 5 |

A WebSocket test using echo.websocket.org

6 | 7 |
8 | 9 |

Enter text to echo:

10 | 11 | 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: dart 2 | 3 | dart: 4 | - 2.1.0 5 | - dev 6 | 7 | dart_task: 8 | - test: -p vm,chrome 9 | - dartfmt 10 | - dartanalyzer: --fatal-infos --fatal-warnings . 11 | 12 | # Only building master means that we don't run two builds for each pull request. 13 | branches: 14 | only: [master] 15 | 16 | cache: 17 | directories: 18 | - $HOME/.pub-cache 19 | -------------------------------------------------------------------------------- /example/legacy/hello_world.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2015 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | //# Captured on 2018-10-09 6 | //# https://dartpad.dartlang.org/33706e19df021e52d98c 7 | 8 | void main() { 9 | for (var i = 0; i < 4; i++) { 10 | print('hello $i'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/legacy/hello_world_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | import 'package:test/test.dart'; 6 | 7 | import '../../example/legacy/hello_world.dart' as example; 8 | 9 | void main() { 10 | test('output', () { 11 | expect(example.main, prints(r''' 12 | hello 0 13 | hello 1 14 | hello 2 15 | hello 3 16 | ''')); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /example/legacy/sunflower.html_snippet: -------------------------------------------------------------------------------- 1 | 4 | 5 |

Dr. Fibonacci's Sunflower Spectacular

6 | 7 |
8 | 9 |
10 | 11 |
12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /example/legacy/fibonacci.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2015 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | //# Captured on 2018-10-09 6 | //# https://dartpad.dartlang.org/74e990d984faad26dea0 7 | 8 | void main() { 9 | var i = 20; 10 | print('fibonacci($i) = ${fibonacci(i)}'); 11 | } 12 | 13 | /// Computes the nth Fibonacci number. 14 | int fibonacci(int n) { 15 | return n < 2 ? n : (fibonacci(n - 1) + fibonacci(n - 2)); 16 | } 17 | -------------------------------------------------------------------------------- /test/legacy/fibonacci_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | import 'package:test/test.dart'; 6 | 7 | import '../../example/legacy/fibonacci.dart' as example; 8 | 9 | void main() { 10 | test('output', () { 11 | expect(example.main, prints(r''' 12 | fibonacci(20) = 6765 13 | ''')); 14 | }); 15 | 16 | test('function', () { 17 | expect(example.fibonacci(10), 55); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /test/dart_2_1/int_to_double_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | import 'dart:math' as math; 6 | 7 | import 'package:test/test.dart'; 8 | 9 | import '../../example/dart_2_1/int_to_double.dart' as example; 10 | 11 | void main() { 12 | test('output', () { 13 | expect(example.main, prints(r''' 14 | 12.566370614359172 15 | 12.566370614359172 16 | ''')); 17 | }); 18 | 19 | test('api', () { 20 | var size = example.Circle(1); 21 | expect(size.radius, const TypeMatcher()); 22 | expect(size.area, math.pi); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /example/dart_2_1/int_to_double.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file 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. 4 | 5 | import 'dart:math' as math; 6 | 7 | class Circle { 8 | double radius; 9 | 10 | Circle(this.radius); 11 | 12 | double get area => math.pi * math.pow(radius, 2); 13 | } 14 | 15 | void main() { 16 | // Before Dart 2.1, you had to provide a trailing `.0` – `42.0` – when 17 | // assigning to fields or parameters of type `double`. 18 | // A value like `42` was not allowed. 19 | 20 | print(Circle(2.0).area); // Before Dart 2.1, the trailing `.0` is required. 21 | 22 | // With Dart 2.1, you can provide whole-number values when assigning to 23 | // a double without the trailing `.0`. 24 | print(Circle(2).area); // Legal with Dart 2.1 25 | } 26 | -------------------------------------------------------------------------------- /example/legacy/websocket.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2012 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | //# Captured on 2018-10-17 6 | //# https://dartpad.dartlang.org/479ecba5a56fd706b648 7 | 8 | import 'dart:html'; 9 | 10 | void main() { 11 | var wsTest = WebSocketTest('wss://echo.websocket.org'); 12 | 13 | InputElement input = querySelector('input'); 14 | input.onChange.listen((_) { 15 | wsTest.send(input.value); 16 | input.value = ''; 17 | }); 18 | } 19 | 20 | class WebSocketTest { 21 | final WebSocket _socket; 22 | final _timer = Stopwatch()..start(); 23 | 24 | WebSocketTest(String url) : _socket = WebSocket(url) { 25 | print('Connecting to $url...'); 26 | _startListening(); 27 | } 28 | 29 | void send(String value) { 30 | print('==> $value'); 31 | _socket.send(value); 32 | _timer.reset(); 33 | } 34 | 35 | void _startListening() { 36 | _socket.onOpen.listen((e) { 37 | print('Connected!'); 38 | send('Hello from Dart!'); 39 | }); 40 | 41 | _socket.onClose.listen((_) => print('Websocket closed.')); 42 | _socket.onError.listen((_) => print('Error opening connection.')); 43 | 44 | _socket.onMessage.listen((e) { 45 | print('<== ${e.data} [${_timer.elapsedMilliseconds}ms]'); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/dart_2_1/new_mixin_syntax_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | import 'package:test/test.dart'; 6 | 7 | import '../../example/dart_2_1/new_mixin_syntax.dart' as example; 8 | 9 | void main() { 10 | test('output', () { 11 | expect(example.main, prints(r''' 12 | * 13 | * Simple usage of `mixin` 14 | * 15 | 16 | [ Answer ] 17 | - Use `with` to include a mixin 18 | answer: 42 19 | 20 | * 21 | * More advanced usage of `mixin` 22 | * 23 | 24 | [ LogAnswer ] 25 | - Include many mixins by separating with commas. `LoggingAnswerMixin` prints every time `answer` is accessed. 26 | LOG: `answer` property was accessed 27 | answer: 42 28 | 29 | * 30 | * The order in which mixins are included matters. 31 | * 32 | 33 | [ LogVerifyAnswer ] 34 | - In this case, log then verify. 35 | LOG: `answer` property was accessed 36 | VERIFY: Invalid Result! 37 | answer: 42 38 | 39 | [ VerifyLogAnswer ] 40 | - In this case, verify then log. 41 | VERIFY: Invalid Result! 42 | LOG: `answer` property was accessed 43 | answer: 42 44 | 45 | * 46 | * You can extend classes that include mixins, too. 47 | * 48 | 49 | [ DeltaLogVerifyAnswer ] 50 | - Verify will fail. 51 | LOG: `answer` property was accessed 52 | VERIFY: Invalid Result! 53 | answer: 42 54 | 55 | [ DeltaLogVerifyAnswer ] 56 | - Verify will succeed. 57 | LOG: `answer` property was accessed 58 | VERIFY: valid result 59 | answer: 43 60 | 61 | ''')); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018, the Dart project authors. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | * Neither the name of Google Inc. nor the names of its 13 | contributors may be used to endorse or promote products derived 14 | from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! First, read this page (including the small print at 2 | the end). 3 | 4 | ### Before you contribute 5 | Before we can use your code, you must sign the 6 | [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) 7 | (CLA), which you can do online. The CLA is necessary mainly because you own the 8 | copyright to your changes, even after your contribution becomes part of our 9 | codebase, so we need your permission to use and distribute your code. We also 10 | need to be sure of various other things—for instance that you'll tell us if you 11 | know that your code infringes on other people's patents. You don't have to sign 12 | the CLA until after you've submitted your code for review and a member has 13 | approved it, but you must do it before we can put your code into our codebase. 14 | 15 | Before you start working on a larger contribution, you should get in touch with 16 | us first through the issue tracker with your idea so that we can help out and 17 | possibly guide you. Coordinating up front makes it much easier to avoid 18 | frustration later on. 19 | 20 | ### Code reviews 21 | All submissions, including submissions by project members, require review. 22 | 23 | ### File headers 24 | All files in the project must start with the following header. 25 | 26 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file 27 | // for details. All rights reserved. Use of this source code is governed by a 28 | // BSD-style license that can be found in the LICENSE file. 29 | 30 | ### The small print 31 | Contributions made by corporations are covered by a different agreement than the 32 | one above, the 33 | [Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). 34 | -------------------------------------------------------------------------------- /example/legacy/sunflower.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2011 the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license 3 | // that can be found in the LICENSE file. 4 | 5 | //# Captured on 2018-10-17 6 | //# https://dartpad.dartlang.org/49bde0c1ed780decc902f3d4d06d8f0c 7 | 8 | import 'dart:html'; 9 | import 'dart:math' as math; 10 | 11 | void main() { 12 | Sunflower(); 13 | } 14 | 15 | class Sunflower { 16 | static const orange = 'orange'; 17 | static const seedRadius = 2; 18 | static const scaleFactor = 4; 19 | static const tau = math.pi * 2; 20 | static const maxD = 300; 21 | 22 | static final phi = (math.sqrt(5) + 1) / 2; 23 | static final center = maxD / 2; 24 | 25 | final context = (querySelector('#canvas') as CanvasElement).context2D; 26 | 27 | int seeds; 28 | 29 | Sunflower() { 30 | InputElement slider = querySelector('#slider'); 31 | 32 | void update() { 33 | seeds = int.parse(slider.value); 34 | drawFrame(); 35 | } 36 | 37 | slider.onChange.listen((_) => update()); 38 | 39 | update(); 40 | } 41 | 42 | // Draw the complete figure for the current number of seeds. 43 | void drawFrame() { 44 | print('seed value = $seeds'); 45 | 46 | context.clearRect(0, 0, maxD, maxD); 47 | 48 | for (var i = 0; i < seeds; i++) { 49 | var theta = i * tau / phi; 50 | var r = math.sqrt(i) * scaleFactor; 51 | var x = center + r * math.cos(theta); 52 | var y = center - r * math.sin(theta); 53 | drawSeed(x, y); 54 | } 55 | } 56 | 57 | // Draw a small circle representing a seed centered at (x,y). 58 | void drawSeed(num x, num y) { 59 | context 60 | ..beginPath() 61 | ..lineWidth = 2 62 | ..fillStyle = orange 63 | ..strokeStyle = orange 64 | ..arc(x, y, seedRadius, 0, tau, false) 65 | ..fill() 66 | ..closePath() 67 | ..stroke(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:pedantic/analysis_options.yaml 2 | linter: 3 | rules: 4 | - annotate_overrides 5 | - avoid_empty_else 6 | - avoid_function_literals_in_foreach_calls 7 | - avoid_init_to_null 8 | - avoid_null_checks_in_equality_operators 9 | - avoid_relative_lib_imports 10 | - avoid_return_types_on_setters 11 | - avoid_returning_null 12 | - avoid_types_as_parameter_names 13 | - avoid_unused_constructor_parameters 14 | - await_only_futures 15 | - camel_case_types 16 | - cancel_subscriptions 17 | - cascade_invocations 18 | - comment_references 19 | - constant_identifier_names 20 | - control_flow_in_finally 21 | - directives_ordering 22 | - empty_catches 23 | - empty_constructor_bodies 24 | - empty_statements 25 | - hash_and_equals 26 | - implementation_imports 27 | - invariant_booleans 28 | - iterable_contains_unrelated_type 29 | - library_names 30 | - library_prefixes 31 | - list_remove_unrelated_type 32 | - no_adjacent_strings_in_list 33 | - no_duplicate_case_values 34 | - non_constant_identifier_names 35 | - omit_local_variable_types 36 | - only_throw_errors 37 | - overridden_fields 38 | - package_api_docs 39 | - package_names 40 | - package_prefixed_library_names 41 | - prefer_adjacent_string_concatenation 42 | - prefer_collection_literals 43 | - prefer_conditional_assignment 44 | - prefer_const_constructors 45 | - prefer_contains 46 | - prefer_equal_for_default_values 47 | - prefer_final_fields 48 | - prefer_initializing_formals 49 | - prefer_interpolation_to_compose_strings 50 | - prefer_is_empty 51 | - prefer_is_not_empty 52 | - prefer_single_quotes 53 | - prefer_typing_uninitialized_variables 54 | - recursive_getters 55 | - slash_for_doc_comments 56 | - test_types_in_equals 57 | - throw_in_finally 58 | - type_init_formals 59 | - unawaited_futures 60 | - unnecessary_brace_in_string_interps 61 | - unnecessary_const 62 | - unnecessary_getters_setters 63 | - unnecessary_lambdas 64 | - unnecessary_new 65 | - unnecessary_null_aware_assignments 66 | - unnecessary_statements 67 | - unnecessary_this 68 | - unrelated_type_equality_checks 69 | - use_rethrow_when_possible 70 | - valid_regexps 71 | -------------------------------------------------------------------------------- /example/dart_2_1/new_mixin_syntax.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file 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. 4 | 5 | mixin AnswerMixin { 6 | int get answer => 42; 7 | 8 | @override 9 | String toString() => '[ $runtimeType ]'; 10 | } 11 | 12 | class Answer with AnswerMixin {} 13 | 14 | void main() { 15 | print(''' 16 | * 17 | * Simple usage of `mixin` 18 | * 19 | '''); 20 | printAnswer(Answer(), 'Use `with` to include a mixin'); 21 | 22 | print(''' 23 | * 24 | * More advanced usage of `mixin` 25 | * 26 | '''); 27 | printAnswer( 28 | LogAnswer(), 29 | 'Include many mixins by separating with commas. ' 30 | '`$LoggingAnswerMixin` prints every time `answer` is accessed.'); 31 | 32 | print(''' 33 | * 34 | * The order in which mixins are included matters. 35 | * 36 | '''); 37 | 38 | printAnswer(LogVerifyAnswer(), 'In this case, log then verify.'); 39 | printAnswer(VerifyLogAnswer(), 'In this case, verify then log.'); 40 | 41 | print(''' 42 | * 43 | * You can extend classes that include mixins, too. 44 | * 45 | '''); 46 | 47 | printAnswer(DeltaLogVerifyAnswer(), 'Verify will fail.'); 48 | printAnswer(DeltaLogVerifyAnswer(1), 'Verify will succeed.'); 49 | } 50 | 51 | void printAnswer(AnswerMixin obj, String description) { 52 | print(obj); 53 | print('- $description'); 54 | print('answer: ${obj.answer}'); 55 | print(''); 56 | } 57 | 58 | /// [LoggingAnswerMixin] can only be used as a mixin when the superclass 59 | /// (or one of the mixins that comes before it in a "with" clause) implements 60 | /// [AnswerMixin]. 61 | mixin LoggingAnswerMixin on AnswerMixin { 62 | @override 63 | int get answer { 64 | var value = super.answer; 65 | print(' LOG: `answer` property was accessed'); 66 | return value; 67 | } 68 | } 69 | 70 | class LogAnswer with AnswerMixin, LoggingAnswerMixin {} 71 | 72 | mixin VerifyingAnswerMixin on AnswerMixin { 73 | @override 74 | int get answer { 75 | var value = super.answer; 76 | if (value == 42) { 77 | print(' VERIFY: Invalid Result!'); 78 | } else { 79 | print(' VERIFY: valid result'); 80 | } 81 | return value; 82 | } 83 | } 84 | 85 | class LogVerifyAnswer 86 | with AnswerMixin, LoggingAnswerMixin, VerifyingAnswerMixin {} 87 | 88 | class VerifyLogAnswer 89 | with AnswerMixin, VerifyingAnswerMixin, LoggingAnswerMixin {} 90 | 91 | abstract class DeltaAnswer with AnswerMixin { 92 | final int delta; 93 | 94 | DeltaAnswer(this.delta); 95 | 96 | @override 97 | int get answer => super.answer + delta; 98 | } 99 | 100 | class DeltaLogVerifyAnswer extends DeltaAnswer 101 | with LoggingAnswerMixin, VerifyingAnswerMixin { 102 | DeltaLogVerifyAnswer([int delta = 0]) : super(delta); 103 | } 104 | -------------------------------------------------------------------------------- /tool/builder.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file 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. 4 | 5 | import 'dart:async'; 6 | import 'dart:convert' show HtmlEscape, HtmlEscapeMode; 7 | 8 | import 'package:build/build.dart'; 9 | import 'package:glob/glob.dart'; 10 | import 'package:path/path.dart' as p; 11 | 12 | Builder exampleWebBuilder(BuilderOptions options) => _ExampleWebBuilder(); 13 | 14 | Builder exampleRootBuilder(BuilderOptions options) => _WebRootBuilder(); 15 | 16 | class _ExampleWebBuilder implements Builder { 17 | @override 18 | Future build(BuildStep buildStep) async { 19 | var source = await buildStep.readAsString(buildStep.inputId); 20 | 21 | var htmlAsset = buildStep.inputId.changeExtension('.html_snippet'); 22 | String snippetContent; 23 | if (await buildStep.canRead(htmlAsset)) { 24 | snippetContent = await buildStep.readAsString(htmlAsset); 25 | } 26 | 27 | await buildStep.writeAsString( 28 | buildStep.inputId.changeExtension('.html'), 29 | _template( 30 | p.basenameWithoutExtension(buildStep.inputId.path), 31 | await buildStep.canRead(buildStep.inputId.changeExtension('.css')), 32 | const HtmlEscape(HtmlEscapeMode.element).convert(source), 33 | snippetContent ?? 'Open console...')); 34 | } 35 | 36 | @override 37 | final buildExtensions = const { 38 | '.dart': ['.html'] 39 | }; 40 | 41 | String _template( 42 | String name, bool hasCss, String source, String snippetContent) => 43 | ''' 44 | 45 | 46 | 47 | 48 | 49 | ${name.replaceAll('_', ' ')} 50 | ${hasCss ? '' : ''} 51 | 52 | 53 | 54 | $snippetContent 55 | 56 |

Source

57 |
58 | $source
59 | 
60 | 61 | 62 | '''; 63 | } 64 | 65 | class _WebRootBuilder implements Builder { 66 | @override 67 | Future build(BuildStep buildStep) async { 68 | var examples = await buildStep 69 | .findAssets(Glob('example/**/*.dart')) 70 | .map((asset) => 71 | p.joinAll(asset.changeExtension('.html').pathSegments.skip(1))) 72 | .toList(); 73 | 74 | var exampleLinks = examples.map((p) { 75 | return '

$p

'; 76 | }).join('\n'); 77 | 78 | await buildStep.writeAsString( 79 | AssetId(buildStep.inputId.package, 'example/index.html'), ''' 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | $exampleLinks 88 | 89 | 90 | '''); 91 | } 92 | 93 | @override 94 | final buildExtensions = const { 95 | r'test/$test$': ['example/index.html'] 96 | }; 97 | } 98 | --------------------------------------------------------------------------------