Skip to content

Commit

Permalink
Refactor link abbreviation handling
Browse files Browse the repository at this point in the history
  • Loading branch information
amake committed Dec 19, 2024
1 parent 7dd5806 commit ee4d726
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 16 deletions.
16 changes: 8 additions & 8 deletions lib/src/pages/document/links.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -204,33 +204,33 @@ 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')
? format.replaceFirst('%s', tag)
: 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 =
Expand Down
21 changes: 13 additions & 8 deletions test/links_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'));
});
});
Expand Down

0 comments on commit ee4d726

Please sign in to comment.