repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
91aad91
parent
090d8de
author
ChloƩ Vulquin
date
2024-03-08 13:51:02 +0000 UTC
mdparser: implicitly capture hashtags in document

When they're found, they will be rendered as so:
`<span class="hashtag">...</span>`.

They are ignored in the following:
* block code sections
* block quote sections
* span code sections

This list can be expanded.

We then collect all of the matching hashtags and provide them as
metadata, but only if there is no explicit frontmatter for them.
So a workaround for undesirable hashtag detection is to use front-matter
to specify `tags: []` or similar.
3 files changed,  +44, -0
M go.mod
M go.sum
M go.mod
+2, -0
 1@@ -64,6 +64,7 @@ require (
 2 	github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d // indirect
 3 	github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 // indirect
 4 	github.com/dustin/go-humanize v1.0.1 // indirect
 5+	github.com/forPelevin/gomoji v1.1.3 // indirect
 6 	github.com/go-errors/errors v1.5.1 // indirect
 7 	github.com/go-logfmt/logfmt v0.6.0 // indirect
 8 	github.com/go-ole/go-ole v1.3.0 // indirect
 9@@ -115,6 +116,7 @@ require (
10 	github.com/tklauser/go-sysconf v0.3.12 // indirect
11 	github.com/tklauser/numcpus v0.6.1 // indirect
12 	github.com/yusufpapurcu/wmi v1.2.3 // indirect
13+	go.abhg.dev/goldmark/hashtag v0.3.1 // indirect
14 	golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
15 	golang.org/x/net v0.19.0 // indirect
16 	golang.org/x/sync v0.6.0 // indirect
M go.sum
+4, -0
 1@@ -76,6 +76,8 @@ github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349/go.mod h1:KVK+/
 2 github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
 3 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
 4 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
 5+github.com/forPelevin/gomoji v1.1.3 h1:7c3dYzVmYhpOL3bS4riXqSWJBX3BhSvH68yoNNf3FH0=
 6+github.com/forPelevin/gomoji v1.1.3/go.mod h1:ypB7Kz3Fsp+LVR7KoT7mEFOioYBuTuAtaAT4RGl+ASY=
 7 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 8 github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
 9 github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
10@@ -261,6 +263,8 @@ github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFi
11 github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
12 go.abhg.dev/goldmark/anchor v0.1.1 h1:NUH3hAzhfeymRqZKOkSoFReZlEAmfXBZlbXEzpD2Qgc=
13 go.abhg.dev/goldmark/anchor v0.1.1/go.mod h1:zYKiaHXTdugwVJRZqInVdmNGQRM3ZRJ6AGBC7xP7its=
14+go.abhg.dev/goldmark/hashtag v0.3.1 h1:k0FQwEtVQ1SstIRR2fqDJ4VNYUS0AXLp869V0qHOZMg=
15+go.abhg.dev/goldmark/hashtag v0.3.1/go.mod h1:rXtvxXPL7auhPMGRdG02UrXn/9LMm6PNdP5HO64zbVU=
16 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
17 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
18 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
M shared/mdparser.go
+38, -0
 1@@ -3,6 +3,7 @@ package shared
 2 import (
 3 	"bytes"
 4 	"fmt"
 5+	"sort"
 6 	"strings"
 7 	"time"
 8 
 9@@ -18,6 +19,7 @@ import (
10 	ghtml "github.com/yuin/goldmark/renderer/html"
11 	gtext "github.com/yuin/goldmark/text"
12 	"go.abhg.dev/goldmark/anchor"
13+	"go.abhg.dev/goldmark/hashtag"
14 	yaml "gopkg.in/yaml.v2"
15 )
16 
17@@ -187,6 +189,7 @@ func ParseText(text string) (*ParsedText, error) {
18 			extension.GFM,
19 			extension.Footnote,
20 			meta.Meta,
21+			&hashtag.Extender{}, // TODO: resolver to make them links
22 			hili,
23 			&anchor.Extender{
24 				Position: anchor.Before,
25@@ -290,6 +293,41 @@ func ParseText(text string) (*ParsedText, error) {
26 	if err != nil {
27 		return &parsed, err
28 	}
29+	// fill from hashtag ASTs as fallback
30+	if len(tags) == 0 {
31+		// collect all matching tags
32+		err = ast.Walk(doc, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
33+			switch n.Kind() {
34+			// ignore hashtags inside of these sections
35+			case ast.KindBlockquote, ast.KindCodeBlock, ast.KindCodeSpan:
36+				return ast.WalkSkipChildren, nil
37+			// register hashtags
38+			case hashtag.Kind:
39+				t := n.(*hashtag.Node)
40+				if entering { // only add each tag once
41+					tags = append(tags, string(t.Tag))
42+				}
43+			}
44+			// out-of-switch default
45+			return ast.WalkContinue, nil
46+		})
47+		if err != nil {
48+			panic(err)
49+		}
50+
51+		// sort and deduplicate results
52+		sort.Strings(tags)
53+		e := 1
54+		for i := 1; i < len(tags); i++ {
55+			// this works because we're keeping tags[0]
56+			if tags[i] == tags[i-1] {
57+				continue
58+			}
59+			tags[e] = tags[i]
60+			e++
61+		}
62+		tags = tags[:e]
63+	}
64 	parsed.MetaData.Tags = tags
65 
66 	// Rendering happens last to allow any of the previous steps to manipulate