From ee4d7268c5dc97acfc91f81f2b660f1c122d34f5 Mon Sep 17 00:00:00 2001 From: Aaron Madlon-Kay Date: Thu, 19 Dec 2024 22:34:12 +0900 Subject: [PATCH] Refactor link abbreviation handling --- lib/src/pages/document/links.dart | 16 ++++++++-------- test/links_test.dart | 21 +++++++++++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/src/pages/document/links.dart b/lib/src/pages/document/links.dart index bf704a3..25fb49e 100644 --- a/lib/src/pages/document/links.dart +++ b/lib/src/pages/document/links.dart @@ -33,7 +33,7 @@ extension LinkHandler on DocumentPageState { // Handle as a general URL try { - final url = extractUrl(doc, link); + final url = expandAbbreviatedUrl(doc, link) ?? Uri.parse(link.location); debugPrint('Launching URL: $url'); final handled = await launchUrl(url, mode: LaunchMode.externalApplication); @@ -204,25 +204,25 @@ extension LinkHandler on DocumentPageState { } } -Uri extractUrl(OrgTree doc, OrgLink link) { +Uri? expandAbbreviatedUrl(OrgTree doc, OrgLink link) { // Uri.parse can fail on a link that might otherwise succeed after expanding // abbreviations, so don't unconditionally try to parse the raw link.location. - final abbreviations = extractLinkAbbreviations(doc); - if (abbreviations.isEmpty) return Uri.parse(link.location); - final colonIdx = link.location.indexOf(':'); - if (colonIdx == -1) return Uri.parse(link.location); + if (colonIdx == -1) return null; final linkword = link.location.substring(0, colonIdx); final tag = link.location.substring(colonIdx + 1); + final abbreviations = extractLinkAbbreviations(doc); + if (abbreviations.isEmpty) return null; + final String format; try { (linkword: _, :format) = abbreviations.firstWhere((abbr) => abbr.linkword == linkword); } on StateError { - return Uri.parse(link.location); + return null; } final formatted = format.contains('%s') @@ -230,7 +230,7 @@ Uri extractUrl(OrgTree doc, OrgLink link) { : format.contains('%h') ? format.replaceFirst('%h', Uri.encodeComponent(tag)) : '$format$tag'; - return Uri.tryParse(formatted) ?? Uri.parse(link.location); + return Uri.tryParse(formatted); } final _abbreviationPattern = diff --git a/test/links_test.dart b/test/links_test.dart index 645ffae..ddddda0 100644 --- a/test/links_test.dart +++ b/test/links_test.dart @@ -20,6 +20,11 @@ void main() { final found = extractLinkAbbreviations(doc); expect(found, [(linkword: 'foo bar', format: 'baz')]); }); + test('Case-insensitive', () { + final doc = OrgDocument.parse('''#+link: "foo bar" baz'''); + final found = extractLinkAbbreviations(doc); + expect(found, [(linkword: 'foo bar', format: 'baz')]); + }); test('Multiple', () { final doc = OrgDocument.parse(''' #+LINK: foo bar @@ -36,43 +41,43 @@ void main() { test('Appending', () { final doc = OrgDocument.parse('''#+LINK: foo bar'''); final link = OrgPlainLink('foo:buzz'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('barbuzz')); }); test('Replacing', () { final doc = OrgDocument.parse('''#+LINK: foo bar=%s&blah'''); final link = OrgPlainLink('foo:buzz'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('bar=buzz&blah')); }); test('Percent-encoding', () { final doc = OrgDocument.parse('''#+LINK: foo bar=%h&blah'''); final link = OrgPlainLink('foo:あ'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('bar=%E3%81%82&blah')); }); test('Missing definition', () { final doc = OrgDocument.parse('''#+LINK: foo bar=%h&blah'''); final link = OrgPlainLink('foof:あ'); - final result = extractUrl(doc, link); - expect(result, Uri.parse('foof:あ')); + final result = expandAbbreviatedUrl(doc, link); + expect(result, isNull); }); test('Space in linkword', () { final doc = OrgDocument.parse('''#+LINK: "foo bar" baz=%h&blah'''); final link = OrgPlainLink('foo bar:あ'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('baz=%E3%81%82&blah')); }); test('Multiple placeholders (same)', () { final doc = OrgDocument.parse('''#+LINK: foo bar=%s&%s'''); final link = OrgPlainLink('foo:baz'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('bar=baz&%s')); }); test('Multiple placeholders (different)', () { final doc = OrgDocument.parse('''#+LINK: foo bar=%h&%s'''); final link = OrgPlainLink('foo:baz'); - final result = extractUrl(doc, link); + final result = expandAbbreviatedUrl(doc, link); expect(result, Uri.parse('bar=%h&baz')); }); });