Skip to content

Commit dcceaf8

Browse files
f3athmaltevesper
andauthored
Keep freetext in the beginning of a release. (#16)
Section preamble Co-authored-by: Malte Vesper <[email protected]>
1 parent 2b7d8c9 commit dcceaf8

File tree

12 files changed

+105
-40
lines changed

12 files changed

+105
-40
lines changed

.github/workflows/publish.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# .github/workflows/publish.yml
2+
name: Publish to pub.dev
3+
4+
on:
5+
push:
6+
tags:
7+
- '[0-9]+.[0-9]+.[0-9]+*'
8+
9+
# Publish using the reusable workflow from dart-lang.
10+
jobs:
11+
publish:
12+
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Changelog
22
This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
33

4+
## [0.7.0] - 2023-06-11
5+
### Added
6+
- keep freetext directly under release headings
7+
- Support for section preamble
8+
9+
### Changed
10+
- Min SDK version is 3.0.0
11+
412
## [0.6.0] - 2023-02-14
513
### Added
614
- You may pass an instance of markdown `Document` to the `parseChangelog()` to have fine-grained control over parsing, e.g. whether to encode HTML entities
@@ -111,6 +119,7 @@ This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.
111119
- Parsing from markdown
112120
- Writing to markdown
113121

122+
[0.7.0]: https://github.com/f3ath/change/compare/0.6.0...0.7.0
114123
[0.6.0]: https://github.com/f3ath/change/compare/0.5.0...0.6.0
115124
[0.5.0]: https://github.com/f3ath/change/compare/0.4.0...0.5.0
116125
[0.4.0]: https://github.com/f3ath/change/compare/0.3.1...0.4.0
@@ -130,4 +139,4 @@ This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.
130139
[0.0.5]: https://github.com/f3ath/change/compare/0.0.4...0.0.5
131140
[0.0.4]: https://github.com/f3ath/change/compare/0.0.3...0.0.4
132141
[0.0.3]: https://github.com/f3ath/change/compare/0.0.2...0.0.3
133-
[0.0.2]: https://github.com/f3ath/change/compare/0.0.1...0.0.2
142+
[0.0.2]: https://github.com/f3ath/change/compare/0.0.1...0.0.2

analysis_options.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
include: package:lints/recommended.yaml
2-
analyzer:
3-
strong-mode:
4-
implicit-casts: false
5-
implicit-dynamic: false
62
linter:
73
rules:
84
- sort_constructors_first

lib/src/changelog.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class Changelog {
77
/// Releases mapped by version
88
final _releases = <String, Release>{};
99

10-
/// Changelog header which comes on top of the file before the Unreleased
11-
/// and version sections.
10+
/// Free text which comes on top of the file before the Unreleased section
11+
/// and the releases.
1212
final header = <Node>[];
1313

1414
/// The unreleased changes.

lib/src/parser.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:convert';
33
import 'package:change/src/change.dart';
44
import 'package:change/src/changelog.dart';
55
import 'package:change/src/release.dart';
6+
import 'package:change/src/section.dart';
67
import 'package:markdown/markdown.dart';
78
import 'package:pub_semver/pub_semver.dart';
89

@@ -24,7 +25,7 @@ Changelog parseChangelog(String markdown, {Document? document}) {
2425
}
2526
for (final nodes in sections) {
2627
if (_isUnreleased(nodes.first)) {
27-
_changes(nodes.skip(1)).forEach(log.unreleased.add);
28+
_parseInto(log.unreleased, nodes.skip(1));
2829
log.unreleased.link = doc.linkReferences['unreleased']?.destination ?? '';
2930
} else {
3031
final release = _release(nodes);
@@ -64,22 +65,24 @@ Release _release(Iterable<Node> nodes) {
6465
DateTime.parse(date),
6566
isYanked: isYanked,
6667
);
67-
_changes(nodes.skip(1)).forEach(release.add);
68+
_parseInto(release, nodes.skip(1));
6869
return release;
6970
}
7071

71-
List<Change> _changes(Iterable<Node> nodes) {
72-
final changes = <Change>[];
72+
void _parseInto(Section section, Iterable<Node> nodes) {
7373
var type = 'Changed';
74+
var headerFinished = false;
7475
for (final node in nodes.whereType<Element>()) {
7576
if (node.tag == 'h3') {
77+
headerFinished = true;
7678
type = node.textContent.trim();
79+
} else if (!headerFinished) {
80+
section.preamble.add(node);
7781
} else if (node.tag == 'ul') {
7882
node.children!
7983
.whereType<Element>()
8084
.map((node) => Change(type, node.children!))
81-
.forEach(changes.add);
85+
.forEach(section.add);
8286
}
8387
}
84-
return changes;
8588
}

lib/src/printer.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Iterable<Element> _unreleased(Section section) sync* {
4646
header.add(_link(sectionLink, [text]));
4747
}
4848
yield Element('h2', header);
49+
yield* section.preamble;
4950
yield* _changes(section);
5051
}
5152

@@ -63,6 +64,7 @@ Iterable<Element> _release(Release release) sync* {
6364
header.add(Text(' [YANKED]'));
6465
}
6566
yield Element('h2', header);
67+
yield* release.preamble;
6668
yield* _changes(release);
6769
}
6870

lib/src/section.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import 'package:change/src/change.dart';
2+
import 'package:markdown/markdown.dart';
23

34
/// A release or the unreleased section
45
class Section {
56
final _changes = <Change>[];
67

8+
/// Free text which precedes the actual list of changes.
9+
/// The Keepachangelog standard does not specify this part but we support
10+
/// it since there's a demand for it.
11+
final preamble = <Element>[];
12+
713
/// Section link. Usually, the diff
814
String link = '';
915

@@ -33,5 +39,6 @@ class Section {
3339
void clear() {
3440
_changes.clear();
3541
link = '';
42+
preamble.clear();
3643
}
3744
}

pubspec.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
name: change
2-
version: 0.6.0
2+
version: 0.7.0
33
description: A Changelog manipulation library. Read/modify/write your CHANGELOG.md. Inspired by keepachangelog.com.
44
homepage: "https://github.com/f3ath/change"
55

6-
cider:
7-
link_template:
8-
tag: 'https://github.com/f3ath/change/releases/tag/%tag%' # initial release link template
9-
diff: 'https://github.com/f3ath/change/compare/%from%...%to%' # subsequent releases link template
10-
116
environment:
12-
sdk: ">=2.19.0 <4.0.0"
7+
sdk: '>=3.0.0 <4.0.0'
138

149
dependencies:
1510
markdown: ^7.0.0
@@ -23,3 +18,7 @@ dev_dependencies:
2318
coverage: ^1.2.0
2419
check_coverage: ^0.0.4
2520

21+
cider:
22+
link_template:
23+
tag: 'https://github.com/f3ath/change/releases/tag/%tag%' # initial release link template
24+
diff: 'https://github.com/f3ath/change/compare/%from%...%to%' # subsequent releases link template

test/browser_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:change/change.dart';
2+
import 'package:markdown/markdown.dart';
3+
import 'package:pub_semver/pub_semver.dart';
4+
import 'package:test/test.dart';
5+
6+
void main() {
7+
test('Browser compatibility smoke test', () {
8+
final c = Changelog();
9+
final release =
10+
Release(Version.parse('1.0.0'), DateTime.parse('2022-02-22'))
11+
..add(Change('Added', [Text('Some change')]))
12+
..link = 'https://example.com';
13+
c.add(release);
14+
15+
final expected = '## [1.0.0] - 2022-02-22\n'
16+
'### Added\n'
17+
'- Some change\n'
18+
'\n'
19+
'[1.0.0]: https://example.com';
20+
21+
expect(printChangelog(c), equals(expected));
22+
}, testOn: 'browser');
23+
}

test/changelog_test.dart

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,6 @@ void main() {
6767
throwsFormatException);
6868
});
6969
});
70-
71-
group('Non-standard', () {
72-
final file = File('test/md/non_standard.md');
73-
74-
test('Can be read', () {
75-
final log = parseChangelog(file.readAsStringSync());
76-
expect(log.unreleased, isNotEmpty);
77-
expect(log.history().single.link, isEmpty);
78-
expect(log.history().single.version.toString(), '0.0.1-beta+42');
79-
expect(log.history().single.changes().single.type, 'Invented');
80-
expect(log.unreleased.changes().single.type, 'Added');
81-
});
82-
});
8370
});
8471

