mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 01:45:55 +08:00
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:
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user