From 3bd2ecb2c46dc14065fb2acd703ba769fb737c8c Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 9 May 2017 15:32:38 -0700 Subject: [PATCH] Move flutter_markdown to https://github.com/flutter/flutter_markdown (#9807) Now that we can host packages on pub that depend on Flutter, we can host flutter_markdown in its own git repository. --- .idea/modules.xml | 3 +- dev/bots/test.dart | 1 - packages/flutter_markdown/README.md | 22 -- packages/flutter_markdown/example/demo.dart | 37 --- .../flutter_markdown/flutter_markdown.iml | 17 -- .../lib/flutter_markdown.dart | 10 - .../flutter_markdown/lib/src/builder.dart | 243 ---------------- .../flutter_markdown/lib/src/style_sheet.dart | 269 ------------------ packages/flutter_markdown/lib/src/widget.dart | 210 -------------- packages/flutter_markdown/pubspec.yaml | 15 - .../test/flutter_markdown_test.dart | 177 ------------ 11 files changed, 1 insertion(+), 1003 deletions(-) delete mode 100644 packages/flutter_markdown/README.md delete mode 100644 packages/flutter_markdown/example/demo.dart delete mode 100644 packages/flutter_markdown/flutter_markdown.iml delete mode 100644 packages/flutter_markdown/lib/flutter_markdown.dart delete mode 100644 packages/flutter_markdown/lib/src/builder.dart delete mode 100644 packages/flutter_markdown/lib/src/style_sheet.dart delete mode 100644 packages/flutter_markdown/lib/src/widget.dart delete mode 100644 packages/flutter_markdown/pubspec.yaml delete mode 100644 packages/flutter_markdown/test/flutter_markdown_test.dart diff --git a/.idea/modules.xml b/.idea/modules.xml index d51ade6a369..62dc2237985 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -7,10 +7,9 @@ - - \ No newline at end of file + diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 8b35da36a39..f3553194c8b 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -100,7 +100,6 @@ Future main() async { ); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver')); await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test')); - await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_markdown')); await _pubRunTest(path.join(flutterRoot, 'packages', 'flutter_tools')); await _runAllDartTests(path.join(flutterRoot, 'dev', 'devicelab')); diff --git a/packages/flutter_markdown/README.md b/packages/flutter_markdown/README.md deleted file mode 100644 index db83e6b73f3..00000000000 --- a/packages/flutter_markdown/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Flutter Markdown - -A markdown renderer for Flutter. It supports the -[original format](https://daringfireball.net/projects/markdown/), but no inline -html. - -## Getting Started - -Using the Markdown widget is simple, just pass in the source markdown as a -string: - - new Markdown(data: markdownSource); - -If you do not want the padding or scrolling behavior, use the MarkdownBody -instead: - - new MarkdownBody(data: markdownSource); - -By default, Markdown uses the formatting from the current material design theme, -but it's possible to create your own custom styling. Use the MarkdownStyle class -to pass in your own style. If you don't want to use Markdown outside of material -design, use the MarkdownRaw class. diff --git a/packages/flutter_markdown/example/demo.dart b/packages/flutter_markdown/example/demo.dart deleted file mode 100644 index 41336ab84d4..00000000000 --- a/packages/flutter_markdown/example/demo.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; - -const String _kMarkdownData = """# Markdown Example -Markdown allows you to easily include formatted text, images, and even formatted Dart code in your app. - -## Styling -Style text as _italic_, __bold__, or `inline code`. - -- Use bulleted lists -- To better clarify -- Your points - -## Links -You can use [hyperlinks](hyperlink) in markdown - -## Code blocks -Formatted Dart code looks really pretty too. This is an example of how to create your own Markdown widget: - - new Markdown(data: 'Hello _world_!'); - -Enjoy! -"""; - -void main() { - runApp(new MaterialApp( - title: "Markdown Demo", - home: new Scaffold( - appBar: new AppBar(title: const Text('Markdown Demo')), - body: const Markdown(data: _kMarkdownData) - ) - )); -} diff --git a/packages/flutter_markdown/flutter_markdown.iml b/packages/flutter_markdown/flutter_markdown.iml deleted file mode 100644 index 4f0181093da..00000000000 --- a/packages/flutter_markdown/flutter_markdown.iml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/flutter_markdown/lib/flutter_markdown.dart b/packages/flutter_markdown/lib/flutter_markdown.dart deleted file mode 100644 index 8d7ed6ea082..00000000000 --- a/packages/flutter_markdown/lib/flutter_markdown.dart +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// A library to render markdown formatted text. -library flutter_markdown; - -export 'src/builder.dart'; -export 'src/style_sheet.dart'; -export 'src/widget.dart'; diff --git a/packages/flutter_markdown/lib/src/builder.dart b/packages/flutter_markdown/lib/src/builder.dart deleted file mode 100644 index 7b91ba0bf40..00000000000 --- a/packages/flutter_markdown/lib/src/builder.dart +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/gestures.dart'; -import 'package:flutter/widgets.dart'; -import 'package:markdown/markdown.dart' as md; - -import 'style_sheet.dart'; - -final Set _kBlockTags = new Set.from([ - 'p', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'li', - 'blockquote', - 'img', - 'pre', - 'ol', - 'ul', -]); - -const List _kListTags = const ['ul', 'ol']; - -bool _isBlockTag(String tag) => _kBlockTags.contains(tag); -bool _isListTag(String tag) => _kListTags.contains(tag); - -class _BlockElement { - _BlockElement(this.tag); - - final String tag; - final List children = []; - - int nextListIndex = 0; -} - -class _InlineElement { - final List children = []; -} - -/// A delegate used by [MarkdownBuilder] to control the widgets it creates. -abstract class MarkdownBuilderDelegate { - /// Returns a gesture recognizer to use for an `a` element with the given - /// `href` attribute. - GestureRecognizer createLink(String href); - - /// Returns formatted text to use to display the given contents of a `pre` - /// element. - /// - /// The `styleSheet` is the value of [MarkdownBuilder.styleSheet]. - TextSpan formatText(MarkdownStyleSheet styleSheet, String code); -} - -/// Builds a [Widget] tree from parsed Markdown. -/// -/// See also: -/// -/// * [Markdown], which is a widget that parses and displays Markdown. -class MarkdownBuilder implements md.NodeVisitor { - /// Creates an object that builds a [Widget] tree from parsed Markdown. - MarkdownBuilder({ this.delegate, this.styleSheet }); - - /// A delegate that controls how link and `pre` elements behave. - final MarkdownBuilderDelegate delegate; - - /// Defines which [TextStyle] objects to use for each type of element. - final MarkdownStyleSheet styleSheet; - - final List _listIndents = []; - final List<_BlockElement> _blocks = <_BlockElement>[]; - final List<_InlineElement> _inlines = <_InlineElement>[]; - - /// Returns widgets that display the given Markdown nodes. - /// - /// The returned widgets are typically used as children in a [ListView]. - List build(List nodes) { - _listIndents.clear(); - _blocks.clear(); - _inlines.clear(); - - _blocks.add(new _BlockElement(null)); - _inlines.add(new _InlineElement()); - - for (md.Node node in nodes) { - assert(_blocks.length == 1); - node.accept(this); - } - - assert(_inlines.single.children.isEmpty); - return _blocks.single.children; - } - - @override - void visitText(md.Text text) { - if (_blocks.last.tag == null) // Don't allow text directly under the root. - return; - final TextSpan span = _blocks.last.tag == 'pre' ? - delegate.formatText(styleSheet, text.text) : new TextSpan(text: text.text); - _inlines.last.children.add(span); - } - - @override - bool visitElementBefore(md.Element element) { - final String tag = element.tag; - if (_isBlockTag(tag)) { - _addAnonymousBlockIfNeeded(styleSheet.styles[tag]); - if (_isListTag(tag)) - _listIndents.add(tag); - _blocks.add(new _BlockElement(tag)); - } else { - _inlines.add(new _InlineElement()); - } - return true; - } - - @override - void visitElementAfter(md.Element element) { - final String tag = element.tag; - - if (_isBlockTag(tag)) { - _addAnonymousBlockIfNeeded(styleSheet.styles[tag]); - - final _BlockElement current = _blocks.removeLast(); - Widget child; - if (tag == 'img') { - child = _buildImage(element.attributes['src']); - } else { - if (current.children.isNotEmpty) { - child = new Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: current.children, - ); - } else { - child = const SizedBox(); - } - - if (_isListTag(tag)) { - assert(_listIndents.isNotEmpty); - _listIndents.removeLast(); - } else if (tag == 'li') { - if (_listIndents.isNotEmpty) { - child = new Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new SizedBox( - width: styleSheet.listIndent, - child: _buildBullet(_listIndents.last), - ), - new Expanded(child: child) - ], - ); - } - } else if (tag == 'blockquote') { - child = new DecoratedBox( - decoration: styleSheet.blockquoteDecoration, - child: new Padding( - padding: new EdgeInsets.all(styleSheet.blockquotePadding), - child: child, - ), - ); - } else if (tag == 'pre') { - child = new DecoratedBox( - decoration: styleSheet.codeblockDecoration, - child: new Padding( - padding: new EdgeInsets.all(styleSheet.codeblockPadding), - child: child, - ), - ); - } - } - - _addBlockChild(child); - } else { - final _InlineElement current = _inlines.removeLast(); - final _InlineElement parent = _inlines.last; - - if (current.children.isNotEmpty) { - GestureRecognizer recognizer; - - if (tag == 'a') - recognizer = delegate.createLink(element.attributes['href']); - - parent.children.add(new TextSpan( - style: styleSheet.styles[tag], - recognizer: recognizer, - children: current.children, - )); - } - } - } - - Widget _buildImage(String src) { - final List parts = src.split('#'); - if (parts.isEmpty) - return const SizedBox(); - - final String path = parts.first; - double width; - double height; - if (parts.length == 2) { - final List dimensions = parts.last.split('x'); - if (dimensions.length == 2) { - width = double.parse(dimensions[0]); - height = double.parse(dimensions[1]); - } - } - - return new Image.network(path, width: width, height: height); - } - - Widget _buildBullet(String listTag) { - if (listTag == 'ul') - return const Text('•', textAlign: TextAlign.center); - - final int index = _blocks.last.nextListIndex; - return new Padding( - padding: const EdgeInsets.only(right: 5.0), - child: new Text('${index + 1}.', textAlign: TextAlign.right), - ); - } - - void _addBlockChild(Widget child) { - final _BlockElement parent = _blocks.last; - if (parent.children.isNotEmpty) - parent.children.add(new SizedBox(height: styleSheet.blockSpacing)); - parent.children.add(child); - parent.nextListIndex += 1; - } - - void _addAnonymousBlockIfNeeded(TextStyle style) { - final _InlineElement inline = _inlines.single; - if (inline.children.isNotEmpty) { - final TextSpan span = new TextSpan(style: style, children: inline.children); - _addBlockChild(new RichText(text: span)); - _inlines.clear(); - _inlines.add(new _InlineElement()); - } - } -} diff --git a/packages/flutter_markdown/lib/src/style_sheet.dart b/packages/flutter_markdown/lib/src/style_sheet.dart deleted file mode 100644 index 8415871de3e..00000000000 --- a/packages/flutter_markdown/lib/src/style_sheet.dart +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; - -/// Defines which [TextStyle] objects to use for which Markdown elements. -class MarkdownStyleSheet { - /// Creates an explicit mapping of [TextStyle] objects to Markdown elements. - MarkdownStyleSheet({ - this.a, - this.p, - this.code, - this.h1, - this.h2, - this.h3, - this.h4, - this.h5, - this.h6, - this.em, - this.strong, - this.blockquote, - this.blockSpacing, - this.listIndent, - this.blockquotePadding, - this.blockquoteDecoration, - this.codeblockPadding, - this.codeblockDecoration - }) : _styles = { - 'a': a, - 'p': p, - 'li': p, - 'code': code, - 'pre': p, - 'h1': h1, - 'h2': h2, - 'h3': h3, - 'h4': h4, - 'h5': h5, - 'h6': h6, - 'em': em, - 'strong': strong, - 'blockquote': blockquote - }; - - /// Creates a [MarkdownStyleSheet] from the [TextStyle]s in the provided [ThemeData]. - factory MarkdownStyleSheet.fromTheme(ThemeData theme) { - return new MarkdownStyleSheet( - a: const TextStyle(color: Colors.blue), - p: theme.textTheme.body1, - code: new TextStyle( - color: Colors.grey.shade700, - fontFamily: "monospace", - fontSize: theme.textTheme.body1.fontSize * 0.85 - ), - h1: theme.textTheme.headline, - h2: theme.textTheme.title, - h3: theme.textTheme.subhead, - h4: theme.textTheme.body2, - h5: theme.textTheme.body2, - h6: theme.textTheme.body2, - em: const TextStyle(fontStyle: FontStyle.italic), - strong: const TextStyle(fontWeight: FontWeight.bold), - blockquote: theme.textTheme.body1, - blockSpacing: 8.0, - listIndent: 32.0, - blockquotePadding: 8.0, - blockquoteDecoration: new BoxDecoration( - color: Colors.blue.shade100, - borderRadius: new BorderRadius.circular(2.0) - ), - codeblockPadding: 8.0, - codeblockDecoration: new BoxDecoration( - color: Colors.grey.shade100, - borderRadius: new BorderRadius.circular(2.0) - ) - ); - } - - /// Creates a [MarkdownStyle] from the [TextStyle]s in the provided [ThemeData]. - /// - /// This constructor uses larger fonts for the headings than in - /// [new MarkdownStyle.fromTheme]. - factory MarkdownStyleSheet.largeFromTheme(ThemeData theme) { - return new MarkdownStyleSheet( - a: const TextStyle(color: Colors.blue), - p: theme.textTheme.body1, - code: new TextStyle( - color: Colors.grey.shade700, - fontFamily: "monospace", - fontSize: theme.textTheme.body1.fontSize * 0.85 - ), - h1: theme.textTheme.display3, - h2: theme.textTheme.display2, - h3: theme.textTheme.display1, - h4: theme.textTheme.headline, - h5: theme.textTheme.title, - h6: theme.textTheme.subhead, - em: const TextStyle(fontStyle: FontStyle.italic), - strong: const TextStyle(fontWeight: FontWeight.bold), - blockquote: theme.textTheme.body1, - blockSpacing: 8.0, - listIndent: 32.0, - blockquotePadding: 8.0, - blockquoteDecoration: new BoxDecoration( - color: Colors.blue.shade100, - borderRadius: new BorderRadius.circular(2.0) - ), - codeblockPadding: 8.0, - codeblockDecoration: new BoxDecoration( - color: Colors.grey.shade100, - borderRadius: new BorderRadius.circular(2.0) - ) - ); - } - - /// Creates a new [MarkdownStyleSheet] based on the current style, with the - /// provided parameters overridden. - MarkdownStyleSheet copyWith({ - TextStyle a, - TextStyle p, - TextStyle code, - TextStyle h1, - TextStyle h2, - TextStyle h3, - TextStyle h4, - TextStyle h5, - TextStyle h6, - TextStyle em, - TextStyle strong, - TextStyle blockquote, - double blockSpacing, - double listIndent, - double blockquotePadding, - Decoration blockquoteDecoration, - double codeblockPadding, - Decoration codeblockDecoration - }) { - return new MarkdownStyleSheet( - a: a != null ? a : this.a, - p: p != null ? p : this.p, - code: code != null ? code : this.code, - h1: h1 != null ? h1 : this.h1, - h2: h2 != null ? h2 : this.h2, - h3: h3 != null ? h3 : this.h3, - h4: h4 != null ? h4 : this.h4, - h5: h5 != null ? h5 : this.h5, - h6: h6 != null ? h6 : this.h6, - em: em != null ? em : this.em, - strong: strong != null ? strong : this.strong, - blockquote: blockquote != null ? blockquote : this.blockquote, - blockSpacing: blockSpacing != null ? blockSpacing : this.blockSpacing, - listIndent: listIndent != null ? listIndent : this.listIndent, - blockquotePadding: blockquotePadding != null ? blockquotePadding : this.blockquotePadding, - blockquoteDecoration: blockquoteDecoration != null ? blockquoteDecoration : this.blockquoteDecoration, - codeblockPadding: codeblockPadding != null ? codeblockPadding : this.codeblockPadding, - codeblockDecoration: codeblockDecoration != null ? codeblockDecoration : this.codeblockDecoration - ); - } - - /// The [TextStyle] to use for `a` elements. - final TextStyle a; - - /// The [TextStyle] to use for `p` elements. - final TextStyle p; - - /// The [TextStyle] to use for `code` elements. - final TextStyle code; - - /// The [TextStyle] to use for `h1` elements. - final TextStyle h1; - - /// The [TextStyle] to use for `h2` elements. - final TextStyle h2; - - /// The [TextStyle] to use for `h3` elements. - final TextStyle h3; - - /// The [TextStyle] to use for `h4` elements. - final TextStyle h4; - - /// The [TextStyle] to use for `h5` elements. - final TextStyle h5; - - /// The [TextStyle] to use for `h6` elements. - final TextStyle h6; - - /// The [TextStyle] to use for `em` elements. - final TextStyle em; - - /// The [TextStyle] to use for `strong` elements. - final TextStyle strong; - - /// The [TextStyle] to use for `blockquote` elements. - final TextStyle blockquote; - - /// The amount of vertical space to use between block-level elements. - final double blockSpacing; - - /// The amount of horizontal space to indent list items. - final double listIndent; - - /// The padding to use for `blockquote` elements. - final double blockquotePadding; - - /// The decoration to use behind `blockquote` elements. - final Decoration blockquoteDecoration; - - /// The padding to use for `pre` elements. - final double codeblockPadding; - - /// The decoration to use behind for `pre` elements. - final Decoration codeblockDecoration; - - /// A [Map] from element name to the cooresponding [TextStyle] object. - Map get styles => _styles; - Map _styles; - - @override - bool operator ==(dynamic other) { - if (identical(this, other)) - return true; - if (other.runtimeType != MarkdownStyleSheet) - return false; - final MarkdownStyleSheet typedOther = other; - return typedOther.a == a - && typedOther.p == p - && typedOther.code == code - && typedOther.h1 == h1 - && typedOther.h2 == h2 - && typedOther.h3 == h3 - && typedOther.h4 == h4 - && typedOther.h5 == h5 - && typedOther.h6 == h6 - && typedOther.em == em - && typedOther.strong == strong - && typedOther.blockquote == blockquote - && typedOther.blockSpacing == blockSpacing - && typedOther.listIndent == listIndent - && typedOther.blockquotePadding == blockquotePadding - && typedOther.blockquoteDecoration == blockquoteDecoration - && typedOther.codeblockPadding == codeblockPadding - && typedOther.codeblockDecoration == codeblockDecoration; - } - - @override - int get hashCode { - return hashValues( - a, - p, - code, - h1, - h2, - h3, - h4, - h5, - h6, - em, - strong, - blockquote, - blockSpacing, - listIndent, - blockquotePadding, - blockquoteDecoration, - codeblockPadding, - codeblockDecoration, - ); - } -} diff --git a/packages/flutter_markdown/lib/src/widget.dart b/packages/flutter_markdown/lib/src/widget.dart deleted file mode 100644 index 974b2cde36e..00000000000 --- a/packages/flutter_markdown/lib/src/widget.dart +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:markdown/markdown.dart' as md; -import 'package:meta/meta.dart'; - -import 'builder.dart'; -import 'style_sheet.dart'; - -/// Signature for callbacks used by [MarkdownWidget] when the user taps a link. -/// -/// Used by [MarkdownWidget.onTapLink]. -typedef void MarkdownTapLinkCallback(String href); - -/// Creates a format [TextSpan] given a string. -/// -/// Used by [MarkdownWidget] to highlight the contents of `pre` elements. -abstract class SyntaxHighlighter { // ignore: one_member_abstracts - /// Returns the formated [TextSpan] for the given string. - TextSpan format(String source); -} - -/// A base class for widgets that parse and display Markdown. -/// -/// Supports all standard Markdown from the original -/// [Markdown specification](https://daringfireball.net/projects/markdown/). -/// -/// See also: -/// -/// * [Markdown], which is a scrolling container of Markdown. -/// * [MarkdownBody], which is a non-scrolling container of Markdown. -/// * -abstract class MarkdownWidget extends StatefulWidget { - /// Creates a widget that parses and displays Markdown. - /// - /// The [data] argument must not be null. - const MarkdownWidget({ - Key key, - @required this.data, - this.styleSheet, - this.syntaxHighlighter, - this.onTapLink, - }) : assert(data != null), - super(key: key); - - /// The Markdown to display. - final String data; - - /// The styles to use when displaying the Markdown. - /// - /// If null, the styles are infered from the current [Theme]. - final MarkdownStyleSheet styleSheet; - - /// The syntax highlighter used to color text in `pre` elements. - /// - /// If null, the [MarkdownStyleSheet.code] style is used for `pre` elements. - final SyntaxHighlighter syntaxHighlighter; - - /// Called when the user taps a link. - final MarkdownTapLinkCallback onTapLink; - - /// Subclasses should override this function to display the given children, - /// which are the parsed representation of [data]. - @protected - Widget build(BuildContext context, List children); - - @override - _MarkdownWidgetState createState() => new _MarkdownWidgetState(); -} - -class _MarkdownWidgetState extends State implements MarkdownBuilderDelegate { - List _children; - final List _recognizers = []; - - @override - void didChangeDependencies() { - _parseMarkdown(); - super.didChangeDependencies(); - } - - @override - void didUpdateWidget(MarkdownWidget oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.data != oldWidget.data - || widget.styleSheet != oldWidget.styleSheet) - _parseMarkdown(); - } - - @override - void dispose() { - _disposeRecognizers(); - super.dispose(); - } - - void _parseMarkdown() { - final MarkdownStyleSheet styleSheet = widget.styleSheet ?? new MarkdownStyleSheet.fromTheme(Theme.of(context)); - - _disposeRecognizers(); - - // TODO: This can be optimized by doing the split and removing \r at the same time - final List lines = widget.data.replaceAll('\r\n', '\n').split('\n'); - final md.Document document = new md.Document(); - final MarkdownBuilder builder = new MarkdownBuilder(delegate: this, styleSheet: styleSheet); - _children = builder.build(document.parseLines(lines)); - } - - void _disposeRecognizers() { - if (_recognizers.isEmpty) - return; - final List localRecognizers = new List.from(_recognizers); - _recognizers.clear(); - for (GestureRecognizer recognizer in localRecognizers) - recognizer.dispose(); - } - - @override - GestureRecognizer createLink(String href) { - final TapGestureRecognizer recognizer = new TapGestureRecognizer() - ..onTap = () { - if (widget.onTapLink != null) - widget.onTapLink(href); - }; - _recognizers.add(recognizer); - return recognizer; - } - - @override - TextSpan formatText(MarkdownStyleSheet styleSheet, String code) { - if (widget.syntaxHighlighter != null) - return widget.syntaxHighlighter.format(code); - return new TextSpan(style: styleSheet.code, text: code); - } - - @override - Widget build(BuildContext context) => widget.build(context, _children); -} - -/// A non-scrolling widget that parses and displays Markdown. -/// -/// Supports all standard Markdown from the original -/// [Markdown specification](https://daringfireball.net/projects/markdown/). -/// -/// See also: -/// -/// * [Markdown], which is a scrolling container of Markdown. -/// * -class MarkdownBody extends MarkdownWidget { - /// Creates a non-scrolling widget that parses and displays Markdown. - const MarkdownBody({ - Key key, - String data, - MarkdownStyleSheet styleSheet, - SyntaxHighlighter syntaxHighlighter, - MarkdownTapLinkCallback onTapLink, - }) : super( - key: key, - data: data, - styleSheet: styleSheet, - syntaxHighlighter: syntaxHighlighter, - onTapLink: onTapLink, - ); - - @override - Widget build(BuildContext context, List children) { - if (children.length == 1) - return children.single; - return new Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: children, - ); - } -} - -/// A scrolling widget that parses and displays Markdown. -/// -/// Supports all standard Markdown from the original -/// [Markdown specification](https://daringfireball.net/projects/markdown/). -/// -/// See also: -/// -/// * [MarkdownBody], which is a non-scrolling container of Markdown. -/// * -class Markdown extends MarkdownWidget { - /// Creates a scrolling widget that parses and displays Markdown. - const Markdown({ - Key key, - String data, - MarkdownStyleSheet styleSheet, - SyntaxHighlighter syntaxHighlighter, - MarkdownTapLinkCallback onTapLink, - this.padding: const EdgeInsets.all(16.0), - }) : super( - key: key, - data: data, - styleSheet: styleSheet, - syntaxHighlighter: syntaxHighlighter, - onTapLink: onTapLink, - ); - - /// The amount of space by which to inset the children. - final EdgeInsets padding; - - @override - Widget build(BuildContext context, List children) { - return new ListView(padding: padding, children: children); - } -} diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml deleted file mode 100644 index 117d7340236..00000000000 --- a/packages/flutter_markdown/pubspec.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: flutter_markdown -description: A markdown renderer for Flutter. -version: 0.1.0 -author: Flutter Authors -homepage: http://flutter.io - -dependencies: - flutter: - sdk: flutter - markdown: '^0.11.0' - string_scanner: ^1.0.0 - -dev_dependencies: - flutter_test: - sdk: flutter diff --git a/packages/flutter_markdown/test/flutter_markdown_test.dart b/packages/flutter_markdown/test/flutter_markdown_test.dart deleted file mode 100644 index 73d5ca57bf2..00000000000 --- a/packages/flutter_markdown/test/flutter_markdown_test.dart +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/widgets.dart'; -import 'package:flutter/material.dart'; - -void main() { - testWidgets('Simple string', (WidgetTester tester) async { - await tester.pumpWidget(const MarkdownBody(data: 'Hello')); - - final Iterable widgets = tester.allWidgets; - _expectWidgetTypes(widgets, [MarkdownBody, Column, RichText]); - _expectTextStrings(widgets, ['Hello']); - }); - - testWidgets('Header', (WidgetTester tester) async { - await tester.pumpWidget(const MarkdownBody(data: '# Header')); - - final Iterable widgets = tester.allWidgets; - _expectWidgetTypes(widgets, [MarkdownBody, Column, RichText]); - _expectTextStrings(widgets, ['Header']); - }); - - testWidgets('Empty string', (WidgetTester tester) async { - await tester.pumpWidget(const MarkdownBody(data: '')); - - final Iterable widgets = tester.allWidgets; - _expectWidgetTypes(widgets, [MarkdownBody, Column]); - }); - - testWidgets('Ordered list', (WidgetTester tester) async { - await tester.pumpWidget(const MarkdownBody(data: '1. Item 1\n1. Item 2\n2. Item 3')); - - final Iterable widgets = tester.allWidgets; - _expectTextStrings(widgets, [ - '1.', - 'Item 1', - '2.', - 'Item 2', - '3.', - 'Item 3', - ]); - }); - - testWidgets('Unordered list', (WidgetTester tester) async { - await tester.pumpWidget(const MarkdownBody(data: '- Item 1\n- Item 2\n- Item 3')); - - final Iterable widgets = tester.allWidgets; - _expectTextStrings(widgets, [ - '•', - 'Item 1', - '•', - 'Item 2', - '•', - 'Item 3', - ]); - }); - - testWidgets('Scrollable wrapping', (WidgetTester tester) async { - await tester.pumpWidget(const Markdown(data: '')); - - final List widgets = tester.allWidgets.toList(); - _expectWidgetTypes(widgets.take(2), [ - Markdown, - ListView, - ]); - _expectWidgetTypes(widgets.reversed.take(2).toList().reversed, [ - SliverPadding, - SliverList, - ]); - }); - - testWidgets('Links', (WidgetTester tester) async { - await tester.pumpWidget(const Markdown(data: '[Link Text](href)')); - - final RichText textWidget = tester.allWidgets.firstWhere((Widget widget) => widget is RichText); - final TextSpan span = textWidget.text; - - expect(span.children[0].recognizer.runtimeType, equals(TapGestureRecognizer)); - }); - - testWidgets('HTML tag ignored ', (WidgetTester tester) async { - final List mdData = [ - 'Line 1\n

