feat(flutter): token + asset sync from web; gen_tokens.dart
shared/fabledsword.tokens.json mirrors web/src/lib/styles/tokens.json; assets/error-copy.json mirrors the web's error-code copy table; assets/svg/album-fallback.svg mirrors the web placeholder. Together these give Flutter the same visual + copy starting point as the SPA. tool/gen_tokens.dart emits lib/theme/tokens.dart from the JSON; the generated file is committed so CI can verify the JSON and the Dart file haven't drifted (gate added in Task 21). tool/sync_shared.sh mkdirs the shared/ + assets/ destinations before copying so the script works on a fresh checkout (the original plan-text shape only mkdir'd assets/svg). pubspec.yaml assets block uncommented now that the three asset paths exist on disk.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
// Reads shared/fabledsword.tokens.json and emits lib/theme/tokens.dart.
|
||||
// Run via `dart run tool/gen_tokens.dart`. The generated file is
|
||||
// committed (CI validates it matches the JSON to catch drift).
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
void main() {
|
||||
final jsonFile = File('shared/fabledsword.tokens.json');
|
||||
final tokens = jsonDecode(jsonFile.readAsStringSync()) as Map<String, dynamic>;
|
||||
final colors = (tokens['colors'] as Map).cast<String, String>();
|
||||
final radii = (tokens['radii'] as Map).cast<String, String>();
|
||||
final fonts = (tokens['fonts'] as Map).cast<String, String>();
|
||||
|
||||
final out = StringBuffer()
|
||||
..writeln('// GENERATED — do not edit. Source: shared/fabledsword.tokens.json')
|
||||
..writeln('// Run `dart run tool/gen_tokens.dart` to regenerate.')
|
||||
..writeln("import 'package:flutter/material.dart';")
|
||||
..writeln()
|
||||
..writeln('class FabledSwordTokens {');
|
||||
|
||||
colors.forEach((name, hex) {
|
||||
final value = hex.replaceFirst('#', '0xFF');
|
||||
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
||||
});
|
||||
|
||||
radii.forEach((name, px) {
|
||||
final v = px.replaceAll('px', '');
|
||||
out.writeln(' static const double radius${_pascal(name)} = $v;');
|
||||
});
|
||||
|
||||
fonts.forEach((name, family) {
|
||||
out.writeln(' static const String font${_pascal(name)} = ${jsonEncode(family)};');
|
||||
});
|
||||
|
||||
out.writeln('}');
|
||||
|
||||
File('lib/theme/tokens.dart').writeAsStringSync(out.toString());
|
||||
stdout.writeln('wrote lib/theme/tokens.dart');
|
||||
}
|
||||
|
||||
String _camel(String s) => s; // tokens are already lowerCamel-friendly
|
||||
String _pascal(String s) => s[0].toUpperCase() + s.substring(1);
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copies shared assets from web/ into flutter_client/. Run before
|
||||
# `flutter build` and as part of CI. Idempotent.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
mkdir -p shared assets/svg
|
||||
cp ../web/src/lib/styles/tokens.json shared/fabledsword.tokens.json
|
||||
cp ../web/src/lib/styles/error-copy.json assets/error-copy.json
|
||||
cp ../web/static/placeholders/album-fallback.svg assets/svg/album-fallback.svg
|
||||
|
||||
echo "shared assets synced from web/"
|
||||
Reference in New Issue
Block a user