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:gitjournal/utils/datetime.dart';
|
||||||
|
|
||||||
import 'package:path/path.dart' as p;
|
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.dart';
|
||||||
import 'md_yaml_doc_codec.dart';
|
import 'md_yaml_doc_codec.dart';
|
||||||
@ -366,6 +369,36 @@ class Note with NotesNotifier {
|
|||||||
|
|
||||||
return date.toString();
|
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) {
|
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();
|
var actualContent = File(notePath).readAsStringSync();
|
||||||
expect(actualContent, equals(expectedContent));
|
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