Minor sample index cleanup (#1532)

pull/1535/head
Parker Lougheed 2 years ago committed by GitHub
parent 7e11b89445
commit 9a82e003ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

@ -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;

Loading…
Cancel
Save