1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright 2014 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 'dart:io';
abstract class TokenTemplate {
const TokenTemplate(this.fileName, this.tokens);
static const String beginGeneratedComment = '''
// BEGIN GENERATED TOKEN PROPERTIES
''';
static const String headerComment = '''
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
''';
static const String endGeneratedComment = '''
// END GENERATED TOKEN PROPERTIES
''';
final String fileName;
final Map<String, dynamic> tokens;
/// Replace or append the contents of the file with the text from [generate].
///
/// If the file already contains generated block at the end, it will
/// be replaced by the [generate] output. Otherwise the content will
/// just be appended to the end of the file.
Future<void> updateFile() async {
String contents = File(fileName).readAsStringSync();
final int previousGeneratedIndex = contents.indexOf(beginGeneratedComment);
if (previousGeneratedIndex != -1) {
contents = contents.substring(0, previousGeneratedIndex);
}
final StringBuffer buffer = StringBuffer(contents);
buffer.write(beginGeneratedComment);
buffer.write(headerComment);
buffer.write(generate());
buffer.write(endGeneratedComment);
File(fileName).writeAsStringSync(buffer.toString());
}
/// Provide the generated content for the template.
///
/// This abstract method needs to be implemented by subclasses
/// to provide the content that [updateFile] will append to the
/// bottom of the file.
String generate();
String color(String tokenName) {
final String tokenColor = '$tokenName.color';
final String tokenOpacity = '$tokenName.opacity';
String value = '${tokens[tokenColor]!}';
if (tokens.containsKey(tokenOpacity)) {
final String opacity = tokens[tokens[tokenOpacity]!]!.toString();
value += '.withOpacity($opacity)';
}
return value;
}
String elevation(String tokenName) {
final String elevationName = '$tokenName.elevation';
final Map<String, dynamic> elevationValue = tokens[tokens[elevationName]!]! as Map<String, dynamic>;
return elevationValue['value']!.toString();
}
String shape(String tokenName) {
// TODO(darrenaustin): handle more than just rounded rectangle shapes
final String shapeToken = tokens[tokenName]! as String;
final Map<String, dynamic> shape = tokens[shapeToken]! as Map<String, dynamic>;
final Map<String, dynamic> shapeValue = shape['value']! as Map<String, dynamic>;
return 'const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(${shapeValue['value']!})))';
}
String value(String tokenName) {
final Map<String, dynamic> value = tokens[tokenName]! as Map<String, dynamic>;
return value['value'].toString();
}
String textStyle(String tokenName) {
final String fontName = '$tokenName.font';
return tokens[fontName]!.toString();
}
}