diff --git a/.analysis_options b/.analysis_options new file mode 100644 index 00000000000..174aa2c9dae --- /dev/null +++ b/.analysis_options @@ -0,0 +1,4 @@ +analyzer: + exclude: + - '_includes/**' + - '_layouts/**' diff --git a/.gitignore b/.gitignore index badbc02f6c1..0dbf596f77c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ _site .sass-cache + +# Dart ignores. +.packages +.pub/ +pubspec.lock +packages +example/*.dart diff --git a/_config.yml b/_config.yml index 3a1b6430ac3..f2f62c9f2c5 100644 --- a/_config.yml +++ b/_config.yml @@ -12,3 +12,5 @@ markdown: kramdown kramdown: input: GFM hard_wrap: false + +exclude: [example, packages, tool] diff --git a/example/readme.md b/example/readme.md new file mode 100644 index 00000000000..081f7122fd7 --- /dev/null +++ b/example/readme.md @@ -0,0 +1 @@ +Note: All Dart files in this directory are git ignored. diff --git a/getting-started.md b/getting-started.md index adc1e82d3c6..889e5ba5799 100644 --- a/getting-started.md +++ b/getting-started.md @@ -23,6 +23,7 @@ Once you have installed Dart SDK, create a new directory and add a name: your_app_name dependencies: flutter: any +dev_dependencies: sky_tools: any ``` @@ -36,7 +37,7 @@ Flutter assumes the entry point for your application is a `main` function in `lib/main.dart`: ```dart -import 'package:flutter/materal.dart'; +import 'package:flutter/material.dart'; void main() => runApp(new Center(child: new Text('Hello, world!'))); ``` @@ -65,7 +66,7 @@ of the Android operating system. device, authorize your computer to access your device. Running a Flutter application -------------------------- +----------------------------- Flutter includes a `sky_tool` script to assist in running Flutter applications inside the development environment. The `sky_tool` script expects diff --git a/layout.md b/layout.md index d038105dc2f..84244af743b 100644 --- a/layout.md +++ b/layout.md @@ -3,6 +3,7 @@ layout: page title: Layout permalink: /layout/ --- + In Flutter, widgets are rendered by render boxes. Render boxes are given constraints by their parent, and size themselves within those constraints. Constraints consist of minimum and maximum widths and diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 00000000000..662eeaf4ddb --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,5 @@ +name: flutter_github_io +version: 0.0.1 +dev_dependencies: + flutter: any + path: any diff --git a/rendering.md b/rendering.md index 4c13b8a8601..12a3c1146c4 100644 --- a/rendering.md +++ b/rendering.md @@ -3,11 +3,12 @@ layout: page title: Rendering permalink: /rendering/ --- + The Flutter render tree is a low-level layout and painting system based on a retained tree of objects that inherit from `RenderObject`. Most developers using Flutter will not need to interact directly with the rendering tree. Instead, most developers should use [widgets](/tutorial/), which are built using - the render tree. +the render tree. Overview -------- @@ -242,6 +243,7 @@ A `RenderBox` subclass is required to implement the following contract: `RenderBox` nodes, then change the `setupParentData()` signature accordingly, to catch misuse of the method.) + ```dart class FooParentData extends BoxParentData { ... } @@ -394,7 +396,9 @@ working with the render tree. import 'package:flutter/animation.dart'; import 'package:flutter/rendering.dart'; -scheduler.addPersistentFrameCallback((_) { - FlutterBinding.instance.debugDumpRenderTree(); -}); +void main() { + scheduler.addPersistentFrameCallback((_) { + FlutterBinding.instance.debugDumpRenderTree(); + }); +} ``` diff --git a/tool/extract.dart b/tool/extract.dart new file mode 100644 index 00000000000..7a3ef69929c --- /dev/null +++ b/tool/extract.dart @@ -0,0 +1,100 @@ +import 'dart:io'; + +import 'package:path/path.dart' as p; + +/// Extract Dart snippets from the markdown documentation. +void main(List args) { + // Validate our cwd. + if (!new File('pubspec.yaml').existsSync()) { + print('This tool must be run from the project root.'); + exit(1); + } + + // Remove any previously generated files. + clean(); + + // Traverse markdown files in the root. + int extractCount = 0; + Iterable files = Directory.current + .listSync() + .where((entity) => entity is File && entity.path.endsWith('.md')); + files.forEach((file) => extractCount += _processFile(file)); + print('\n${extractCount} code snippets extracted.'); +} + +int _processFile(File file) { + String name = p.basename(file.path); + print(name); + + // Look for ```dart sections. + String source = file.readAsStringSync(); + List lines = source.split('\n'); + + int index = 1; + int count = 0; + + String lastComment; + + while (index < lines.length) { + // Look for ```dart sections. + if (lines[index].startsWith('```dart') && lastComment != 'skip') { + int startIndex = index + 1; + index++; + while (index < lines.length && !lines[index].startsWith('```')) { + index++; + } + _extractSnippet(name, ++count, startIndex, lines.sublist(startIndex, index), + includeSource: lastComment); + } else if (lines[index].startsWith('')) { + index++; + } + + lastComment = lines.sublist(startIndex, index + 1).join('\n'); + lastComment = lastComment.substring(4); + lastComment = lastComment.substring(0, lastComment.length - 3).trim(); + } else { + lastComment = null; + } + + index++; + } + + return count; +} + +void _extractSnippet(String filename, int snippet, int startLine, List lines, + {String includeSource}) { + bool hasImport = lines.first.trim().startsWith('import '); + String path = 'example/${filename.replaceAll('-', '_').replaceAll('.', '_')}_' + '${snippet}.dart'; + + int adjust = 1; + String source = '// Extracted from ${filename}, line ${startLine}.\n'; + + if (!hasImport) { + source += "import 'package:flutter/material.dart';\n"; + adjust++; + } + + if (includeSource != null) { + source += "${includeSource}\n"; + adjust += includeSource.split('\n').length; + } + + source += + '${''.padRight(startLine - adjust, '\n')}' + '${lines.join('\n')}\n'; + + new File(path).writeAsStringSync(source); + print(' ${lines.length} line snippet ==> ${path}'); +} + +void clean() { + Iterable files = new Directory('example') + .listSync() + .where((entity) => entity is File && entity.path.endsWith('.dart')); + files.forEach((file) => file.deleteSync()); +} diff --git a/tool/travis.sh b/tool/travis.sh new file mode 100755 index 00000000000..d2028dd3960 --- /dev/null +++ b/tool/travis.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Fast fail the script on failures. +set -e + +# Extract Dart snippets from the markdown documentation. +dart tool/extract.dart + +# Analyze the extracted Dart libraries. +pub global activate tuneup +pub global run tuneup check diff --git a/tos.md b/tos.md index dd3c667c22a..e2911b52421 100644 --- a/tos.md +++ b/tos.md @@ -3,12 +3,12 @@ layout: page title: Terms of Service permalink: /tos/ --- + # Terms of Service -The Flutter website (the "Website") is hosted by Google. By using and/or +The Flutter website (the "Website") is hosted by Google. By using and / or visiting the Website, you consent to be bound by Google's general -[Terms of Service][tos] and Google's general -[Privacy Policy][pp]. +[Terms of Service][tos] and Google's general [Privacy Policy][pp]. [tos]: http://www.google.com/accounts/TOS [pp]: http://www.google.com/intl/en/policies/privacy/ diff --git a/tutorial.md b/tutorial.md index 5114e165af4..b6a75d92a7c 100644 --- a/tutorial.md +++ b/tutorial.md @@ -4,6 +4,7 @@ title: Flutter Tutorial nav_title: Tutorial permalink: /tutorial/ --- + Flutter widgets are built using a functional-reactive framework, which takes inspiration from [React](http://facebook.github.io/react/). The central idea is that you build your UI out of components. Components describe what their view @@ -91,6 +92,7 @@ ratio in which they consume the available space using the `flex` argument to To use this component, we simply create an instance of `MyToolBar` in a `build` function: + ```dart import 'package:flutter/material.dart'; @@ -132,8 +134,8 @@ input. The first step in building an interactive application is to detect input gestures. Let's see how that works by creating a simple button: ```dart -import 'package:flutter/painting.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; final BoxDecoration _decoration = new BoxDecoration( borderRadius: 5.0, @@ -185,6 +187,8 @@ class MyButton extends StatelessComponent { final Widget child; final Function onPressed; + BoxDecoration _decoration; + Widget build(BuildContext context) { return new GestureDetector( onTap: onPressed, @@ -205,6 +209,11 @@ uses `MyButton` provide an arbitrary `Widget` to put inside the button. For example, we can put an elaborate layout involving text and an image inside the button: + ```dart Widget build(BuildContext context) { return new MyButton( @@ -237,6 +246,11 @@ a checkbox. While the dialog is open, the user might check and uncheck the checkbox several times before closing the dialog and committing the final value of the checkbox to the underlying application data model. + ```dart class MyCheckbox extends StatelessComponent { MyCheckbox({ this.value, this.onChanged }); @@ -247,7 +261,7 @@ class MyCheckbox extends StatelessComponent { Widget build(BuildContext context) { Color color = value ? const Color(0xFF00FF00) : const Color(0xFF0000FF); return new GestureDetector( - onTap: () { onChanged(!value) }, + onTap: () { onChanged(!value); }, child: new Container( height: 25.0, width: 25.0, @@ -381,12 +395,21 @@ only be unique among siblings. Because they are globally unique, a global key can be used to retrieve the state associated with a widget. Consider the following example: + ```dart class MyComponentState extends State { GlobalKey _scrollable = new GlobalKey(); Widget build(BuildContext context) { - return Column([ + return new Column([ new MyButton( onPressed: () { (_scrollable.currentState as ScrollableState).scrollBy(10.0); @@ -402,7 +425,7 @@ class MyComponentState extends State { child: new Center(child: new Text('$i')) ); } - ); + ) ]); } } @@ -425,6 +448,7 @@ This can be quite useful in figuring out exactly what is going on when working with the widgets system. For this to work, you have to have launched your app with `runApp()`. + ```dart debugDumpApp(); ``` diff --git a/widgets.md b/widgets.md index 148bfb801e6..1bb28cc4a90 100644 --- a/widgets.md +++ b/widgets.md @@ -4,6 +4,7 @@ title: Widget Gallery nav_title: Widgets permalink: /widgets/ --- + This page describes the widgets available in Flutter. These widgets are general-purpose and don't offer an opinion about the visual style of your app. @@ -39,7 +40,7 @@ The direction along which the widgets are laid out is called the *main* direction and the other axis is called the *cross* direction. These flex widgets size themselves to the maximum size permitted by its parent, unless that would be infinite size, in which case they -shrink-wrap their children. For details, see [flex.md](flex.md). +shrink-wrap their children. For details, see [layout](../layout/#flex). Each child of a flex widget is either *flexible* or *inflexible*. The flex first lays out its inflexible children and subtracts their