8572
group('Printing', () {
@@ -92,13 +79,6 @@ void main() {
9279
});
9380
});
9481

95-
test('Non-standard', () {
96-
final original = File('test/md/non_standard.md');
97-
final saved = File('test/md/non_standard_saved.md');
98-
expect(printChangelog(parseChangelog(original.readAsStringSync())),
99-
saved.readAsStringSync());
100-
});
101-
10282
final step1 = File('test/md/step1.md');
10383
final step2 = File('test/md/step2.md');
10484
final step3 = File('test/md/step3.md');
@@ -175,4 +155,23 @@ void main() {
175155
].join('\n'));
176156
});
177157
});
158+
159+
group('Non-standard', () {
160+
final file = File('test/md/non_standard.md');
161+
162+
test('Reading', () {
163+
final log = parseChangelog(file.readAsStringSync());
164+
expect(log.unreleased, isNotEmpty);
165+
expect(log.history().single.link, isEmpty);
166+
expect(log.history().single.version.toString(), '0.0.1-beta+42');
167+
expect(log.history().single.changes().single.type, 'Invented');
168+
expect(log.unreleased.changes().single.type, 'Added');
169+
});
170+
171+
test('Writing', () {
172+
final saved = File('test/md/non_standard_saved.md');
173+
expect(printChangelog(parseChangelog(file.readAsStringSync())),
174+
saved.readAsStringSync());
175+
});
176+
});
178177
}

0 commit comments

Comments
 (0)