diff --git a/lib/src/org/model/org_timestamp.dart b/lib/src/org/model/org_timestamp.dart index 6ae77cf..d35ed2e 100644 --- a/lib/src/org/model/org_timestamp.dart +++ b/lib/src/org/model/org_timestamp.dart @@ -14,8 +14,12 @@ class OrgDiaryTimestamp extends OrgLeafNode with SingleContentElement { typedef OrgDate = ({String year, String month, String day, String? dayName}); typedef OrgTime = ({String hour, String minute}); +sealed class OrgTimestamp extends OrgNode { + bool get isActive; +} + /// A timestamp, like `[2020-05-05 Tue]` -class OrgSimpleTimestamp extends OrgLeafNode { +class OrgSimpleTimestamp extends OrgLeafNode implements OrgTimestamp { OrgSimpleTimestamp( this.prefix, this.date, @@ -30,6 +34,7 @@ class OrgSimpleTimestamp extends OrgLeafNode { final List repeaterOrDelay; final String suffix; + @override bool get isActive => prefix == '<' && suffix == '>'; @override @@ -99,13 +104,14 @@ class OrgSimpleTimestamp extends OrgLeafNode { ); } -class OrgDateRangeTimestamp extends OrgParentNode { +class OrgDateRangeTimestamp extends OrgParentNode implements OrgTimestamp { OrgDateRangeTimestamp(this.start, this.delimiter, this.end); final OrgSimpleTimestamp start; final String delimiter; final OrgSimpleTimestamp end; + @override bool get isActive => start.isActive && end.isActive; @override @@ -146,7 +152,7 @@ class OrgDateRangeTimestamp extends OrgParentNode { ); } -class OrgTimeRangeTimestamp extends OrgLeafNode { +class OrgTimeRangeTimestamp extends OrgLeafNode implements OrgTimestamp { OrgTimeRangeTimestamp( this.prefix, this.date, @@ -163,6 +169,7 @@ class OrgTimeRangeTimestamp extends OrgLeafNode { final List repeaterOrDelay; final String suffix; + @override bool get isActive => prefix == '<' && suffix == '>'; DateTime get startDateTime => DateTime( diff --git a/test/org/model/timestamp_test.dart b/test/org/model/timestamp_test.dart index d4e664d..4c28bfe 100644 --- a/test/org/model/timestamp_test.dart +++ b/test/org/model/timestamp_test.dart @@ -108,5 +108,51 @@ void main() { expect(result.contains('あ'), isFalse); expect(result.toMarkup(), markup); }); + group("generic timestamp tests", () { + test('OrgSimpleTimestamp', () { + final markup = '<2025-05-30>'; + final result = parser.parse(markup).value as OrgTimestamp; + + expect(result.isActive, isTrue); + expect(result, isA()); + expect(result, isA()); + expect(result, isNot(isA())); + expect(result, isNot(isA())); + expect(result.toMarkup(), markup); + }); + test('OrgTimeRangeTimestamp', () { + final markup = '<2025-05-30 15:00-16:00>'; + final result = parser.parse(markup).value as OrgTimestamp; + + expect(result.isActive, isTrue); + expect(result, isA()); + expect(result, isA()); + expect(result, isNot(isA())); + expect(result, isNot(isA())); + expect(result.toMarkup(), markup); + }); + test('OrgDateRangeTimestamp', () { + final markup = '[2025-05-30]--[2025-06-30]'; + final result = parser.parse(markup).value as OrgTimestamp; + + expect(result.isActive, isFalse); + expect(result, isA()); + expect(result, isA()); + expect(result, isNot(isA())); + expect(result, isNot(isA())); + expect(result.toMarkup(), markup); + }); + test('Exhaustivity', () { + final markup = '[2025-05-30]--[2025-06-30]'; + final result = parser.parse(markup).value as OrgTimestamp; + + final type = switch (result) { + OrgTimeRangeTimestamp() => result.toString(), + OrgDateRangeTimestamp() => result.toString(), + OrgSimpleTimestamp() => result.toString(), + }; + expect(type, isNotEmpty); + }); + }); }); }