Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/material_ui/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ environment:

workspace:
- example
- tool/m3e_gen_defaults

dependencies:
cupertino_ui:
Expand Down
24 changes: 24 additions & 0 deletions packages/material_ui/tool/m3e_gen_defaults/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Token Defaults Generator

Script that generates component theme data defaults based on token data.

## Usage
Run this program from the root of the git repository:
```sh
dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v]
```

This updates generated component theming files under
`packages/material_ui/lib/src/m3e/generated`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new folder for m3e should not contain abbreviation based on the style guide.

Suggested change
`packages/material_ui/lib/src/m3e/generated`.
`packages/material_ui/lib/src/material_3_expressive/generated`.


## Templates

There is a template file for every component that needs defaults from the token
database. These templates are implemented as subclasses of `TokenTemplate`.

Templates need to override the `generateContents` method to provide the
generated code block as a string.

## Tokens

Tokens are stored in `data/`, and are sourced from an internal Google database.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include: ../../../../analysis_options.yaml

formatter:
page_width: 100
28 changes: 28 additions & 0 deletions packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ## Usage
//
// Run from the root of flutter/packages:
//
// ```
// dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v]
// ```

import 'package:args/args.dart';

// TODO(elliette): Import template files.
// import '../templates/x_template.dart';

Future<void> main(List<String> args) async {
// Parse arguments
final parser = ArgParser();
parser.addFlag('verbose', abbr: 'v', help: 'Enable verbose output', negatable: false);
final ArgResults argResults = parser.parse(args);
// TODO(elliette): Add token logger when verbose flag is used.
// ignore: unused_local_variable
final verbose = argResults['verbose'] as bool;
// TODO(elliette): Invoke template generators.
// const XTemplate().generateFile(verbose: verbose);
}
15 changes: 15 additions & 0 deletions packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: gen_defaults
description: A command line script to generate Material component defaults from the token database.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also make it not publishable? like material_ui/example.

Suggested change
description: A command line script to generate Material component defaults from the token database.
description: A command line script to generate Material component defaults from the token database.
publish_to: none

version: 1.0.0

environment:
sdk: ^3.10.0-0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not familiar with how to constrain the version. In packages/material_ui/pubspec.yaml, it shows sdk: ^3.9.0, do we need to match it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh but seems material_ui/example also use sdk: ^3.10.0-0


resolution: workspace
Comment thread
elliette marked this conversation as resolved.

dependencies:
args: any

dev_dependencies:
path: any
test: any
78 changes: 78 additions & 0 deletions packages/material_ui/tool/m3e_gen_defaults/templates/template.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2013 The Flutter Authors
// 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();

/// The name of the template, which corresponds to the target file name.
/// E.g., 'typography' for generating 'typography_defaults.g.dart'.
String get name;

static const String copyrightHeader = '''
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
''';

static const String headerComment = '''

// Do not edit by hand. The code is generated from data in the Material
// Design token database by the script:
// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart.

// dart format off
''';

static const String footerComment = '''
// dart format on
''';

String generateContents();

void generateFile({bool verbose = false}) {
final fileName = '$materialLib/${name}_defaults.g.dart';
if (verbose) {
stdout.writeln('Generating file: $fileName');
stdout.writeln('Target parent file name: $name.dart');
}
final file = File(fileName);
if (!file.existsSync()) {
if (verbose) {
stdout.writeln('File does not exist, creating it.');
}
file.createSync(recursive: true);
}

final parentName = '$name.dart';

if (verbose) {
stdout.writeln('Generating contents...');
}
final buffer = StringBuffer();
buffer.write(copyrightHeader);
buffer.write(headerComment);
buffer.write("part of '../$parentName';\n\n");
buffer.write(generateContents());
buffer.write(footerComment);

if (verbose) {
stdout.writeln('Writing generated contents to $fileName...');
}
file.writeAsStringSync(buffer.toString());
if (verbose) {
stdout.writeln('Done generating $fileName.');
}
}

String get materialLib {
const packagePath = 'packages/material_ui';
const relativeOutputPath = 'lib/src/m3e/generated';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const relativeOutputPath = 'lib/src/m3e/generated';
const relativeOutputPath = 'lib/src/material_3_expressive/generated';

if (Directory(packagePath).existsSync()) {
return '$packagePath/$relativeOutputPath';
}
return relativeOutputPath;
}
Comment thread
elliette marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:test/test.dart';
import 'test_fixtures/button_template.dart';

void main() {
group('TokenTemplate', () {
test(
'Templates will generate a part file ending in _defaults.g.dart with correct parent reference',
() {
final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults');
try {
final template = ButtonTemplate(tempDir.path);
template.generateFile();

final file = File('${tempDir.path}/button_defaults.g.dart');
expect(file.readAsStringSync(), '''
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Do not edit by hand. The code is generated from data in the Material
// Design token database by the script:
// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart.

// dart format off
part of '../button.dart';

abstract final class _ButtonDefaults {
static const double height = 40.0;
static const double borderRadius = 8.0;
}
// dart format on
''');
} finally {
tempDir.deleteSync(recursive: true);
}
},
);

test('Templates will completely overwrite any previous code', () {
final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults');
try {
// Seed the file with pre-existing random text.
final file = File('${tempDir.path}/button_defaults.g.dart');
file.writeAsStringSync('Pre-existing random text.');

final templateNew = ButtonTemplate(tempDir.path);
templateNew.generateFile();
expect(file.readAsStringSync(), '''
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Do not edit by hand. The code is generated from data in the Material
// Design token database by the script:
// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart.

// dart format off
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should remove this and keep the format correct, even though it's just generated code. I vaguely remember this line is added when we started to use dart format and wanted to avoid updating these code that are already generated. But for expressive, maybe we can consider to allow dart format?

part of '../button.dart';

abstract final class _ButtonDefaults {
static const double height = 40.0;
static const double borderRadius = 8.0;
}
// dart format on
''');
} finally {
tempDir.deleteSync(recursive: true);
}
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../../templates/template.dart';
import 'button_token_data.dart';

class ButtonTemplate extends TokenTemplate {
ButtonTemplate(this.customMaterialLib);

final String customMaterialLib;

@override
String get name => 'button';

@override
String get materialLib => customMaterialLib;

@override
String generateContents() {
return '''
abstract final class _ButtonDefaults {
static const double height = ${TokenButton.height};
static const double borderRadius = ${TokenButton.borderRadius};
}
''';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

abstract final class TokenButton {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to match the real generated token file

Suggested change
abstract final class TokenButton {
class TokenButton {

static const double height = 40.0;
static const double borderRadius = 8.0;
}