Add support for 'screenshots' field (dart-lang/pubspec_parse#78)
diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md
index 8f2d288..5f3d5d6 100644
--- a/pkgs/pubspec_parse/CHANGELOG.md
+++ b/pkgs/pubspec_parse/CHANGELOG.md
@@ -1,14 +1,12 @@
-## 1.2.0-dev
+## 1.2.0
+- Added support for `screenshots` field.
- Update `HostedDetails` to reflect how `hosted` dependencies are parsed in
Dart 2.15:
- Add `HostedDetails.declaredName` as the (optional) `name` property in a
`hosted` block.
- `HostedDetails.name` now falls back to the name of the dependency if no
name is declared in the block.
-
-## 1.1.1-dev
-
- Require Dart SDK >= 2.14.0
## 1.1.0
diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart
index 63c1e30..7360d1a 100644
--- a/pkgs/pubspec_parse/lib/pubspec_parse.dart
+++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart
@@ -11,3 +11,4 @@
SdkDependency,
PathDependency;
export 'src/pubspec.dart' show Pubspec;
+export 'src/screenshot.dart' show Screenshot;
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart
index 8cc7b09..82c78aa 100644
--- a/pkgs/pubspec_parse/lib/src/pubspec.dart
+++ b/pkgs/pubspec_parse/lib/src/pubspec.dart
@@ -7,6 +7,7 @@
import 'package:pub_semver/pub_semver.dart';
import 'dependency.dart';
+import 'screenshot.dart';
part 'pubspec.g.dart';
@@ -39,6 +40,10 @@
/// view existing ones.
final Uri? issueTracker;
+ /// Optional field for specifying included screenshot files.
+ @JsonKey(fromJson: parseScreenshots)
+ final List<Screenshot>? screenshots;
+
/// If there is exactly 1 value in [authors], returns it.
///
/// If there are 0 or more than 1, returns `null`.
@@ -96,6 +101,7 @@
this.homepage,
this.repository,
this.issueTracker,
+ this.screenshots,
this.documentation,
this.description,
Map<String, Dependency>? dependencies,
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart
index cadd38e..221cc83 100644
--- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart
+++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart
@@ -27,6 +27,8 @@
'repository', (v) => v == null ? null : Uri.parse(v as String)),
issueTracker: $checkedConvert('issue_tracker',
(v) => v == null ? null : Uri.parse(v as String)),
+ screenshots: $checkedConvert(
+ 'screenshots', (v) => parseScreenshots(v as List?)),
documentation: $checkedConvert('documentation', (v) => v as String?),
description: $checkedConvert('description', (v) => v as String?),
dependencies:
diff --git a/pkgs/pubspec_parse/lib/src/screenshot.dart b/pkgs/pubspec_parse/lib/src/screenshot.dart
new file mode 100644
index 0000000..f5f0be2
--- /dev/null
+++ b/pkgs/pubspec_parse/lib/src/screenshot.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:json_annotation/json_annotation.dart';
+
+@JsonSerializable()
+class Screenshot {
+ final String description;
+ final String path;
+
+ Screenshot(this.description, this.path);
+}
+
+List<Screenshot> parseScreenshots(List? input) {
+ final res = <Screenshot>[];
+ if (input == null) {
+ return res;
+ }
+
+ for (final e in input) {
+ if (e is! Map) continue;
+
+ final description = e['description'];
+ if (description == null) {
+ throw CheckedFromJsonException(
+ e,
+ 'description',
+ 'Screenshot',
+ 'Missing required key `description`',
+ );
+ }
+
+ if (description is! String) {
+ throw CheckedFromJsonException(
+ e,
+ 'description',
+ 'Screenshot',
+ '`$description` is not a String',
+ );
+ }
+
+ final path = e['path'];
+ if (path == null) {
+ throw CheckedFromJsonException(
+ e,
+ 'path',
+ 'Screenshot',
+ 'Missing required key `path`',
+ );
+ }
+
+ if (path is! String) {
+ throw CheckedFromJsonException(
+ e,
+ 'path',
+ 'Screenshot',
+ '`$path` is not a String',
+ );
+ }
+
+ res.add(Screenshot(description, path));
+ }
+ return res;
+}
diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml
index 90ae1fe..ae7a03f 100644
--- a/pkgs/pubspec_parse/pubspec.yaml
+++ b/pkgs/pubspec_parse/pubspec.yaml
@@ -2,7 +2,7 @@
description: >-
Simple package for parsing pubspec.yaml files with a type-safe API and rich
error reporting.
-version: 1.2.0-dev
+version: 1.2.0
repository: https://github.com/dart-lang/pubspec_parse
environment:
diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart
index 5f70de8..e8d24c6 100644
--- a/pkgs/pubspec_parse/test/parse_test.dart
+++ b/pkgs/pubspec_parse/test/parse_test.dart
@@ -31,6 +31,7 @@
expect(value.flutter, isNull);
expect(value.repository, isNull);
expect(value.issueTracker, isNull);
+ expect(value.screenshots, isEmpty);
});
test('all fields set', () {
@@ -47,6 +48,9 @@
'documentation': 'documentation',
'repository': 'https://github.com/example/repo',
'issue_tracker': 'https://github.com/example/repo/issues',
+ 'screenshots': [
+ {'description': 'my screenshot', 'path': 'path/to/screenshot'}
+ ],
});
expect(value.name, 'sample');
expect(value.version, version);
@@ -66,6 +70,9 @@
value.issueTracker,
Uri.parse('https://github.com/example/repo/issues'),
);
+ expect(value.screenshots, hasLength(1));
+ expect(value.screenshots!.first.description, 'my screenshot');
+ expect(value.screenshots!.first.path, 'path/to/screenshot');
});
test('environment values can be null', () {
@@ -357,6 +364,160 @@
});
});
+ group('screenshots', () {
+ test('one screenshot', () {
+ final value = parse({
+ ...defaultPubspec,
+ 'screenshots': [
+ {'description': 'my screenshot', 'path': 'path/to/screenshot'}
+ ],
+ });
+ expect(value.screenshots, hasLength(1));
+ expect(value.screenshots!.first.description, 'my screenshot');
+ expect(value.screenshots!.first.path, 'path/to/screenshot');
+ });
+
+ test('many screenshots', () {
+ final value = parse({
+ ...defaultPubspec,
+ 'screenshots': [
+ {'description': 'my screenshot', 'path': 'path/to/screenshot'},
+ {
+ 'description': 'my second screenshot',
+ 'path': 'path/to/screenshot2'
+ },
+ ],
+ });
+ expect(value.screenshots, hasLength(2));
+ expect(value.screenshots!.first.description, 'my screenshot');
+ expect(value.screenshots!.first.path, 'path/to/screenshot');
+ expect(value.screenshots!.last.description, 'my second screenshot');
+ expect(value.screenshots!.last.path, 'path/to/screenshot2');
+ });
+
+ test('one screenshot plus invalid entries', () {
+ final value = parse({
+ ...defaultPubspec,
+ 'screenshots': [
+ 42,
+ {
+ 'description': 'my screenshot',
+ 'path': 'path/to/screenshot',
+ 'extraKey': 'not important'
+ },
+ 'not a screenshot',
+ ],
+ });
+ expect(value.screenshots, hasLength(1));
+ expect(value.screenshots!.first.description, 'my screenshot');
+ expect(value.screenshots!.first.path, 'path/to/screenshot');
+ });
+
+ test('invalid entries', () {
+ final value = parse({
+ ...defaultPubspec,
+ 'screenshots': [
+ 42,
+ 'not a screenshot',
+ ],
+ });
+ expect(value.screenshots, isEmpty);
+ });
+
+ test('missing key `dessription', () {
+ expectParseThrows(
+ {
+ ...defaultPubspec,
+ 'screenshots': [
+ {'path': 'my/path'},
+ ],
+ },
+ r'''
+line 7, column 3: Missing key "description". Missing required key `description`
+ ╷
+7 │ ┌ {
+8 │ │ "path": "my/path"
+9 │ └ }
+ ╵''',
+ skipTryPub: true,
+ );
+ });
+
+ test('missing key `path`', () {
+ expectParseThrows(
+ {
+ ...defaultPubspec,
+ 'screenshots': [
+ {'description': 'my screenshot'},
+ ],
+ },
+ r'''
+line 7, column 3: Missing key "path". Missing required key `path`
+ ╷
+7 │ ┌ {
+8 │ │ "description": "my screenshot"
+9 │ └ }
+ ╵''',
+ skipTryPub: true,
+ );
+ });
+
+ test('Value of description not a String`', () {
+ expectParseThrows(
+ {
+ ...defaultPubspec,
+ 'screenshots': [
+ {'description': 42},
+ ],
+ },
+ r'''
+line 8, column 19: Unsupported value for "description". `42` is not a String
+ ╷
+8 │ "description": 42
+ │ ┌───────────────────^
+9 │ │ }
+ │ └──^
+ ╵''',
+ skipTryPub: true,
+ );
+ });
+
+ test('Value of path not a String`', () {
+ expectParseThrows(
+ {
+ ...defaultPubspec,
+ 'screenshots': [
+ {
+ 'description': '',
+ 'path': 42,
+ },
+ ],
+ },
+ r'''
+line 9, column 12: Unsupported value for "path". `42` is not a String
+ ╷
+9 │ "path": 42
+ │ ┌────────────^
+10 │ │ }
+ │ └──^
+ ╵''',
+ skipTryPub: true,
+ );
+ });
+
+ test('invalid screenshot - lenient', () {
+ final value = parse(
+ {
+ ...defaultPubspec,
+ 'screenshots': 'Invalid value',
+ },
+ lenient: true,
+ );
+ expect(value.name, 'sample');
+ expect(value.screenshots, isEmpty);
+ });
+ });
+
group('lenient', () {
test('null', () {
expectParseThrows(