Note: Allow returning the links in the document

This isn't perfect as we aren't handling referenced links and maybe even
autolinks, but it's a start.

Related to #141
This commit is contained in:
Vishesh Handa
2020-05-26 14:49:01 +02:00
parent 29ec2d1a90
commit af69dd6e48
2 changed files with 116 additions and 0 deletions

View File

@ -9,6 +9,9 @@ import 'package:gitjournal/utils/logger.dart';
import 'package:gitjournal/utils/datetime.dart';
import 'package:path/path.dart' as p;
import 'package:meta/meta.dart';
import 'package:markdown/markdown.dart' as md;
import 'md_yaml_doc.dart';
import 'md_yaml_doc_codec.dart';
@ -366,6 +369,36 @@ class Note with NotesNotifier {
return date.toString();
}
Future<List<Link>> fetchLinks() async {
final doc = md.Document(
encodeHtml: false,
extensionSet: md.ExtensionSet.gitHubFlavored,
);
var lines = body.replaceAll('\r\n', '\n').split('\n');
var nodes = doc.parseLines(lines);
var possibleLinks = LinkExtractor().visit(nodes);
var links = <Link>[];
for (var l in possibleLinks) {
var path = l.filePath;
var isLocal = (path.startsWith('/') || path.startsWith('.')) &&
!path.contains('://');
if (isLocal) {
l.filePath = p.join(parent.folderPath, p.normalize(l.filePath));
links.add(l);
}
}
doc.linkReferences.forEach((key, value) {
print(value);
var filePath = value.destination;
links.add(Link(term: key, filePath: filePath));
});
return links;
}
}
String buildTitleFileName(String parentDir, String title) {
@ -388,3 +421,59 @@ String buildTitleFileName(String parentDir, String title) {
}
}
}
class Link {
String term;
String filePath;
Link({@required this.term, @required this.filePath});
@override
int get hashCode => filePath.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Note &&
runtimeType == other.runtimeType &&
filePath == other.filePath;
}
class LinkExtractor implements md.NodeVisitor {
List<Link> links = [];
@override
bool visitElementBefore(md.Element element) {
return true;
}
@override
void visitText(md.Text text) {}
@override
void visitElementAfter(md.Element el) {
final String tag = el.tag;
if (tag == 'a') {
var title = el.attributes['title'] ?? "";
if (title.isEmpty) {
for (var child in el.children) {
if (child is md.Text) {
title += child.text;
}
}
}
var url = el.attributes['href'];
var link = Link(term: title, filePath: url);
links.add(link);
}
}
List<Link> visit(List<md.Node> nodes) {
for (final node in nodes) {
node.accept(this);
}
return links;
}
}

View File

@ -112,5 +112,32 @@ Hello""";
var actualContent = File(notePath).readAsStringSync();
expect(actualContent, equals(expectedContent));
});
test('Should parse links', () async {
var content = """---
title: Foo
---
[Hi](./foo.md)
[Hi2](./po/../food.md)
[Web](http://example.com)
""";
var notePath = p.join(tempDir.path, "note6.md");
File(notePath).writeAsString(content);
var parentFolder = NotesFolderFS(null, tempDir.path);
var note = Note(parentFolder, notePath);
await note.load();
var links = await note.fetchLinks();
expect(links[0].filePath, p.join(tempDir.path, "foo.md"));
expect(links[0].term, "Hi");
expect(links[1].filePath, p.join(tempDir.path, "food.md"));
expect(links[1].term, "Hi2");
expect(links.length, 2);
});
});
}