From 52c53dcce3fc8b5c4d7d9c3c56ae568871b4aa79 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 8 Sep 2026 16:22:55 -0500 Subject: [PATCH 1/5] Update Google Fonts Lite --- packages/google_fonts/CHANGELOG.md | 3 + packages/google_fonts/README.md | 26 +++++- .../example/lib/readme_excerpts.dart | 16 ++++ .../google_fonts/generator/google_fonts.tmpl | 2 +- .../generator/google_fonts_lite.tmpl | 91 +++++++++++++++++++ packages/google_fonts/lib/google_fonts.dart | 2 +- .../google_fonts/lib/google_fonts_lite.dart | 2 +- .../lib/src/google_fonts_all_parts.dart | 2 +- .../lib/src/google_fonts_base.dart | 6 +- .../lib/src/google_fonts_config.dart | 5 + .../lib/src/google_fonts_lite.dart | 91 +++++++++++++++++++ packages/google_fonts/pubspec.yaml | 1 + .../test/google_fonts_lite_test.dart | 82 +++++++++++++++++ 13 files changed, 320 insertions(+), 9 deletions(-) diff --git a/packages/google_fonts/CHANGELOG.md b/packages/google_fonts/CHANGELOG.md index 02db16a9be28..885babb89f94 100644 --- a/packages/google_fonts/CHANGELOG.md +++ b/packages/google_fonts/CHANGELOG.md @@ -1,5 +1,8 @@ ## NEXT +- Adds `config`, `pendingFonts`, and `getTextTheme` to `GoogleFontsLite`. +- Decouples internal base library from the main entry point to ensure complete tree-shakability. +- Adds code samples and documentation for `GoogleFontsLite`. - Adds the `GoogleFontsLite` class to allow tree-shaking unused font code. - Added fonts: - `Akt` diff --git a/packages/google_fonts/README.md b/packages/google_fonts/README.md index 96da05fa81e5..5758afc0ec89 100644 --- a/packages/google_fonts/README.md +++ b/packages/google_fonts/README.md @@ -115,10 +115,32 @@ return MaterialApp( ``` ### Lower build size -The `GoogleFontsLite` class is a replacement for the `GoogleFonts` class containing only a map of all fonts and the `getFont` function. Using *only* `GoogleFontsLite` allows the Dart compiler to tree-shake most of the package's code, yielding a significant reduction in build size. +The `GoogleFontsLite` class is an alternative entry point containing only a map of all fonts and dynamic font resolution methods. Using *only* `GoogleFontsLite` allows the Dart compiler to tree-shake all unused font methods, yielding a significant reduction in build size. + +To allow the Dart compiler to tree-shake unused fonts, import `package:google_fonts/google_fonts_lite.dart` instead of `package:google_fonts/google_fonts.dart`. + +Do not import `package:google_fonts/google_fonts.dart` when optimizing for bundle size, as that imports the generated static font methods. + + +```dart +Widget liteExamples(BuildContext context) { + return Column( + children: [ + // Single text style: + Text('Dynamic font with minimal bundle size', style: GoogleFontsLite.getFont('Lato')), + // Custom text theme: + Theme( + data: ThemeData(textTheme: GoogleFontsLite.getTextTheme('Lato')), + child: const Text('Themed text'), + ), + ], + ); +} +``` + ### Visual font swapping -To avoid visual font swaps that occur when a font is loading, use [FutureBuilder](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html) and [GoogleFonts.pendingFonts()](https://pub.dev/documentation/google_fonts/latest/google_fonts/GoogleFonts/pendingFonts.html). +To avoid visual font swaps that occur when a font is loading, use [FutureBuilder](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html) and [GoogleFonts.pendingFonts()](https://pub.dev/documentation/google_fonts/latest/google_fonts/GoogleFonts/pendingFonts.html) (or `GoogleFontsLite.pendingFonts()`). See the [example app](https://pub.dev/packages/google_fonts/example). diff --git a/packages/google_fonts/example/lib/readme_excerpts.dart b/packages/google_fonts/example/lib/readme_excerpts.dart index 49b0b6887175..7c146386f7ed 100644 --- a/packages/google_fonts/example/lib/readme_excerpts.dart +++ b/packages/google_fonts/example/lib/readme_excerpts.dart @@ -126,3 +126,19 @@ void main() { } // #enddocregion LicenseRegistration + +// #docregion GoogleFontsLite +Widget liteExamples(BuildContext context) { + return Column( + children: [ + // Single text style: + Text('Dynamic font with minimal bundle size', style: GoogleFontsLite.getFont('Lato')), + // Custom text theme: + Theme( + data: ThemeData(textTheme: GoogleFontsLite.getTextTheme('Lato')), + child: const Text('Themed text'), + ), + ], + ); +} +// #enddocregion GoogleFontsLite diff --git a/packages/google_fonts/generator/google_fonts.tmpl b/packages/google_fonts/generator/google_fonts.tmpl index 43821c728ed2..6b4fe20e55c6 100755 --- a/packages/google_fonts/generator/google_fonts.tmpl +++ b/packages/google_fonts/generator/google_fonts.tmpl @@ -34,7 +34,7 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` - static final GoogleFontsConfig config = GoogleFontsConfig(); + static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished /// loading and are ready to be rendered on screen. diff --git a/packages/google_fonts/generator/google_fonts_lite.tmpl b/packages/google_fonts/generator/google_fonts_lite.tmpl index 8c5d3a5086d9..e1ad6c2f8222 100644 --- a/packages/google_fonts/generator/google_fonts_lite.tmpl +++ b/packages/google_fonts/generator/google_fonts_lite.tmpl @@ -9,6 +9,7 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'google_fonts_base.dart'; +import 'google_fonts_config.dart'; import 'google_fonts_descriptor.dart'; import 'google_fonts_variant.dart'; @@ -18,6 +19,63 @@ import 'google_fonts_variant.dart'; /// each font, [GoogleFontsLite] provides dynamic font lookup via [getFont] /// and [fontsMap], allowing unused font methods to be tree-shaken by the compiler. abstract final class GoogleFontsLite { + /// Configuration for the [GoogleFontsLite] library. + /// + /// ```dart + /// GoogleFontsLite.config.allowRuntimeFetching = false; + /// ``` + static final GoogleFontsConfig config = sharedGoogleFontsConfig; + + /// Returns a [Future] which resolves when requested fonts have finished + /// loading and are ready to be rendered on screen. + /// + /// Usage: + /// ```dart + /// GoogleFontsLite.getFont('Lato'); + /// GoogleFontsLite.getTextTheme('Pacifico'); + /// await GoogleFontsLite.pendingFonts(); // <-- waits until Lato and Pacifico files have loaded. + /// ``` + /// + /// To keep things tidy, one can also pass in requested fonts as a list + /// to [pendingFonts]. + /// + /// ```dart + /// await GoogleFontsLite.pendingFonts([ + /// GoogleFontsLite.getFont('Lato'), + /// GoogleFontsLite.getTextTheme('Pacifico'), + /// ]); + /// ``` + /// + /// To avoid visual font swaps that occur when a font is loading, + /// consider using [FutureBuilder]. Note: This future cannot be created in + /// [build], as described in [FutureBuilder]'s documentation. + /// + /// ```dart + /// late Future> googleFontsPending; + /// + /// @override + /// void initState() { + /// super.initState(); + /// googleFontsPending = GoogleFontsLite.pendingFonts([ + /// GoogleFontsLite.getFont('Lato'), + /// ]); + /// } + /// + /// @override + /// Widget build(BuildContext context) { + /// return FutureBuilder( + /// future: googleFontsPending, + /// builder: (context, snapshot) { + /// if (snapshot.connectionState != ConnectionState.done) { + /// return const SizedBox(); + /// } + /// return Text('Lato text', style: GoogleFontsLite.getFont('Lato')); + /// }, + /// ); + /// } + /// ``` + static Future> pendingFonts([List? _]) => Future.wait(pendingFontFutures); + /// Map of all available Google Fonts families to their variant file descriptors. static final Map> fontsMap = { {{#fontEntries}} @@ -86,4 +144,37 @@ abstract final class GoogleFontsLite { decorationThickness: decorationThickness, ); } + + /// Retrieve a text theme by its font family name. + /// + /// Applies the given font family from Google Fonts to the given [textTheme] + /// and returns the resulting [textTheme]. + /// + /// Note: [fontFamily] is case-sensitive. + /// + /// Parameter [fontFamily] must not be `null`. Throws if no font by name + /// [fontFamily] exists. + static TextTheme getTextTheme(String fontFamily, [TextTheme? textTheme]) { + if (!fontsMap.containsKey(fontFamily)) { + throw Exception("No font family by name '$fontFamily' was found."); + } + textTheme ??= ThemeData.light().textTheme; + return TextTheme( + displayLarge: getFont(fontFamily, textStyle: textTheme.displayLarge), + displayMedium: getFont(fontFamily, textStyle: textTheme.displayMedium), + displaySmall: getFont(fontFamily, textStyle: textTheme.displaySmall), + headlineLarge: getFont(fontFamily, textStyle: textTheme.headlineLarge), + headlineMedium: getFont(fontFamily, textStyle: textTheme.headlineMedium), + headlineSmall: getFont(fontFamily, textStyle: textTheme.headlineSmall), + titleLarge: getFont(fontFamily, textStyle: textTheme.titleLarge), + titleMedium: getFont(fontFamily, textStyle: textTheme.titleMedium), + titleSmall: getFont(fontFamily, textStyle: textTheme.titleSmall), + bodyLarge: getFont(fontFamily, textStyle: textTheme.bodyLarge), + bodyMedium: getFont(fontFamily, textStyle: textTheme.bodyMedium), + bodySmall: getFont(fontFamily, textStyle: textTheme.bodySmall), + labelLarge: getFont(fontFamily, textStyle: textTheme.labelLarge), + labelMedium: getFont(fontFamily, textStyle: textTheme.labelMedium), + labelSmall: getFont(fontFamily, textStyle: textTheme.labelSmall), + ); + } } diff --git a/packages/google_fonts/lib/google_fonts.dart b/packages/google_fonts/lib/google_fonts.dart index e7b82aa7f87f..f51aace1f085 100644 --- a/packages/google_fonts/lib/google_fonts.dart +++ b/packages/google_fonts/lib/google_fonts.dart @@ -3,5 +3,5 @@ // found in the LICENSE file. export 'src/google_fonts_all_parts.dart'; -export 'src/google_fonts_config.dart'; +export 'src/google_fonts_config.dart' show Config, GoogleFontsConfig; export 'src/google_fonts_lite.dart'; diff --git a/packages/google_fonts/lib/google_fonts_lite.dart b/packages/google_fonts/lib/google_fonts_lite.dart index 8991731f8d32..fa12fd27e450 100644 --- a/packages/google_fonts/lib/google_fonts_lite.dart +++ b/packages/google_fonts/lib/google_fonts_lite.dart @@ -2,5 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -export 'src/google_fonts_config.dart'; +export 'src/google_fonts_config.dart' show Config, GoogleFontsConfig; export 'src/google_fonts_lite.dart'; diff --git a/packages/google_fonts/lib/src/google_fonts_all_parts.dart b/packages/google_fonts/lib/src/google_fonts_all_parts.dart index 73c48ae08e0a..64b4894c7409 100644 --- a/packages/google_fonts/lib/src/google_fonts_all_parts.dart +++ b/packages/google_fonts/lib/src/google_fonts_all_parts.dart @@ -57,7 +57,7 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` - static final GoogleFontsConfig config = GoogleFontsConfig(); + static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished /// loading and are ready to be rendered on screen. diff --git a/packages/google_fonts/lib/src/google_fonts_base.dart b/packages/google_fonts/lib/src/google_fonts_base.dart index b68795340514..3210e71d2f46 100755 --- a/packages/google_fonts/lib/src/google_fonts_base.dart +++ b/packages/google_fonts/lib/src/google_fonts_base.dart @@ -8,11 +8,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; -import '../google_fonts.dart'; import 'file_io.dart' // Stubbed implementation by default. // Concrete implementation if File IO is available. if (dart.library.io) 'file_io_desktop_and_mobile.dart' as file_io; +import 'google_fonts_config.dart'; import 'google_fonts_descriptor.dart'; import 'google_fonts_family_with_variant.dart'; import 'google_fonts_variant.dart'; @@ -164,7 +164,7 @@ Future loadFontIfNecessary(GoogleFontsDescriptor descriptor) async { } // Attempt to load this font via http, unless disallowed. - if (GoogleFonts.config.allowRuntimeFetching) { + if (sharedGoogleFontsConfig.allowRuntimeFetching) { byteData = _httpFetchFontAndSaveToDevice(familyWithVariantString, descriptor.file); if (await byteData != null) { return await loadFontByteData(familyWithVariantString, byteData); @@ -250,7 +250,7 @@ Future _httpFetchFontAndSaveToDevice(String fontName, GoogleFontsFile } http.Response response; - final http.Client client = GoogleFonts.config.httpClient ?? _httpClient; + final http.Client client = sharedGoogleFontsConfig.httpClient ?? _httpClient; try { response = await client.get(uri); } catch (e) { diff --git a/packages/google_fonts/lib/src/google_fonts_config.dart b/packages/google_fonts/lib/src/google_fonts_config.dart index c7aff7d7a77c..25250e7a7d5f 100644 --- a/packages/google_fonts/lib/src/google_fonts_config.dart +++ b/packages/google_fonts/lib/src/google_fonts_config.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:http/http.dart' as http; +import 'package:meta/meta.dart'; /// A collection of properties used to specify custom behavior of the /// GoogleFonts library. @@ -22,3 +23,7 @@ class GoogleFontsConfig { /// Deprecated. Use [GoogleFontsConfig] instead. @Deprecated('Use GoogleFontsConfig instead') typedef Config = GoogleFontsConfig; + +/// Shared configuration instance for the Google Fonts library. +@internal +final GoogleFontsConfig sharedGoogleFontsConfig = GoogleFontsConfig(); diff --git a/packages/google_fonts/lib/src/google_fonts_lite.dart b/packages/google_fonts/lib/src/google_fonts_lite.dart index d98e040eb7cf..baa0cfc6cf5c 100644 --- a/packages/google_fonts/lib/src/google_fonts_lite.dart +++ b/packages/google_fonts/lib/src/google_fonts_lite.dart @@ -9,6 +9,7 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'google_fonts_base.dart'; +import 'google_fonts_config.dart'; import 'google_fonts_descriptor.dart'; import 'google_fonts_variant.dart'; @@ -18,6 +19,63 @@ import 'google_fonts_variant.dart'; /// each font, [GoogleFontsLite] provides dynamic font lookup via [getFont] /// and [fontsMap], allowing unused font methods to be tree-shaken by the compiler. abstract final class GoogleFontsLite { + /// Configuration for the [GoogleFontsLite] library. + /// + /// ```dart + /// GoogleFontsLite.config.allowRuntimeFetching = false; + /// ``` + static final GoogleFontsConfig config = sharedGoogleFontsConfig; + + /// Returns a [Future] which resolves when requested fonts have finished + /// loading and are ready to be rendered on screen. + /// + /// Usage: + /// ```dart + /// GoogleFontsLite.getFont('Lato'); + /// GoogleFontsLite.getTextTheme('Pacifico'); + /// await GoogleFontsLite.pendingFonts(); // <-- waits until Lato and Pacifico files have loaded. + /// ``` + /// + /// To keep things tidy, one can also pass in requested fonts as a list + /// to [pendingFonts]. + /// + /// ```dart + /// await GoogleFontsLite.pendingFonts([ + /// GoogleFontsLite.getFont('Lato'), + /// GoogleFontsLite.getTextTheme('Pacifico'), + /// ]); + /// ``` + /// + /// To avoid visual font swaps that occur when a font is loading, + /// consider using [FutureBuilder]. Note: This future cannot be created in + /// [build], as described in [FutureBuilder]'s documentation. + /// + /// ```dart + /// late Future> googleFontsPending; + /// + /// @override + /// void initState() { + /// super.initState(); + /// googleFontsPending = GoogleFontsLite.pendingFonts([ + /// GoogleFontsLite.getFont('Lato'), + /// ]); + /// } + /// + /// @override + /// Widget build(BuildContext context) { + /// return FutureBuilder( + /// future: googleFontsPending, + /// builder: (context, snapshot) { + /// if (snapshot.connectionState != ConnectionState.done) { + /// return const SizedBox(); + /// } + /// return Text('Lato text', style: GoogleFontsLite.getFont('Lato')); + /// }, + /// ); + /// } + /// ``` + static Future> pendingFonts([List? _]) => Future.wait(pendingFontFutures); + /// Map of all available Google Fonts families to their variant file descriptors. static final Map> fontsMap = { 'ABeeZee': { @@ -57090,4 +57148,37 @@ abstract final class GoogleFontsLite { decorationThickness: decorationThickness, ); } + + /// Retrieve a text theme by its font family name. + /// + /// Applies the given font family from Google Fonts to the given [textTheme] + /// and returns the resulting [textTheme]. + /// + /// Note: [fontFamily] is case-sensitive. + /// + /// Parameter [fontFamily] must not be `null`. Throws if no font by name + /// [fontFamily] exists. + static TextTheme getTextTheme(String fontFamily, [TextTheme? textTheme]) { + if (!fontsMap.containsKey(fontFamily)) { + throw Exception("No font family by name '$fontFamily' was found."); + } + textTheme ??= ThemeData.light().textTheme; + return TextTheme( + displayLarge: getFont(fontFamily, textStyle: textTheme.displayLarge), + displayMedium: getFont(fontFamily, textStyle: textTheme.displayMedium), + displaySmall: getFont(fontFamily, textStyle: textTheme.displaySmall), + headlineLarge: getFont(fontFamily, textStyle: textTheme.headlineLarge), + headlineMedium: getFont(fontFamily, textStyle: textTheme.headlineMedium), + headlineSmall: getFont(fontFamily, textStyle: textTheme.headlineSmall), + titleLarge: getFont(fontFamily, textStyle: textTheme.titleLarge), + titleMedium: getFont(fontFamily, textStyle: textTheme.titleMedium), + titleSmall: getFont(fontFamily, textStyle: textTheme.titleSmall), + bodyLarge: getFont(fontFamily, textStyle: textTheme.bodyLarge), + bodyMedium: getFont(fontFamily, textStyle: textTheme.bodyMedium), + bodySmall: getFont(fontFamily, textStyle: textTheme.bodySmall), + labelLarge: getFont(fontFamily, textStyle: textTheme.labelLarge), + labelMedium: getFont(fontFamily, textStyle: textTheme.labelMedium), + labelSmall: getFont(fontFamily, textStyle: textTheme.labelSmall), + ); + } } diff --git a/packages/google_fonts/pubspec.yaml b/packages/google_fonts/pubspec.yaml index 8580ea804bb7..4491df8c3f33 100644 --- a/packages/google_fonts/pubspec.yaml +++ b/packages/google_fonts/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: flutter: sdk: flutter http: ^1.0.0 + meta: ^1.10.0 path_provider: ^2.0.0 dev_dependencies: diff --git a/packages/google_fonts/test/google_fonts_lite_test.dart b/packages/google_fonts/test/google_fonts_lite_test.dart index 1a0fd10aef6c..eecc7471bd45 100644 --- a/packages/google_fonts/test/google_fonts_lite_test.dart +++ b/packages/google_fonts/test/google_fonts_lite_test.dart @@ -2,9 +2,13 @@ // 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:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:google_fonts/google_fonts_lite.dart' as lite; +import 'package:google_fonts/src/google_fonts_base.dart'; void main() { testWidgets('GoogleFontsLite getFont returns the correct font with the given parameters', ( @@ -99,4 +103,82 @@ void main() { test('GoogleFontsLite.fontsMap keys match GoogleFonts.asMap keys exactly', () { expect(GoogleFontsLite.fontsMap.keys, equals(GoogleFonts.asMap().keys)); }); + + test('GoogleFontsLite.config and GoogleFonts.config share the same instance', () { + expect(identical(GoogleFontsLite.config, GoogleFonts.config), isTrue); + addTearDown(() { + GoogleFontsLite.config.allowRuntimeFetching = true; + }); + GoogleFontsLite.config.allowRuntimeFetching = false; + expect(GoogleFonts.config.allowRuntimeFetching, isFalse); + }); + + test('GoogleFontsLite.pendingFonts awaits loaded fonts and accepts optional argument', () async { + pendingFontFutures.clear(); + expect(await GoogleFontsLite.pendingFonts(), isEmpty); + expect( + await GoogleFontsLite.pendingFonts([const TextStyle(fontFamily: 'Lato')]), + isEmpty, + ); + }); + + testWidgets('GoogleFontsLite.getTextTheme creates matching TextTheme', ( + WidgetTester tester, + ) async { + final TextTheme liteTheme = GoogleFontsLite.getTextTheme('Lato'); + final TextTheme heavyTheme = GoogleFonts.latoTextTheme(); + expect(liteTheme, equals(heavyTheme)); + }); + + testWidgets('GoogleFontsLite.getTextTheme preserves existing TextTheme properties', ( + WidgetTester tester, + ) async { + const customStyle = TextStyle(fontSize: 42.0, color: Colors.purple); + final lightTheme = ThemeData.light(); + final TextTheme customBaseTheme = lightTheme.textTheme.copyWith(displayLarge: customStyle); + final TextTheme resultTheme = GoogleFontsLite.getTextTheme('Lato', customBaseTheme); + expect(resultTheme.displayLarge?.fontSize, equals(42.0)); + expect(resultTheme.displayLarge?.color, equals(Colors.purple)); + expect(resultTheme.displayLarge?.fontFamily, contains('Lato')); + }); + + test('GoogleFontsLite.getTextTheme throws on unknown font family', () { + expect( + () => GoogleFontsLite.getTextTheme('NonExistentFamily'), + throwsA( + isA().having( + (Exception e) => e.toString(), + 'message', + contains("No font family by name 'NonExistentFamily' was found."), + ), + ), + ); + }); + + test('google_fonts_lite.dart entrypoint exports expected public symbols', () { + expect(lite.GoogleFontsLite.fontsMap, isNotEmpty); + expect(lite.GoogleFontsLite.config, isA()); + expect(lite.GoogleFontsLite.config, isA()); + }); + + test('lib/google_fonts_lite.dart does not transitively import part files', () { + final String liteEntryContent = File('lib/google_fonts_lite.dart').readAsStringSync(); + expect(liteEntryContent.contains('google_fonts.dart'), isFalse); + expect(liteEntryContent.contains('google_fonts_all_parts.dart'), isFalse); + + final String liteSrcContent = File('lib/src/google_fonts_lite.dart').readAsStringSync(); + expect(liteSrcContent.contains('google_fonts.dart'), isFalse); + expect(liteSrcContent.contains('google_fonts_all_parts.dart'), isFalse); + expect(liteSrcContent.contains('google_fonts_parts/'), isFalse); + + final String baseFileContent = File('lib/src/google_fonts_base.dart').readAsStringSync(); + expect( + baseFileContent.contains("import '../google_fonts.dart'"), + isFalse, + reason: 'google_fonts_base.dart must not import google_fonts.dart to maintain tree-shaking', + ); + expect(baseFileContent.contains("import 'google_fonts_config.dart'"), isTrue); + expect(baseFileContent.contains('google_fonts_all_parts.dart'), isFalse); + expect(baseFileContent.contains('google_fonts_parts/'), isFalse); + }); } From ecb0279321ea7ae4ef0a3d95e6c30cef52489545 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 8 Sep 2026 17:42:51 -0500 Subject: [PATCH 2/5] ++ --- packages/google_fonts/generator/google_fonts.tmpl | 3 +++ packages/google_fonts/generator/google_fonts_lite.tmpl | 7 +++++++ packages/google_fonts/lib/src/google_fonts_all_parts.dart | 3 +++ packages/google_fonts/lib/src/google_fonts_config.dart | 4 ++++ packages/google_fonts/lib/src/google_fonts_lite.dart | 7 +++++++ 5 files changed, 24 insertions(+) diff --git a/packages/google_fonts/generator/google_fonts.tmpl b/packages/google_fonts/generator/google_fonts.tmpl index 6b4fe20e55c6..19cc20d966a8 100755 --- a/packages/google_fonts/generator/google_fonts.tmpl +++ b/packages/google_fonts/generator/google_fonts.tmpl @@ -34,6 +34,9 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` + /// + /// The underlying [sharedGoogleFontsConfig] is not exported or meant for + /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/generator/google_fonts_lite.tmpl b/packages/google_fonts/generator/google_fonts_lite.tmpl index e1ad6c2f8222..b53db0bba455 100644 --- a/packages/google_fonts/generator/google_fonts_lite.tmpl +++ b/packages/google_fonts/generator/google_fonts_lite.tmpl @@ -21,9 +21,16 @@ import 'google_fonts_variant.dart'; abstract final class GoogleFontsLite { /// Configuration for the [GoogleFontsLite] library. /// + /// Use this to define custom behavior of the GoogleFonts library in your app. + /// For example, if you do not want the GoogleFonts library to make any HTTP + /// requests for fonts, add the following snippet to your app's `main` method. + /// /// ```dart /// GoogleFontsLite.config.allowRuntimeFetching = false; /// ``` + /// + /// The underlying [sharedGoogleFontsConfig] is not exported or meant for + /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/lib/src/google_fonts_all_parts.dart b/packages/google_fonts/lib/src/google_fonts_all_parts.dart index 64b4894c7409..f81f5523a816 100644 --- a/packages/google_fonts/lib/src/google_fonts_all_parts.dart +++ b/packages/google_fonts/lib/src/google_fonts_all_parts.dart @@ -57,6 +57,9 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` + /// + /// The underlying [sharedGoogleFontsConfig] is not exported or meant for + /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/lib/src/google_fonts_config.dart b/packages/google_fonts/lib/src/google_fonts_config.dart index 25250e7a7d5f..2c1dfb02d55a 100644 --- a/packages/google_fonts/lib/src/google_fonts_config.dart +++ b/packages/google_fonts/lib/src/google_fonts_config.dart @@ -25,5 +25,9 @@ class GoogleFontsConfig { typedef Config = GoogleFontsConfig; /// Shared configuration instance for the Google Fonts library. +/// +/// This instance is not exported and is not meant for public consumption. +/// Applications should configure Google Fonts using `GoogleFonts.config` or +/// `GoogleFontsLite.config`. @internal final GoogleFontsConfig sharedGoogleFontsConfig = GoogleFontsConfig(); diff --git a/packages/google_fonts/lib/src/google_fonts_lite.dart b/packages/google_fonts/lib/src/google_fonts_lite.dart index baa0cfc6cf5c..707d8c2e1b7f 100644 --- a/packages/google_fonts/lib/src/google_fonts_lite.dart +++ b/packages/google_fonts/lib/src/google_fonts_lite.dart @@ -21,9 +21,16 @@ import 'google_fonts_variant.dart'; abstract final class GoogleFontsLite { /// Configuration for the [GoogleFontsLite] library. /// + /// Use this to define custom behavior of the GoogleFonts library in your app. + /// For example, if you do not want the GoogleFonts library to make any HTTP + /// requests for fonts, add the following snippet to your app's `main` method. + /// /// ```dart /// GoogleFontsLite.config.allowRuntimeFetching = false; /// ``` + /// + /// The underlying [sharedGoogleFontsConfig] is not exported or meant for + /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished From c240b2af43134f5bcb6bc00c9f7c86369e00828c Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 10 Sep 2026 16:12:58 -0500 Subject: [PATCH 3/5] Address review feedback: throw ArgumentError in GoogleFontsLite.getTextTheme --- packages/google_fonts/generator/google_fonts_lite.tmpl | 6 +++--- packages/google_fonts/lib/src/google_fonts_lite.dart | 6 +++--- packages/google_fonts/test/google_fonts_lite_test.dart | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/google_fonts/generator/google_fonts_lite.tmpl b/packages/google_fonts/generator/google_fonts_lite.tmpl index b53db0bba455..976e6f6a96e1 100644 --- a/packages/google_fonts/generator/google_fonts_lite.tmpl +++ b/packages/google_fonts/generator/google_fonts_lite.tmpl @@ -159,11 +159,11 @@ abstract final class GoogleFontsLite { /// /// Note: [fontFamily] is case-sensitive. /// - /// Parameter [fontFamily] must not be `null`. Throws if no font by name - /// [fontFamily] exists. + /// Parameter [fontFamily] must not be `null`. Throws an [ArgumentError] if no + /// font by name [fontFamily] exists. static TextTheme getTextTheme(String fontFamily, [TextTheme? textTheme]) { if (!fontsMap.containsKey(fontFamily)) { - throw Exception("No font family by name '$fontFamily' was found."); + throw ArgumentError("No font family by name '$fontFamily' was found."); } textTheme ??= ThemeData.light().textTheme; return TextTheme( diff --git a/packages/google_fonts/lib/src/google_fonts_lite.dart b/packages/google_fonts/lib/src/google_fonts_lite.dart index 707d8c2e1b7f..e6acc65eb979 100644 --- a/packages/google_fonts/lib/src/google_fonts_lite.dart +++ b/packages/google_fonts/lib/src/google_fonts_lite.dart @@ -57163,11 +57163,11 @@ abstract final class GoogleFontsLite { /// /// Note: [fontFamily] is case-sensitive. /// - /// Parameter [fontFamily] must not be `null`. Throws if no font by name - /// [fontFamily] exists. + /// Parameter [fontFamily] must not be `null`. Throws an [ArgumentError] if no + /// font by name [fontFamily] exists. static TextTheme getTextTheme(String fontFamily, [TextTheme? textTheme]) { if (!fontsMap.containsKey(fontFamily)) { - throw Exception("No font family by name '$fontFamily' was found."); + throw ArgumentError("No font family by name '$fontFamily' was found."); } textTheme ??= ThemeData.light().textTheme; return TextTheme( diff --git a/packages/google_fonts/test/google_fonts_lite_test.dart b/packages/google_fonts/test/google_fonts_lite_test.dart index eecc7471bd45..d15e5ba7d346 100644 --- a/packages/google_fonts/test/google_fonts_lite_test.dart +++ b/packages/google_fonts/test/google_fonts_lite_test.dart @@ -146,8 +146,8 @@ void main() { expect( () => GoogleFontsLite.getTextTheme('NonExistentFamily'), throwsA( - isA().having( - (Exception e) => e.toString(), + isA().having( + (ArgumentError e) => e.message, 'message', contains("No font family by name 'NonExistentFamily' was found."), ), From 3a212e3eb4dbd081a6ac32bc380a736ac0df0f78 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 10 Sep 2026 17:38:43 -0500 Subject: [PATCH 4/5] Fixes --- .../test/google_fonts_lite_test.dart | 38 ++++++++----------- .../google_fonts/test/tree_shaking_test.dart | 33 ++++++++++++++++ 2 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 packages/google_fonts/test/tree_shaking_test.dart diff --git a/packages/google_fonts/test/google_fonts_lite_test.dart b/packages/google_fonts/test/google_fonts_lite_test.dart index d15e5ba7d346..15b7645bade0 100644 --- a/packages/google_fonts/test/google_fonts_lite_test.dart +++ b/packages/google_fonts/test/google_fonts_lite_test.dart @@ -2,15 +2,28 @@ // 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:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts_lite.dart' as lite; import 'package:google_fonts/src/google_fonts_base.dart'; +import 'package:mockito/mockito.dart'; + +class MockAssetManifest extends Mock implements AssetManifest { + @override + List listAssets() => []; +} void main() { + setUpAll(() { + assetManifest = MockAssetManifest(); + }); + + tearDown(() { + clearCache(); + pendingFontFutures.clear(); + }); testWidgets('GoogleFontsLite getFont returns the correct font with the given parameters', ( WidgetTester tester, ) async { @@ -160,25 +173,4 @@ void main() { expect(lite.GoogleFontsLite.config, isA()); expect(lite.GoogleFontsLite.config, isA()); }); - - test('lib/google_fonts_lite.dart does not transitively import part files', () { - final String liteEntryContent = File('lib/google_fonts_lite.dart').readAsStringSync(); - expect(liteEntryContent.contains('google_fonts.dart'), isFalse); - expect(liteEntryContent.contains('google_fonts_all_parts.dart'), isFalse); - - final String liteSrcContent = File('lib/src/google_fonts_lite.dart').readAsStringSync(); - expect(liteSrcContent.contains('google_fonts.dart'), isFalse); - expect(liteSrcContent.contains('google_fonts_all_parts.dart'), isFalse); - expect(liteSrcContent.contains('google_fonts_parts/'), isFalse); - - final String baseFileContent = File('lib/src/google_fonts_base.dart').readAsStringSync(); - expect( - baseFileContent.contains("import '../google_fonts.dart'"), - isFalse, - reason: 'google_fonts_base.dart must not import google_fonts.dart to maintain tree-shaking', - ); - expect(baseFileContent.contains("import 'google_fonts_config.dart'"), isTrue); - expect(baseFileContent.contains('google_fonts_all_parts.dart'), isFalse); - expect(baseFileContent.contains('google_fonts_parts/'), isFalse); - }); } diff --git a/packages/google_fonts/test/tree_shaking_test.dart b/packages/google_fonts/test/tree_shaking_test.dart new file mode 100644 index 000000000000..122a964ba8c1 --- /dev/null +++ b/packages/google_fonts/test/tree_shaking_test.dart @@ -0,0 +1,33 @@ +// 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. + +@TestOn('vm') // Uses dart:io +library; + +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('lib/google_fonts_lite.dart does not transitively import part files', () { + final String liteEntryContent = File('lib/google_fonts_lite.dart').readAsStringSync(); + expect(liteEntryContent.contains('google_fonts.dart'), isFalse); + expect(liteEntryContent.contains('google_fonts_all_parts.dart'), isFalse); + + final String liteSrcContent = File('lib/src/google_fonts_lite.dart').readAsStringSync(); + expect(liteSrcContent.contains('google_fonts.dart'), isFalse); + expect(liteSrcContent.contains('google_fonts_all_parts.dart'), isFalse); + expect(liteSrcContent.contains('google_fonts_parts/'), isFalse); + + final String baseFileContent = File('lib/src/google_fonts_base.dart').readAsStringSync(); + expect( + baseFileContent.contains("import '../google_fonts.dart'"), + isFalse, + reason: 'google_fonts_base.dart must not import google_fonts.dart to maintain tree-shaking', + ); + expect(baseFileContent.contains("import 'google_fonts_config.dart'"), isTrue); + expect(baseFileContent.contains('google_fonts_all_parts.dart'), isFalse); + expect(baseFileContent.contains('google_fonts_parts/'), isFalse); + }); +} From f6d131258cb908c7a6717a2ed6f7adfe76c70a51 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 10 Sep 2026 18:26:06 -0500 Subject: [PATCH 5/5] Tidy --- packages/google_fonts/generator/google_fonts.tmpl | 3 --- packages/google_fonts/generator/google_fonts_lite.tmpl | 3 --- packages/google_fonts/lib/src/google_fonts_all_parts.dart | 3 --- packages/google_fonts/lib/src/google_fonts_lite.dart | 3 --- 4 files changed, 12 deletions(-) diff --git a/packages/google_fonts/generator/google_fonts.tmpl b/packages/google_fonts/generator/google_fonts.tmpl index 19cc20d966a8..6b4fe20e55c6 100755 --- a/packages/google_fonts/generator/google_fonts.tmpl +++ b/packages/google_fonts/generator/google_fonts.tmpl @@ -34,9 +34,6 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` - /// - /// The underlying [sharedGoogleFontsConfig] is not exported or meant for - /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/generator/google_fonts_lite.tmpl b/packages/google_fonts/generator/google_fonts_lite.tmpl index 976e6f6a96e1..0e7c1853b892 100644 --- a/packages/google_fonts/generator/google_fonts_lite.tmpl +++ b/packages/google_fonts/generator/google_fonts_lite.tmpl @@ -28,9 +28,6 @@ abstract final class GoogleFontsLite { /// ```dart /// GoogleFontsLite.config.allowRuntimeFetching = false; /// ``` - /// - /// The underlying [sharedGoogleFontsConfig] is not exported or meant for - /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/lib/src/google_fonts_all_parts.dart b/packages/google_fonts/lib/src/google_fonts_all_parts.dart index f81f5523a816..64b4894c7409 100644 --- a/packages/google_fonts/lib/src/google_fonts_all_parts.dart +++ b/packages/google_fonts/lib/src/google_fonts_all_parts.dart @@ -57,9 +57,6 @@ class GoogleFonts { /// ```dart /// GoogleFonts.config.allowRuntimeFetching = false; /// ``` - /// - /// The underlying [sharedGoogleFontsConfig] is not exported or meant for - /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished diff --git a/packages/google_fonts/lib/src/google_fonts_lite.dart b/packages/google_fonts/lib/src/google_fonts_lite.dart index e6acc65eb979..018337fcf219 100644 --- a/packages/google_fonts/lib/src/google_fonts_lite.dart +++ b/packages/google_fonts/lib/src/google_fonts_lite.dart @@ -28,9 +28,6 @@ abstract final class GoogleFontsLite { /// ```dart /// GoogleFontsLite.config.allowRuntimeFetching = false; /// ``` - /// - /// The underlying [sharedGoogleFontsConfig] is not exported or meant for - /// public consumption. static final GoogleFontsConfig config = sharedGoogleFontsConfig; /// Returns a [Future] which resolves when requested fonts have finished