WIP hot reloading enabled, much progress

This commit is contained in:
Nathan Anderson 2024-09-07 14:42:32 -06:00
commit 976c3d0679
17 changed files with 1342 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
.direnv/**
*.toml
*.pdf
*.jpeg
*.png
*.JPEG

3
CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
## 1.0.0
- Initial version.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
A sample command-line application with an entrypoint in `bin/`, library code
in `lib/`, and example unit test in `test/`.

12
analysis_options.yaml Normal file
View File

@ -0,0 +1,12 @@
include: package:lint/strict.yaml
# linter:
# rules:
# - camel_case_types
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
exclude:
# - path/to/excluded/files/**

47
bin/dartboard_resume.dart Normal file
View File

@ -0,0 +1,47 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dartboard_resume/render.dart';
import 'package:hotreloader/hotreloader.dart';
import 'package:logging/logging.dart' as logging;
StreamSubscription<FileSystemEvent>? fileStreamSub;
StreamSubscription<String>? stdinStreamSub;
Future<void> main(List<String> arguments) async {
const String tomlFilePath = "resume.toml";
logging.hierarchicalLoggingEnabled = true;
HotReloader.logLevel = logging.Level.INFO;
final HotReloader reloader = await HotReloader.create();
stdin.lineMode = false;
stdin.echoMode = false;
stdin.echoNewlineMode = false;
stdinStreamSub = stdin.transform(const Utf8Decoder()).transform(const LineSplitter()).listen(
(event) {
if (event == "r") {
stdout.writeln("Triggering pdf render...");
renderPdf(tomlFilePath, force: true);
}
},
);
ProcessSignal.sigint.watch().listen((_) {
stdout.writeln('SIGINT received. Exiting gracefully...');
fileStreamSub?.cancel();
stdinStreamSub?.cancel();
// Perform cleanup or other necessary actions here
reloader.stop();
exit(0); // Exit with code 0 to indicate a successful termination
});
if (FileSystemEntity.isWatchSupported) {
final fileStream = File(tomlFilePath).watch(events: FileSystemEvent.modify);
fileStreamSub = fileStream.listen((e) {
renderPdf(tomlFilePath);
});
stdout.writeln('Watching for file changes.');
} else {
renderPdf(tomlFilePath);
}
}

61
flake.lock Normal file
View File

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1719848872,
"narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

25
flake.nix Normal file
View File

@ -0,0 +1,25 @@
{
description = "Simple dart flake";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = {
flake-utils,
nixpkgs,
...
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = import nixpkgs {
inherit system;
};
in {
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
dart
];
# shellHook = ''
# export FLUTTER_ROOT
# '';
};
});
}

281
lib/dartboard_parser.dart Normal file
View File

@ -0,0 +1,281 @@
import 'dart:io';
import 'package:intl/intl.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
import 'package:toml/toml.dart';
class DartboardData {
DartboardData({
required this.fullName,
required this.phoneNumber,
required this.email,
// required this.address,
required this.imagePath,
required this.dartboardTheme,
required this.experiences,
required this.miscList,
});
factory DartboardData.fromToml(String tomlFilePath) {
final tomlData = TomlDocument.loadSync(tomlFilePath).toMap();
final List<DartboardExperience> exps = tomlData.entries
.where((e) => e.value is List && (e.value as List).firstOrNull is Map)
.map((MapEntry<String, dynamic> expsEntry) {
final String subsection = tomlData['${expsEntry.key}_name'] as String? ?? '';
final exps = (expsEntry.value as List).map((e) => e as Map<String, dynamic>).toList();
return exps.map((exp) {
final TomlLocalDate? start = exp['start'] as TomlLocalDate?;
final TomlLocalDate? end = exp['end'] as TomlLocalDate?;
return DartboardExperience(
title: exp['title'] as String,
subsection: subsection,
range: DateRange(
start: start == null ? null : DateTime(start.date.year, start.date.month),
end: end == null ? null : DateTime(end.date.year, end.date.month),
),
attributes: (exp['attributes'] as List).map((e) => DartboardText(content: e as String)).toList(),
location: exp['location'] as String?,
);
}).toList();
})
.expand((i) => i)
.toList();
return DartboardData(
fullName: tomlData['full_name'] as String,
phoneNumber: tomlData['phone_number'] as String,
email: tomlData['email'] as String,
imagePath: tomlData['image'] as String,
dartboardTheme: DartboardTheme.fromToml(tomlData),
experiences: exps,
miscList: [
DartboardList(subsection: 'Skills & Interest', content: 'Proficient in flutter and other'),
],
);
}
final String fullName;
final String phoneNumber;
final String email;
// final String address;
final String imagePath;
final DartboardTheme dartboardTheme;
final List<DartboardExperience> experiences;
final List<DartboardList> miscList;
Font get font => dartboardTheme.font;
PdfColor get primaryColor => dartboardTheme.primaryColor;
PdfColor get accentColor => dartboardTheme.accentColor;
PdfColor get backgroundColor => dartboardTheme.backgroundColor;
TextStyle get headerTextStyle =>
TextStyle(fontSize: 18, font: font, fontWeight: FontWeight.bold, color: const PdfColorGrey(0.18));
TextStyle get subheaderTextStyle => TextStyle(fontSize: 14, font: font, color: const PdfColorGrey(0.3));
TextStyle get defaultTextStyle => TextStyle(fontSize: 10, font: font, color: const PdfColorGrey(0.45));
Map<String, List<DartboardExperience>> get groupedExperiences {
final Map<String, List<DartboardExperience>> exps = {};
for (final DartboardExperience exp in experiences) {
if (!exps.containsKey(exp.subsection)) {
exps[exp.subsection] = <DartboardExperience>[];
}
exps[exp.subsection]!.add(exp);
}
return exps;
}
@override
int get hashCode {
return Object.hashAll([fullName, phoneNumber, email, imagePath, ...experiences]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
class DartboardExperience {
DartboardExperience({
required this.title,
required this.attributes,
required this.range,
required this.subsection,
this.location,
});
final String subsection;
final String title;
String? location;
final List<DartboardText> attributes;
final DateRange range;
@override
int get hashCode {
return Object.hashAll([subsection, title, ...attributes, range]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
class DateRange {
DateRange({required this.start, required this.end});
final DateTime? start;
final DateTime? end;
@override
String toString() {
final DateFormat dateFormat = DateFormat("MMM yyyy");
if (start == null && end == null) {
return '';
}
if (start == null && end != null) {
return dateFormat.format(end!);
}
if (start != null && end == null) {
return "${dateFormat.format(start!)} - Current";
}
return "${dateFormat.format(start!)} - ${dateFormat.format(end!)}";
}
@override
int get hashCode {
return Object.hashAll([start, end]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
class DartboardList {
DartboardList({required this.subsection, required this.content});
final String subsection;
final String content;
@override
int get hashCode {
return Object.hashAll([subsection, content]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
class DartboardTheme {
DartboardTheme({
required this.primaryHex,
required this.accentHex,
required this.backgroundHex,
required this.fontPath,
required this.bulletPoint,
});
factory DartboardTheme.fromToml(Map<String, dynamic> toml) => DartboardTheme(
primaryHex: (toml['theme'] as Map)['primary_hex'] as String,
accentHex: (toml['theme'] as Map)['accent_hex'] as String,
backgroundHex: (toml['theme'] as Map)['background_hex'] as String,
fontPath: (toml['theme'] as Map)['font'] as String,
bulletPoint: (toml['theme'] as Map)['bullet_point'] as String? ?? '-',
);
factory DartboardTheme.retro() => DartboardTheme(
primaryHex: "00AA00",
accentHex: "44EE66",
backgroundHex: "FFFFFF",
fontPath: "nerd.ttf",
bulletPoint: '-',
);
static const double inch = 72.0;
static const double cm = inch / 2.54;
static const double mm = inch / 25.4;
static const width = 21.0 * cm;
static const height = 29.7 * cm;
static const margin = 2.0 * cm;
final String primaryHex;
final String accentHex;
final String backgroundHex;
final String fontPath;
final String bulletPoint;
Font? _font;
PdfColor get primaryColor => PdfColor.fromHex(primaryHex);
PdfColor get accentColor => PdfColor.fromHex(accentHex);
PdfColor get backgroundColor => PdfColor.fromHex(backgroundHex);
Font get font {
_font ??= Font.ttf(File(fontPath).readAsBytesSync().buffer.asByteData());
return _font!;
}
@override
int get hashCode {
return Object.hashAll([primaryHex, accentHex, backgroundHex, fontPath, bulletPoint]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
enum DartboardTextType { normal, linkText }
typedef DartboardTextLinkData = ({String text, String? url, DartboardTextType type});
/// Automatically detects and parses strings with hypertext in a markdown format
class DartboardText {
DartboardText({required this.content});
final String content;
static final _markdownLinkRegex = RegExp(r'\[(.*?)\]\((.*?)\)');
bool get hasLinkMarkup => _markdownLinkRegex.hasMatch(content);
List<DartboardTextLinkData> toTextLinkList() {
final markdownLinkRegex = RegExp(r'\[(.*?)\]\((.*?)\)');
if (markdownLinkRegex.hasMatch(content)) {
final matches = markdownLinkRegex.allMatches(content).toList();
final List<DartboardTextLinkData> stringSections = [];
int prevStartIndex = 0;
while (matches.isNotEmpty) {
final match = matches.removeAt(0);
stringSections
.add((text: content.substring(prevStartIndex, match.start), url: null, type: DartboardTextType.normal));
stringSections.add((text: match.group(1)!, url: match.group(2), type: DartboardTextType.linkText));
prevStartIndex = match.end;
}
stringSections
.add((text: content.substring(prevStartIndex, content.length), url: null, type: DartboardTextType.normal));
return stringSections;
} else {
return [(text: content, url: null, type: DartboardTextType.normal)];
// return Text("${bulletString != null ? '$bulletString ' : ''}$content", style: style);
}
}
@override
int get hashCode {
return Object.hashAll([content]);
}
@override
bool operator ==(Object other) {
return super.hashCode == other.hashCode;
}
}
String _getSubsectionFromKey(String key) {
switch (key) {
case 'exp':
}
}

101
lib/dartboard_resume.dart Normal file
View File

@ -0,0 +1,101 @@
import 'dart:io';
import 'package:dartboard_resume/dartboard_parser.dart';
import 'package:dartboard_resume/dartboard_widgets.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
Page generatePdfPage({required DartboardData dartboardData, required int renderNs}) {
final List<Widget> groupedExperienceList = dartboardData.groupedExperiences.entries.map<Widget>(
(entry) {
final String subsection = entry.key;
final List<DartboardExperience> experiences = entry.value;
return Column(
children: [
Row(
children: [
Text(
subsection,
style: dartboardData.subheaderTextStyle
.merge(const TextStyle(fontSize: 18))
.apply(color: const PdfColorGrey(0.2)),
),
],
),
Container(height: 2, width: 200, color: const PdfColorGrey(0.7)),
...experiences.map(
(DartboardExperience exp) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(exp.title, style: dartboardData.subheaderTextStyle.apply(color: const PdfColorGrey(0.3))),
Text(
exp.range.toString(),
style: dartboardData.subheaderTextStyle.apply(color: const PdfColorGrey(0.42)),
),
],
),
...exp.attributes.map(
(a) => Text(
"${dartboardData.dartboardTheme.bulletPoint} $a",
style: dartboardData.defaultTextStyle.apply(
color: const PdfColorGrey(0.55),
),
),
),
SizedBox(height: 20),
],
),
),
DartboardFooter(dartboardData: dartboardData, renderNs: renderNs),
],
);
},
).toList();
return Page(
pageTheme: const PageTheme(pageFormat: PdfPageFormat.standard),
build: (Context context) {
return Column(
children: [
SizedBox(
height: 120,
width: double.infinity,
child: Stack(
children: [
Positioned(
left: 0,
child: Container(
height: 100,
width: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.contain,
image: MemoryImage(
File(dartboardData.imagePath).readAsBytesSync(),
),
),
),
),
),
Center(
child: Column(
children: [
Text(dartboardData.fullName, style: dartboardData.headerTextStyle),
Text(dartboardData.phoneNumber, style: dartboardData.headerTextStyle),
Text(dartboardData.email, style: dartboardData.headerTextStyle),
],
),
),
],
),
),
Container(height: 20),
...groupedExperienceList,
],
);
},
);
}

123
lib/dartboard_widgets.dart Normal file
View File

@ -0,0 +1,123 @@
import 'package:dartboard_resume/dartboard_parser.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
class DartboardFooter extends StatelessWidget {
DartboardFooter({required this.dartboardData, required this.renderNs});
final int renderNs;
final DartboardData dartboardData;
@override
Widget build(Context context) {
final double renderTimeMs = renderNs.toDouble() / 1000.0;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
'This resume was generated with DartBoard Resume',
style: dartboardData.defaultTextStyle.copyWith(fontSize: 10),
),
Text(
'Rendered in ${renderTimeMs.toStringAsFixed(2)}ms',
style: dartboardData.defaultTextStyle.copyWith(fontSize: 10),
),
],
);
}
}
class DartboardExperienceEntry extends StatelessWidget {
DartboardExperienceEntry({required this.dartboardData, required this.exp});
final DartboardData dartboardData;
final DartboardExperience exp;
@override
Widget build(Context context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(exp.title, style: dartboardData.subheaderTextStyle.apply(color: const PdfColorGrey(0.3))),
Container(height: 1, width: 60, color: const PdfColorGrey(0.75)),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
exp.range.toString(),
style: dartboardData.defaultTextStyle.apply(color: const PdfColorGrey(0.42)),
),
if (exp.location != null)
Text(
exp.location!,
style: dartboardData.defaultTextStyle.apply(color: const PdfColorGrey(0.42)),
),
],
),
],
),
SizedBox(height: 6),
...exp.attributes.map(
(a) => Padding(
child: DartboardTextWithLink(
stringSections: a.toTextLinkList(),
bulletString: dartboardData.dartboardTheme.bulletPoint,
style: dartboardData.defaultTextStyle.apply(
color: const PdfColorGrey(0.55),
),
),
padding: const EdgeInsets.only(bottom: 4.0),
),
),
SizedBox(height: 20),
],
);
}
}
// TODO this lays out long text lines on a newline after a uilink rather than soft wrapping it.
class DartboardTextWithLink extends StatelessWidget {
DartboardTextWithLink({this.bulletString, required this.stringSections, this.style});
final String? bulletString;
final List<DartboardTextLinkData> stringSections;
final TextStyle? style;
@override
Widget build(Context context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(bulletString == null ? '' : '$bulletString ', style: style),
SizedBox(
width: DartboardTheme.width - DartboardTheme.margin * 2 - 20.0,
child: Wrap(
children: [
...stringSections.map((s) {
switch (s.type) {
case DartboardTextType.normal:
return Text(s.text, style: style);
case DartboardTextType.linkText:
return UrlLink(
destination: s.url!,
child: Text(
s.text,
style: style?.copyWith(color: PdfColors.blue),
),
);
}
}),
],
),
),
],
);
}
}

118
lib/render.dart Normal file
View File

@ -0,0 +1,118 @@
import 'dart:io';
import 'package:dartboard_resume/dartboard_parser.dart';
import 'package:dartboard_resume/dartboard_widgets.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
import 'package:toml/toml.dart';
int? lastDartboardHash;
Future<void> renderPdf(String tomlFilePath, {bool force = false}) async {
try {
final start = DateTime.now().microsecondsSinceEpoch;
final dartboardData = DartboardData.fromToml(tomlFilePath);
if (lastDartboardHash == dartboardData.hashCode && !force) {
return;
}
lastDartboardHash = dartboardData.hashCode;
stdout.writeln("Detected change:\nRendering with new dartboard data: $lastDartboardHash");
final pdfFuture = Document()..addPage(_generatePdfPage(dartboardData: dartboardData, renderNs: 0));
await pdfFuture.save();
final renderNs = DateTime.now().microsecondsSinceEpoch - start;
final pdf = Document();
pdf.addPage(_generatePdfPage(dartboardData: dartboardData, renderNs: renderNs));
final file = File("example.pdf");
final bytes = await pdf.save();
stdout.writeln('New pdf file saved.');
file.writeAsBytesSync(bytes);
stdout.writeln('Reloading llpp...');
Process.runSync('pkill', ['-HUP', 'llpp']);
} catch (e) {
stderr.writeln('Encountered error: $e');
try {
stderr.writeln('Current toml map:\n${TomlDocument.loadSync(tomlFilePath).toMap()}');
} catch (_) {
stderr.writeln('Cannot display current toml map');
}
}
}
Page _generatePdfPage({required DartboardData dartboardData, required int renderNs}) {
final List<Widget> groupedExperienceList = dartboardData.groupedExperiences.entries.map<Widget>(
(entry) {
final String subsection = entry.key;
final List<DartboardExperience> experiences = entry.value;
return Column(
children: [
Row(
children: [
Text(
subsection,
style: dartboardData.subheaderTextStyle
.merge(const TextStyle(fontSize: 18))
.apply(color: const PdfColorGrey(0.2)),
),
],
),
Container(height: 2, width: 200, color: const PdfColorGrey(0.7)),
...experiences.map(
(DartboardExperience exp) => DartboardExperienceEntry(dartboardData: dartboardData, exp: exp),
),
DartboardFooter(dartboardData: dartboardData, renderNs: renderNs),
],
);
},
).toList();
return Page(
pageTheme: const PageTheme(pageFormat: PdfPageFormat.standard),
build: (Context context) {
return
// FullPage(
// ignoreMargins: true,
// child:
Column(
children: [
SizedBox(
height: 120,
width: double.infinity,
child: Stack(
children: [
Positioned(
left: 0,
child: Container(
height: 100,
width: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.contain,
image: MemoryImage(
File(dartboardData.imagePath).readAsBytesSync(),
),
),
),
),
),
Center(
child: Column(
children: [
Text(dartboardData.fullName, style: dartboardData.headerTextStyle),
Text(dartboardData.phoneNumber, style: dartboardData.headerTextStyle),
Text(dartboardData.email, style: dartboardData.headerTextStyle),
],
),
),
],
),
),
Container(height: 20),
...groupedExperienceList,
],
// ),
);
},
);
}

5
lib/utils.dart Normal file
View File

@ -0,0 +1,5 @@
extension StringUtils on String {
String capitalize() {
return substring(0, 1).toUpperCase() + substring(1);
}
}

BIN
nerd.ttf Normal file

Binary file not shown.

530
pubspec.lock Normal file
View File

@ -0,0 +1,530 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3"
url: "https://pub.dev"
source: hosted
version: "68.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.1.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808"
url: "https://pub.dev"
source: hosted
version: "6.5.0"
archive:
dependency: transitive
description:
name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev"
source: hosted
version: "3.6.1"
args:
dependency: transitive
description:
name: args
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
version: "2.5.0"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
barcode:
dependency: transitive
description:
name: barcode
sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003
url: "https://pub.dev"
source: hosted
version: "2.2.8"
bidi:
dependency: transitive
description:
name: bidi
sha256: "9a712c7ddf708f7c41b1923aa83648a3ed44cfd75b04f72d598c45e5be287f9d"
url: "https://pub.dev"
source: hosted
version: "2.0.12"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.19.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
coverage:
dependency: transitive
description:
name: coverage
sha256: c1fb2dce3c0085f39dc72668e85f8e0210ec7de05345821ff58530567df345a5
url: "https://pub.dev"
source: hosted
version: "1.9.2"
crypto:
dependency: transitive
description:
name: crypto
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
url: "https://pub.dev"
source: hosted
version: "3.0.5"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
hotreloader:
dependency: "direct dev"
description:
name: hotreloader
sha256: ed56fdc1f3a8ac924e717257621d09e9ec20e308ab6352a73a50a1d7a4d9158e
url: "https://pub.dev"
source: hosted
version: "4.2.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
image:
dependency: transitive
description:
name: image
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
intl:
dependency: "direct main"
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.19.0"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
lint:
dependency: "direct main"
description:
name: lint
sha256: d758a5211fce7fd3f5e316f804daefecdc34c7e53559716125e6da7388ae8565
url: "https://pub.dev"
source: hosted
version: "2.3.0"
lints:
dependency: "direct dev"
description:
name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.dev"
source: hosted
version: "3.0.0"
logging:
dependency: "direct main"
description:
name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
macros:
dependency: transitive
description:
name: macros
sha256: "12e8a9842b5a7390de7a781ec63d793527582398d16ea26c60fed58833c9ae79"
url: "https://pub.dev"
source: hosted
version: "0.1.0-main.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16+1"
meta:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.15.0"
mime:
dependency: transitive
description:
name: mime
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
url: "https://pub.dev"
source: hosted
version: "1.0.6"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
version: "1.9.0"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "1.0.1"
pdf:
dependency: "direct main"
description:
name: pdf
sha256: "05df53f8791587402493ac97b9869d3824eccbc77d97855f4545cf72df3cae07"
url: "https://pub.dev"
source: hosted
version: "3.11.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
qr:
dependency: transitive
description:
name: qr
sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
url: "https://pub.dev"
source: hosted
version: "1.1.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
url: "https://pub.dev"
source: hosted
version: "0.10.12"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
url: "https://pub.dev"
source: hosted
version: "1.25.8"
test_api:
dependency: transitive
description:
name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.3"
test_core:
dependency: transitive
description:
name: test_core
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
url: "https://pub.dev"
source: hosted
version: "0.6.5"
toml:
dependency: "direct main"
description:
name: toml
sha256: d968d149c8bd06dc14e09ea3a140f90a3f2ba71949e7a91df4a46f3107400e71
url: "https://pub.dev"
source: hosted
version: "0.16.0"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
watcher:
dependency: transitive
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
url: "https://pub.dev"
source: hosted
version: "1.0.0"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
url: "https://pub.dev"
source: hosted
version: "0.1.6"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.4.4 <4.0.0"

22
pubspec.yaml Normal file
View File

@ -0,0 +1,22 @@
name: dartboard_resume
description: A sample command-line application.
version: 1.0.0
# repository: https://github.com/my_org/my_repo
environment:
sdk: ^3.4.4
# Add regular dependencies here.
dependencies:
intl: ^0.19.0
lint: ^2.3.0
logging: ^1.2.0
pdf: ^3.11.1
toml: ^0.16.0
# path: ^1.8.0
dev_dependencies:
lints: ^3.0.0
test: ^1.24.0
hotreloader: ^4.2.0

View File

@ -0,0 +1 @@