blob: 58553ecc1cbcbf0f3c2359c82470bc670bccdc8f [file] [log] [blame]
// Copyright 2013 The Flutter 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/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import '../shared/dropdown_menu.dart';
import '../shared/markdown_demo_widget.dart';
import '../shared/markdown_extensions.dart';
// ignore_for_file: public_member_api_docs
const String _notes = """
# Basic Markdown Demo
---
The Basic Markdown Demo shows the effect of the four Markdown extension sets
on formatting basic and extended Markdown tags.
## Overview
The Dart [markdown](https://pub.dev/packages/markdown) package parses Markdown
into HTML. The flutter_markdown package builds on this package using the
abstract syntax tree generated by the parser to make a tree of widgets instead
of HTML elements.
The markdown package supports the basic block and inline Markdown syntax
specified in the original Markdown implementation as well as a few Markdown
extensions. The markdown package uses extension sets to make extension
management easy. There are four pre-defined extension sets; none, Common Mark,
GitHub Flavored, and GitHub Web. The default extension set used by the
flutter_markdown package is GitHub Flavored.
The Basic Markdown Demo shows the effect each of the pre-defined extension sets
has on a test Markdown document with basic and extended Markdown tags. Use the
Extension Set dropdown menu to select an extension set and view the Markdown
widget's output.
## Comments
Since GitHub Flavored is the default extension set, it is the initial setting
for the formatted Markdown view in the demo.
""";
// TODO(goderbauer): Restructure the examples to avoid this ignore, https://github.com/flutter/flutter/issues/110208.
// ignore: avoid_implementing_value_types
class BasicMarkdownDemo extends StatefulWidget implements MarkdownDemoWidget {
const BasicMarkdownDemo({Key? key}) : super(key: key);
static const String _title = 'Basic Markdown Demo';
@override
String get title => BasicMarkdownDemo._title;
@override
String get description => 'Shows the effect the four Markdown extension sets '
'have on basic and extended Markdown tagged elements.';
@override
Future<String> get data =>
rootBundle.loadString('assets/markdown_test_page.md');
@override
Future<String> get notes => Future<String>.value(_notes);
@override
State<BasicMarkdownDemo> createState() => _BasicMarkdownDemoState();
}
class _BasicMarkdownDemoState extends State<BasicMarkdownDemo> {
MarkdownExtensionSet _extensionSet = MarkdownExtensionSet.githubFlavored;
final Map<String, MarkdownExtensionSet> _menuItems =
Map<String, MarkdownExtensionSet>.fromIterables(
MarkdownExtensionSet.values.map((MarkdownExtensionSet e) => e.displayTitle),
MarkdownExtensionSet.values,
);
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: widget.data,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
children: <Widget>[
DropdownMenu<MarkdownExtensionSet>(
items: _menuItems,
label: 'Extension Set:',
initialValue: _extensionSet,
onChanged: (MarkdownExtensionSet? value) {
if (value != _extensionSet) {
setState(() {
_extensionSet = value!;
});
}
},
),
Expanded(
child: Markdown(
key: Key(_extensionSet.name),
data: snapshot.data!,
imageDirectory: 'https://raw.githubusercontent.com',
extensionSet: _extensionSet.value,
onTapLink: (String text, String? href, String title) =>
linkOnTapHandler(context, text, href, title),
),
),
],
);
} else {
return const CircularProgressIndicator();
}
},
);
}
// Handle the link. The [href] in the callback contains information
// from the link. The url_launcher package or other similar package
// can be used to execute the link.
Future<void> linkOnTapHandler(
BuildContext context,
String text,
String? href,
String title,
) async {
showDialog<Widget>(
context: context,
builder: (BuildContext context) =>
_createDialog(context, text, href, title),
);
}
Widget _createDialog(
BuildContext context, String text, String? href, String title) =>
AlertDialog(
title: const Text('Reference Link'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'See the following link for more information:',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 8),
Text(
'Link text: $text',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 8),
Text(
'Link destination: $href',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 8),
Text(
'Link title: $title',
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
)
],
);
}