mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Minor sample index cleanup (#1532)
This commit is contained in:
@@ -7,9 +7,9 @@ import 'package:path/path.dart' as p;
|
||||
import 'common.dart';
|
||||
import 'fix_base_tags.dart';
|
||||
|
||||
final ignoredDirectories = ['_tool', 'samples_index'];
|
||||
const ignoredDirectories = ['_tool', 'samples_index'];
|
||||
|
||||
main() async {
|
||||
void main() async {
|
||||
final packageDirs = [
|
||||
...listPackageDirs(Directory.current)
|
||||
.map((path) => p.relative(path, from: Directory.current.path))
|
||||
|
||||
@@ -14,7 +14,7 @@ import 'package:path/path.dart' as p;
|
||||
|
||||
import 'common.dart';
|
||||
|
||||
main(List<String> args) async {
|
||||
void main(List<String> args) async {
|
||||
final buildDir = args[0];
|
||||
final fileMap =
|
||||
(jsonDecode(args[1]) as Map<String, dynamic>).cast<String, String>();
|
||||
|
||||
@@ -2,7 +2,7 @@ name: tool
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
markdown: ^6.0.0
|
||||
|
||||
1
web/samples_index/.gitignore
vendored
1
web/samples_index/.gitignore
vendored
@@ -3,7 +3,6 @@ public/
|
||||
|
||||
# Files and directories created by pub
|
||||
.dart_tool/
|
||||
.packages
|
||||
# Remove the following pattern if you wish to check in your lock file
|
||||
pubspec.lock
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ This tool is used to generate the visual samples index for Flutter samples.
|
||||
We use [grinder](https://pub.dev/packages/grinder) to run the build tasks:
|
||||
|
||||
```bash
|
||||
$ pub get
|
||||
$ pub global activate grinder
|
||||
$ grind generate
|
||||
$ dart pub get
|
||||
$ dart run grinder generate
|
||||
```
|
||||
|
||||
This will generate the index into `./web`
|
||||
@@ -20,6 +19,7 @@ If you want to serve the index locally, you can use
|
||||
[webdev](https://pub.dev/packages/webdev):
|
||||
|
||||
```bash
|
||||
$ dart pub global activate grinder
|
||||
$ webdev serve
|
||||
```
|
||||
|
||||
@@ -28,16 +28,16 @@ $ webdev serve
|
||||
You can build the complete index into a publishable directory using Grinder:
|
||||
|
||||
```bash
|
||||
$ grind build-release
|
||||
$ dart run grinder build-release
|
||||
```
|
||||
|
||||
This outputs the completely built index to `./public`.
|
||||
|
||||
## Generating cookbook content
|
||||
|
||||
The cookbook articles are generated using a WebDriver script that scrapes the
|
||||
flutter.dev website. To run:
|
||||
The cookbook articles are generated using a WebDriver script
|
||||
that scrapes the docs.flutter.dev website. To run:
|
||||
|
||||
1. Install [ChromeDriver](https://chromedriver.chromium.org/downloads)
|
||||
2. run `chromedriver --port=4444 --url-base=wd/hub --verbose`
|
||||
3. run `grind scrape-cookbook`
|
||||
3. run `dart run grinder scrape-cookbook`
|
||||
|
||||
@@ -6,6 +6,7 @@ analyzer:
|
||||
language:
|
||||
strict-casts: true
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
linter:
|
||||
rules:
|
||||
@@ -16,6 +17,11 @@ linter:
|
||||
directives_ordering: true
|
||||
package_api_docs: true
|
||||
package_prefixed_library_names: true
|
||||
prefer_final_in_for_each: true
|
||||
prefer_single_quotes: true
|
||||
test_types_in_equals: true
|
||||
throw_in_finally: true
|
||||
unawaited_futures: true
|
||||
unnecessary_statements: true
|
||||
use_enums: true
|
||||
use_super_parameters: true
|
||||
|
||||
@@ -14,11 +14,11 @@ import 'package:webdriver/io.dart';
|
||||
class CookbookScraper {
|
||||
late WebDriver _driver;
|
||||
|
||||
Future init() async {
|
||||
Future<void> init() async {
|
||||
_driver = await createDriver(desired: <String, dynamic>{});
|
||||
}
|
||||
|
||||
Future dispose() async {
|
||||
Future<void> dispose() async {
|
||||
await _driver.quit();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class CookbookScraper {
|
||||
);
|
||||
}
|
||||
|
||||
Future takeScreenshot(String url) async {
|
||||
Future<void> takeScreenshot(String url) async {
|
||||
var screenshot = await _driver.captureScreenshotAsList();
|
||||
var file = File('web/${screenshotPath(url)}');
|
||||
await file.create(recursive: true);
|
||||
|
||||
@@ -11,7 +11,7 @@ class Carousel {
|
||||
final List<Element> slides = querySelectorAll('.slider-single');
|
||||
|
||||
late int currentSlideIndex;
|
||||
late int lastSlideIndex;
|
||||
late final int lastSlideIndex;
|
||||
|
||||
late Element prevSlide, currentSlide, nextSlide;
|
||||
|
||||
@@ -127,24 +127,24 @@ class Carousel {
|
||||
}
|
||||
|
||||
void _checkRepeat() {
|
||||
var prevArrow = querySelector('.slider-left');
|
||||
var nextArrow = querySelector('.slider-right');
|
||||
var prevArrow = querySelector('.slider-left') as AnchorElement;
|
||||
var nextArrow = querySelector('.slider-right') as AnchorElement;
|
||||
|
||||
if (currentSlideIndex == slides.length - 1) {
|
||||
slides[0].classes.add('hidden');
|
||||
slides[slides.length - 1].classes.remove('hidden');
|
||||
prevArrow!.classes.remove('hidden');
|
||||
nextArrow!.classes.add('hidden');
|
||||
prevArrow.classes.remove('hidden');
|
||||
nextArrow.classes.add('hidden');
|
||||
} else if (currentSlideIndex == 0) {
|
||||
slides[slides.length - 1].classes.add('hidden');
|
||||
slides[0].classes.remove('hidden');
|
||||
prevArrow!.classes.add('hidden');
|
||||
nextArrow!.classes.remove('hidden');
|
||||
prevArrow.classes.add('hidden');
|
||||
nextArrow.classes.remove('hidden');
|
||||
} else {
|
||||
slides[slides.length - 1].classes.remove('hidden');
|
||||
slides[0].classes.remove('hidden');
|
||||
prevArrow!.classes.remove('hidden');
|
||||
nextArrow!.classes.remove('hidden');
|
||||
prevArrow.classes.remove('hidden');
|
||||
nextArrow.classes.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class Index {
|
||||
|
||||
Index(this.samples);
|
||||
|
||||
factory Index.fromJson(Map json) => _$IndexFromJson(json);
|
||||
factory Index.fromJson(Map<dynamic, dynamic> json) => _$IndexFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$IndexToJson(this);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class Sample {
|
||||
this.channel,
|
||||
});
|
||||
|
||||
factory Sample.fromJson(Map json) => _$SampleFromJson(json);
|
||||
factory Sample.fromJson(Map<dynamic, dynamic> json) => _$SampleFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$SampleToJson(this);
|
||||
|
||||
@@ -116,25 +116,25 @@ class Sample {
|
||||
buf.write(name.toLowerCase());
|
||||
buf.write(' ');
|
||||
|
||||
for (var tag in tags) {
|
||||
for (final tag in tags) {
|
||||
buf.write('tag:${tag.toLowerCase()} ');
|
||||
|
||||
// Allow tags to be searched without the tag: prefix
|
||||
buf.write('${tag.toLowerCase()} ');
|
||||
}
|
||||
|
||||
for (var platform in platforms) {
|
||||
for (final platform in platforms) {
|
||||
buf.write('platform:$platform ');
|
||||
|
||||
// Allow platforms to be searched without the tag: prefix
|
||||
buf.write('$platform ');
|
||||
}
|
||||
|
||||
for (var widget in widgets) {
|
||||
for (final widget in widgets) {
|
||||
buf.write('widget:$widget ');
|
||||
}
|
||||
|
||||
for (var package in packages) {
|
||||
for (final package in packages) {
|
||||
buf.write('package:$package ');
|
||||
}
|
||||
|
||||
@@ -167,7 +167,8 @@ class Screenshot {
|
||||
|
||||
Screenshot(this.url, this.alt);
|
||||
|
||||
factory Screenshot.fromJson(Map json) => _$ScreenshotFromJson(json);
|
||||
factory Screenshot.fromJson(Map<dynamic, dynamic> json) =>
|
||||
_$ScreenshotFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ScreenshotToJson(this);
|
||||
}
|
||||
@@ -180,7 +181,7 @@ class Link {
|
||||
|
||||
Link(this.text, this.href);
|
||||
|
||||
factory Link.fromJson(Map json) => _$LinkFromJson(json);
|
||||
factory Link.fromJson(Map<dynamic, dynamic> json) => _$LinkFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$LinkToJson(this);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ bool matchesQuery(String query, String sampleAttributes) {
|
||||
// This will check whether a type parameter is present in the
|
||||
// search query, and return false if the self type mismatches
|
||||
// the query type
|
||||
for (var word in queryWords) {
|
||||
for (final word in queryWords) {
|
||||
if ((word.contains('type:') && !attributes.contains(word)) ||
|
||||
(word.contains('platform:') && !attributes.contains('type:demo'))) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ bool matchesQuery(String query, String sampleAttributes) {
|
||||
|
||||
// Test for exact matches for keywords
|
||||
var matches = 0;
|
||||
for (var word in queryWords) {
|
||||
for (final word in queryWords) {
|
||||
if (attributes.contains(word)) {
|
||||
matches++;
|
||||
}
|
||||
@@ -43,8 +43,8 @@ bool matchesQuery(String query, String sampleAttributes) {
|
||||
// e.g. searching "kitten tag:cats" is a match for a sample with the
|
||||
// attributes "kittens tag:cats"
|
||||
matches = 0;
|
||||
for (var attribute in attributes) {
|
||||
for (var queryWord in queryWords) {
|
||||
for (final attribute in attributes) {
|
||||
for (final queryWord in queryWords) {
|
||||
if (attribute.startsWith(queryWord)) {
|
||||
matches++;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ $_footer
|
||||
</html>
|
||||
''';
|
||||
|
||||
String _indexHeader = '''
|
||||
const String _indexHeader = '''
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Flutter samples</title>
|
||||
@@ -39,11 +39,11 @@ String _indexHeader = '''
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="packages/mdc_web/material-components-web.min.js"></script>
|
||||
<script defer src="main.dart.js"></script>
|
||||
${_googleAnalytics()}
|
||||
$_googleAnalytics
|
||||
</head>
|
||||
''';
|
||||
|
||||
String _descriptionHeader = '''
|
||||
const String _descriptionHeader = '''
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Flutter samples</title>
|
||||
@@ -54,11 +54,11 @@ String _descriptionHeader = '''
|
||||
<script src="packages/mdc_web/material-components-web.min.js"></script>
|
||||
<script src="https://kit.fontawesome.com/16cc04762e.js"></script>
|
||||
<script defer src="description.dart.js"></script>
|
||||
${_googleAnalytics()}
|
||||
$_googleAnalytics
|
||||
</head>
|
||||
''';
|
||||
|
||||
String _navbar = '''
|
||||
const String _navbar = '''
|
||||
<div class="navbar">
|
||||
<a class="leading" href="./">
|
||||
<img src="images/logos/logo_lockup_flutter_horizontal_wht_96.png" />
|
||||
@@ -189,9 +189,10 @@ String _descriptionPage(Sample sample) => '''
|
||||
|
||||
String _descriptionButtons(Sample sample) {
|
||||
var buf = StringBuffer();
|
||||
if (sample.web?.isNotEmpty == true) {
|
||||
var sampleLink = sample.web;
|
||||
if (sampleLink != null && sampleLink.isNotEmpty) {
|
||||
buf.write(
|
||||
'''<button class="mdc-button mdc-button--outlined" onclick="window.location.href = '${sample.web}';"><span class="mdc-button__ripple"></span> Launch App</button>''');
|
||||
'''<button class="mdc-button mdc-button--outlined" onclick="window.location.href = '$sampleLink';"><span class="mdc-button__ripple"></span> Launch App</button>''');
|
||||
}
|
||||
|
||||
if (sample.type == 'app' ||
|
||||
@@ -214,7 +215,7 @@ String _descriptionButtons(Sample sample) {
|
||||
|
||||
String _tags(Sample sample) {
|
||||
var buf = StringBuffer();
|
||||
for (var tag in sample.tags) {
|
||||
for (final tag in sample.tags) {
|
||||
buf.write('<a href="./#?search=tag%3A$tag">$tag</a>\n');
|
||||
}
|
||||
return buf.toString();
|
||||
@@ -222,7 +223,7 @@ String _tags(Sample sample) {
|
||||
|
||||
String _descriptionScreenshots(Sample sample) {
|
||||
var buf = StringBuffer();
|
||||
for (var screenshot in sample.screenshots) {
|
||||
for (final screenshot in sample.screenshots) {
|
||||
buf.write(
|
||||
'''<div class="slider-single"><img class="slider-single-image" src="${screenshot.url}" alt="${screenshot.alt}" /></div>\n''');
|
||||
}
|
||||
@@ -233,8 +234,7 @@ String _descriptionText(Sample sample) {
|
||||
return '<p>${sample.description}</p>';
|
||||
}
|
||||
|
||||
String _googleAnalytics() {
|
||||
return """
|
||||
const String _googleAnalytics = """
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-67589403-8"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
@@ -242,4 +242,3 @@ String _googleAnalytics() {
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-67589403-8');
|
||||
</script>""";
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
name: samples_index
|
||||
description: A visual index of Flutter samples
|
||||
homepage: https://github.com/flutter/samples_index
|
||||
homepage: https://github.com/flutter/samples/tree/main/web/samples_index
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
json_annotation: ^4.0.1
|
||||
path: ^1.6.0
|
||||
yaml: ^3.0.0
|
||||
json_annotation: ^4.7.0
|
||||
path: ^1.8.0
|
||||
yaml: ^3.1.0
|
||||
mdc_web: ^0.6.0
|
||||
# ^2.1.5 is no longer compatible with our overridden sass version
|
||||
# https://github.com/flutter/samples/issues/1472
|
||||
@@ -15,15 +17,17 @@ dependencies:
|
||||
checked_yaml: ^2.0.1
|
||||
webdriver: ^3.0.0
|
||||
html: ^0.15.0
|
||||
|
||||
dev_dependencies:
|
||||
grinder: ^0.9.0
|
||||
flutter_lints: ^2.0.1
|
||||
test: ^1.17.10
|
||||
json_serializable: ^6.1.5
|
||||
build: ^2.0.3
|
||||
build_runner: ^2.0.6
|
||||
build_web_compilers: ^3.0.0
|
||||
image: ^3.0.2
|
||||
test: ^1.12.0
|
||||
json_serializable: ^6.5.0
|
||||
build: ^2.3.0
|
||||
build_runner: ^2.3.0
|
||||
build_web_compilers: ^3.2.0
|
||||
image: ^3.2.0
|
||||
|
||||
# waiting for the next material-components-web release.
|
||||
# Once released, it will need to be rolled into package:mdc_web.
|
||||
#
|
||||
|
||||
@@ -48,8 +48,8 @@ Future<void> generate() async {
|
||||
var outputFile = File('web/index.html');
|
||||
await outputFile.create(recursive: true);
|
||||
await outputFile.writeAsString(templates.index(samples));
|
||||
var futures = <Future>[];
|
||||
for (var sample in samples) {
|
||||
var futures = <Future<void>>[];
|
||||
for (final sample in samples) {
|
||||
var file = File('web/${sample.filename}.html');
|
||||
var future = file.create(recursive: true).then((_) async {
|
||||
await file.writeAsString(templates.description(sample));
|
||||
@@ -71,7 +71,7 @@ Future<void> scrapeCookbook() async {
|
||||
var links = await scraper.fetchCookbookLinks();
|
||||
log('Scraping ${links.length} cookbook articles');
|
||||
var allSamples = <Sample>[];
|
||||
for (var link in links) {
|
||||
for (final link in links) {
|
||||
allSamples.add(await scraper.getMetadata(link));
|
||||
await scraper.takeScreenshot(link);
|
||||
}
|
||||
@@ -95,9 +95,9 @@ Future<void> createThumbnails() async {
|
||||
// Creates a thumbnail image for each png file
|
||||
Future<void> _createThumbnails(Directory directory) async {
|
||||
var files = await directory.list().toList();
|
||||
var filesToWrite = <Future>{};
|
||||
var filesToWrite = <Future<void>>{};
|
||||
|
||||
for (var entity in files) {
|
||||
for (final entity in files) {
|
||||
var extension = path.extension(entity.path);
|
||||
var filename = path.basenameWithoutExtension(entity.path);
|
||||
if (extension != '.png' || entity is! File || filename.endsWith('_thumb')) {
|
||||
@@ -117,8 +117,8 @@ Future<void> _createThumbnails(Directory directory) async {
|
||||
|
||||
@Task('remove generated HTML files')
|
||||
Future<void> clean() async {
|
||||
var tasks = <Future>[];
|
||||
await for (var file in Directory('web').list(recursive: true)) {
|
||||
var tasks = <Future<void>>[];
|
||||
await for (final file in Directory('web').list(recursive: true)) {
|
||||
if (path.extension(file.path) == '.html') {
|
||||
tasks.add(file.delete());
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ void filterCards() {
|
||||
|
||||
// Filter out all elements with non-matching search-attrs
|
||||
var elements = querySelectorAll('[search-attrs]');
|
||||
for (var element in elements) {
|
||||
for (final element in elements) {
|
||||
var searchAttributes = element.attributes['search-attrs'];
|
||||
if (matchesQuery(searchQuery, searchAttributes!)) {
|
||||
element.hidden = false;
|
||||
|
||||
@@ -423,7 +423,7 @@ a {
|
||||
margin-right: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
height: 8px;
|
||||
|
||||
Reference in New Issue
Block a user