HTML content

\nLine 2', - 'Line 1\n<\nLine 2' - ]; - - for (String mdLine in mdData) { - await tester.pumpWidget(new MarkdownBody(data: mdLine)); - - final Iterable widgets = tester.allWidgets; - _expectTextStrings(widgets, ['Line 1', 'Line 2']); - } - }); - - testWidgets('Less than', (WidgetTester tester) async { - final String mdLine = 'Line 1 <\n\nc < c c\n\n< Line 2'; - await tester.pumpWidget(new MarkdownBody(data: mdLine)); - - final Iterable widgets = tester.allWidgets; - _expectTextStrings(widgets, ['Line 1 <','c < c c','< Line 2']); - }); - - testWidgets('Changing config - data', (WidgetTester tester) async { - await tester.pumpWidget(const Markdown(data: 'Data1')); - _expectTextStrings(tester.allWidgets, ['Data1']); - - final String stateBefore = _dumpRenderView(); - await tester.pumpWidget(const Markdown(data: 'Data1')); - final String stateAfter = _dumpRenderView(); - expect(stateBefore, equals(stateAfter)); - - await tester.pumpWidget(const Markdown(data: 'Data2')); - _expectTextStrings(tester.allWidgets, ['Data2']); - }); - - testWidgets('Changing config - style', (WidgetTester tester) async { - final ThemeData theme = new ThemeData.light(); - - final MarkdownStyleSheet style1 = new MarkdownStyleSheet.fromTheme(theme); - final MarkdownStyleSheet style2 = new MarkdownStyleSheet.largeFromTheme(theme); - expect(style1, isNot(style2)); - - await tester.pumpWidget(new Markdown(data: '# Test', styleSheet: style1)); - final RichText text1 = tester.widget(find.byType(RichText)); - await tester.pumpWidget(new Markdown(data: '# Test', styleSheet: style2)); - final RichText text2 = tester.widget(find.byType(RichText)); - - expect(text1.text, isNot(text2.text)); - }); - - testWidgets('Style equality', (WidgetTester tester) async { - final ThemeData theme = new ThemeData.light(); - - final MarkdownStyleSheet style1 = new MarkdownStyleSheet.fromTheme(theme); - final MarkdownStyleSheet style2 = new MarkdownStyleSheet.fromTheme(theme); - expect(style1, equals(style2)); - expect(style1.hashCode, equals(style2.hashCode)); - }); -} - -void _expectWidgetTypes(Iterable widgets, List expected) { - final List actual = widgets.map((Widget w) => w.runtimeType).toList(); - expect(actual, expected); -} - -void _expectTextStrings(Iterable widgets, List strings) { - int currentString = 0; - for (Widget widget in widgets) { - if (widget is RichText) { - final TextSpan span = widget.text; - final String text = _extractTextFromTextSpan(span); - expect(text, equals(strings[currentString])); - currentString += 1; - } - } -} - -String _extractTextFromTextSpan(TextSpan span) { - String text = span.text ?? ''; - if (span.children != null) { - for (TextSpan child in span.children) { - text += _extractTextFromTextSpan(child); - } - } - return text; -} - -String _dumpRenderView() { - return WidgetsBinding.instance.renderViewElement.toStringDeep().replaceAll( - new RegExp(r'SliverChildListDelegate#\d+', multiLine: true), 'SliverChildListDelegate' - ); -}