From fb78993fbcf8579fe3c6820a51f57a28865edfe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Sat, 30 Jan 2021 16:32:58 +0100 Subject: [PATCH] Save a link's context as a snippet --- adapter/handlebars/handlebars_test.go | 2 +- adapter/markdown/markdown.go | 14 ++++++++++++ adapter/markdown/markdown_test.go | 11 +++++++++ adapter/sqlite/db.go | 3 ++- adapter/sqlite/fixtures/default/links.yml | 5 +++++ adapter/sqlite/note_dao.go | 6 ++--- adapter/sqlite/note_dao_test.go | 27 ++++++++++++++++------- core/note/parse.go | 1 + 8 files changed, 56 insertions(+), 13 deletions(-) diff --git a/adapter/handlebars/handlebars_test.go b/adapter/handlebars/handlebars_test.go index 0380512..9db6b04 100644 --- a/adapter/handlebars/handlebars_test.go +++ b/adapter/handlebars/handlebars_test.go @@ -140,7 +140,7 @@ func TestShellHelper(t *testing.T) { testString(t, `{{sh "echo 'Hello, world!'"}}`, nil, - "Hello, world!\n", + "Hello, world!", ) } diff --git a/adapter/markdown/markdown.go b/adapter/markdown/markdown.go index 23225b1..fbc5956 100644 --- a/adapter/markdown/markdown.go +++ b/adapter/markdown/markdown.go @@ -135,6 +135,7 @@ func parseLinks(root ast.Node, source []byte) ([]note.Link, error) { Href: href, Rels: strings.Fields(string(link.Title)), External: strutil.IsURL(href), + Snippet: extractLines(n.Parent(), source), }) } } @@ -143,6 +144,19 @@ func parseLinks(root ast.Node, source []byte) ([]note.Link, error) { return links, err } +func extractLines(n ast.Node, source []byte) string { + if n == nil { + return "" + } + segs := n.Lines() + if segs.Len() == 0 { + return "" + } + start := segs.At(0).Start + end := segs.At(segs.Len() - 1).Stop + return string(source[start:end]) +} + // frontmatter contains metadata parsed from a YAML frontmatter. type frontmatter struct { values map[string]interface{} diff --git a/adapter/markdown/markdown_test.go b/adapter/markdown/markdown_test.go index 0da92ae..8f5bce8 100644 --- a/adapter/markdown/markdown_test.go +++ b/adapter/markdown/markdown_test.go @@ -175,42 +175,53 @@ A link can have [one relation](one "rel-1") or [several relations](several "rel- Href: "heading", Rels: []string{}, External: false, + Snippet: "Heading with a [link](heading)", }, { Title: "multiple links", Href: "stripped-formatting", Rels: []string{}, External: false, + Snippet: `Paragraph containing [multiple **links**](stripped-formatting), here's one [relative](../other). +A link can have [one relation](one "rel-1") or [several relations](several "rel-1 rel-2").`, }, { Title: "relative", Href: "../other", Rels: []string{}, External: false, + Snippet: `Paragraph containing [multiple **links**](stripped-formatting), here's one [relative](../other). +A link can have [one relation](one "rel-1") or [several relations](several "rel-1 rel-2").`, }, { Title: "one relation", Href: "one", Rels: []string{"rel-1"}, External: false, + Snippet: `Paragraph containing [multiple **links**](stripped-formatting), here's one [relative](../other). +A link can have [one relation](one "rel-1") or [several relations](several "rel-1 rel-2").`, }, { Title: "several relations", Href: "several", Rels: []string{"rel-1", "rel-2"}, External: false, + Snippet: `Paragraph containing [multiple **links**](stripped-formatting), here's one [relative](../other). +A link can have [one relation](one "rel-1") or [several relations](several "rel-1 rel-2").`, }, { Title: "External links", Href: "http://example.com", Rels: []string{}, External: true, + Snippet: `[External links](http://example.com) are marked [as such](ftp://domain).`, }, { Title: "as such", Href: "ftp://domain", Rels: []string{}, External: true, + Snippet: `[External links](http://example.com) are marked [as such](ftp://domain).`, }, }) } diff --git a/adapter/sqlite/db.go b/adapter/sqlite/db.go index 7bb71cb..92cfef2 100644 --- a/adapter/sqlite/db.go +++ b/adapter/sqlite/db.go @@ -85,7 +85,8 @@ func (db *DB) Migrate() error { title TEXT DEFAULT('') NOT NULL, href TEXT NOT NULL, external INT DEFAULT(0) NOT NULL, - rels TEXT DEFAULT('') NOT NULL + rels TEXT DEFAULT('') NOT NULL, + snippet TEXT DEFAULT('') NOT NULL )`, `CREATE INDEX IF NOT EXISTS index_links_source_id_target_id ON links (source_id, target_id)`, diff --git a/adapter/sqlite/fixtures/default/links.yml b/adapter/sqlite/fixtures/default/links.yml index 0b47a98..54fdaf9 100644 --- a/adapter/sqlite/fixtures/default/links.yml +++ b/adapter/sqlite/fixtures/default/links.yml @@ -4,6 +4,7 @@ title: "Missing target" href: "missing" external: false + snippet: "There's a Missing target" - id: 2 source_id: 1 @@ -11,6 +12,7 @@ title: "An internal link" href: "log/2021-01-04.md" external: false + snippet: "[[An internal link]]" - id: 3 source_id: 1 @@ -18,6 +20,7 @@ title: "An external link" href: "https://domain.com" external: true + snippet: "[[An external link]]" - id: 4 source_id: 4 @@ -25,6 +28,7 @@ title: "Another link" href: "log/2021-01-03.md" external: false + snippet: "[[Another link]]" - id: 5 source_id: 4 @@ -32,3 +36,4 @@ title: "Link from 4 to 6" href: "ref/test/a" external: false + snippet: "[[Link from 4 to 6]]" diff --git a/adapter/sqlite/note_dao.go b/adapter/sqlite/note_dao.go index 8b2f4f9..6e5ddb8 100644 --- a/adapter/sqlite/note_dao.go +++ b/adapter/sqlite/note_dao.go @@ -78,8 +78,8 @@ func NewNoteDAO(tx Transaction, logger util.Logger) *NoteDAO { // Add a new link. addLinkStmt: tx.PrepareLazy(` - INSERT INTO links (source_id, target_id, title, href, external, rels) - VALUES (?, ?, ?, ?, ?, ?) + INSERT INTO links (source_id, target_id, title, href, external, rels, snippet) + VALUES (?, ?, ?, ?, ?, ?, ?) `), // Set links matching a given href and missing a target ID to the given @@ -203,7 +203,7 @@ func (d *NoteDAO) addLinks(id int64, note note.Metadata) error { return err } - _, err = d.addLinkStmt.Exec(id, targetId, link.Title, link.Href, link.External, joinLinkRels(link.Rels)) + _, err = d.addLinkStmt.Exec(id, targetId, link.Title, link.Href, link.External, joinLinkRels(link.Rels), link.Snippet) if err != nil { return err } diff --git a/adapter/sqlite/note_dao_test.go b/adapter/sqlite/note_dao_test.go index 681bb16..a0bbe80 100644 --- a/adapter/sqlite/note_dao_test.go +++ b/adapter/sqlite/note_dao_test.go @@ -143,8 +143,9 @@ func TestNoteDAOAddWithLinks(t *testing.T) { Rels: []string{"rel-1", "rel-2"}, }, { - Title: "Relative", - Href: "f39c8", + Title: "Relative", + Href: "f39c8", + Snippet: "[Relative](f39c8) link", }, { Title: "Second is added", @@ -159,6 +160,7 @@ func TestNoteDAOAddWithLinks(t *testing.T) { Title: "URL", Href: "http://example.com", External: true, + Snippet: "External [URL](http://example.com)", }, }, }) @@ -179,6 +181,7 @@ func TestNoteDAOAddWithLinks(t *testing.T) { Title: "Relative", Href: "f39c8", Rels: "", + Snippet: "[Relative](f39c8) link", }, { SourceId: id, @@ -201,6 +204,7 @@ func TestNoteDAOAddWithLinks(t *testing.T) { Href: "http://example.com", External: true, Rels: "", + Snippet: "External [URL](http://example.com)", }, }) }) @@ -220,6 +224,7 @@ func TestNoteDAOAddFillsLinksMissingTargetId(t *testing.T) { TargetId: &id, Title: "Missing target", Href: "missing", + Snippet: "There's a Missing target", }, }) }) @@ -282,6 +287,7 @@ func TestNoteDAOUpdateWithLinks(t *testing.T) { TargetId: intPointer(2), Title: "An internal link", Href: "log/2021-01-04.md", + Snippet: "[[An internal link]]", }, { SourceId: 1, @@ -289,6 +295,7 @@ func TestNoteDAOUpdateWithLinks(t *testing.T) { Title: "An external link", Href: "https://domain.com", External: true, + Snippet: "[[An external link]]", }, }) @@ -300,11 +307,13 @@ func TestNoteDAOUpdateWithLinks(t *testing.T) { Href: "index", External: false, Rels: []string{"rel"}, + Snippet: "[[A new link]]", }, { Title: "An external link", Href: "https://domain.com", External: true, + Snippet: "[[An external link]]", }, }, }) @@ -318,6 +327,7 @@ func TestNoteDAOUpdateWithLinks(t *testing.T) { Title: "A new link", Href: "index", Rels: "\x01rel\x01", + Snippet: "[[A new link]]", }, { SourceId: 1, @@ -325,6 +335,7 @@ func TestNoteDAOUpdateWithLinks(t *testing.T) { Title: "An external link", Href: "https://domain.com", External: true, + Snippet: "[[An external link]]", }, }) }) @@ -740,17 +751,17 @@ func queryNoteRow(tx Transaction, where string) (noteRow, error) { } type linkRow struct { - SourceId int64 - TargetId *int64 - Href, Title, Rels string - External bool + SourceId int64 + TargetId *int64 + Href, Title, Rels, Snippet string + External bool } func queryLinkRows(t *testing.T, tx Transaction, where string) []linkRow { links := make([]linkRow, 0) rows, err := tx.Query(fmt.Sprintf(` - SELECT source_id, target_id, title, href, external, rels + SELECT source_id, target_id, title, href, external, rels, snippet FROM links WHERE %v ORDER BY id @@ -759,7 +770,7 @@ func queryLinkRows(t *testing.T, tx Transaction, where string) []linkRow { for rows.Next() { var row linkRow - err = rows.Scan(&row.SourceId, &row.TargetId, &row.Title, &row.Href, &row.External, &row.Rels) + err = rows.Scan(&row.SourceId, &row.TargetId, &row.Title, &row.Href, &row.External, &row.Rels, &row.Snippet) assert.Nil(t, err) links = append(links, row) } diff --git a/core/note/parse.go b/core/note/parse.go index abf6abe..770d231 100644 --- a/core/note/parse.go +++ b/core/note/parse.go @@ -20,6 +20,7 @@ type Link struct { Href string External bool Rels []string + Snippet string } type Parser interface {