diff --git a/.github/workflows/emojiscraper.yml b/.github/workflows/emojiscraper.yml
new file mode 100644
index 0000000..d17ae94
--- /dev/null
+++ b/.github/workflows/emojiscraper.yml
@@ -0,0 +1,32 @@
+name: Emojiscraper
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * 0' # Runs every Sunday at midnight UTC
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: 1.22
+
+ - name: Run emojiscraper
+ run: make emojiscraper
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v5
+ with:
+ token: ${{ secrets.PAT }}
+ commit-message: Update dependencies
+ branch: emojiscraper-updates
+ commit-message: Update from weekly emojiscraper run
+ title: "Weekly Emojiscraper Update"
+ body: "Automated update from the weekly Emojiscraper run."
diff --git a/Makefile b/Makefile
index 7e3c83b..03eb949 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,26 @@
.PHONY: all format lint clean
+# If the first argument is "run"...
+ifeq (run,$(firstword $(MAKECMDGOALS)))
+ # use the rest as arguments for "run"
+ RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
+ # ...and turn them into do-nothing targets
+ $(eval $(RUN_ARGS):;@:)
+endif
+
GOCMD=go
LDFLAGS="-s -w ${LDFLAGS_OPT}"
all: build format lint ## Format, lint and build
run: ## Run
- go run main.go
+ go run -tags debug main.go $(RUN_ARGS)
+
+emojiscraper: ## Run emojiscraper
+ go run -tags debug main.go emojiscraper defaults/static/emojis pkg/emoji_map.go
build: ## Build
- go build -o bin/go-grip main.go
+ go build -tags debug -o bin/go-grip main.go
test: ## Test
${GOCMD} test ./...
diff --git a/README.md b/README.md
index 752523d..792559f 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
## ⚡️Features
-* ⚡️Written in Go
+* ⚡️Written in Go :+1: :steam_locomotive:
* 📄 Render markdown to HTML and view it in your browser
* 📱 Dark and white mode
* 🎨 Syntax highlighting for code
diff --git a/cmd/emojiscraper.go b/cmd/emojiscraper.go
new file mode 100644
index 0000000..6a062f4
--- /dev/null
+++ b/cmd/emojiscraper.go
@@ -0,0 +1,26 @@
+//go:build debug
+// +build debug
+
+package cmd
+
+import (
+ "errors"
+
+ "github.com/chrishrb/go-grip/internal"
+ "github.com/spf13/cobra"
+)
+
+var emojiscraperCmd = &cobra.Command{
+ Use: "emojiscraper [emoji-out] [emoji-map-out]",
+ Short: "Scrape emojis from gist",
+ Run: func(cmd *cobra.Command, args []string) {
+ if len(args) != 2 {
+ cobra.CheckErr(errors.New("provide exact 2 arguments"))
+ }
+ internal.ScrapeEmojis(args[0], args[1])
+ },
+}
+
+func init() {
+ rootCmd.AddCommand(emojiscraperCmd)
+}
diff --git a/defaults/static/emojis/bowtie.png b/defaults/static/emojis/bowtie.png
new file mode 100644
index 0000000..5616d69
Binary files /dev/null and b/defaults/static/emojis/bowtie.png differ
diff --git a/defaults/static/emojis/feelsgood.png b/defaults/static/emojis/feelsgood.png
new file mode 100644
index 0000000..891ec43
Binary files /dev/null and b/defaults/static/emojis/feelsgood.png differ
diff --git a/defaults/static/emojis/finnadie.png b/defaults/static/emojis/finnadie.png
new file mode 100644
index 0000000..90266e2
Binary files /dev/null and b/defaults/static/emojis/finnadie.png differ
diff --git a/defaults/static/emojis/goberserk.png b/defaults/static/emojis/goberserk.png
new file mode 100644
index 0000000..e617a9d
Binary files /dev/null and b/defaults/static/emojis/goberserk.png differ
diff --git a/defaults/static/emojis/godmode.png b/defaults/static/emojis/godmode.png
new file mode 100644
index 0000000..551111a
Binary files /dev/null and b/defaults/static/emojis/godmode.png differ
diff --git a/defaults/static/emojis/hurtrealbad.png b/defaults/static/emojis/hurtrealbad.png
new file mode 100644
index 0000000..6055841
Binary files /dev/null and b/defaults/static/emojis/hurtrealbad.png differ
diff --git a/defaults/static/emojis/neckbeard.png b/defaults/static/emojis/neckbeard.png
new file mode 100644
index 0000000..69ccffc
Binary files /dev/null and b/defaults/static/emojis/neckbeard.png differ
diff --git a/defaults/static/emojis/octocat.png b/defaults/static/emojis/octocat.png
new file mode 100644
index 0000000..f9050b9
Binary files /dev/null and b/defaults/static/emojis/octocat.png differ
diff --git a/defaults/static/emojis/rage1.png b/defaults/static/emojis/rage1.png
new file mode 100644
index 0000000..99a28f2
Binary files /dev/null and b/defaults/static/emojis/rage1.png differ
diff --git a/defaults/static/emojis/rage2.png b/defaults/static/emojis/rage2.png
new file mode 100644
index 0000000..e91813c
Binary files /dev/null and b/defaults/static/emojis/rage2.png differ
diff --git a/defaults/static/emojis/rage3.png b/defaults/static/emojis/rage3.png
new file mode 100644
index 0000000..36f0733
Binary files /dev/null and b/defaults/static/emojis/rage3.png differ
diff --git a/defaults/static/emojis/rage4.png b/defaults/static/emojis/rage4.png
new file mode 100644
index 0000000..d1b87ba
Binary files /dev/null and b/defaults/static/emojis/rage4.png differ
diff --git a/defaults/static/emojis/shipit.png b/defaults/static/emojis/shipit.png
new file mode 100644
index 0000000..2d018e6
Binary files /dev/null and b/defaults/static/emojis/shipit.png differ
diff --git a/defaults/static/emojis/suspect.png b/defaults/static/emojis/suspect.png
new file mode 100644
index 0000000..c4fd15c
Binary files /dev/null and b/defaults/static/emojis/suspect.png differ
diff --git a/defaults/static/emojis/trollface.png b/defaults/static/emojis/trollface.png
new file mode 100644
index 0000000..ee463dc
Binary files /dev/null and b/defaults/static/emojis/trollface.png differ
diff --git a/go.mod b/go.mod
index b84e1b7..4056428 100644
--- a/go.mod
+++ b/go.mod
@@ -1,18 +1,36 @@
module github.com/chrishrb/go-grip
-go 1.22.7
+go 1.23
+
+toolchain go1.23.3
require (
+ github.com/PuerkitoBio/goquery v1.10.0 // indirect
github.com/aarol/reload v1.1.3 // indirect
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
+ github.com/andybalholm/cascadia v1.3.2 // indirect
+ github.com/antchfx/htmlquery v1.3.3 // indirect
+ github.com/antchfx/xmlquery v1.4.2 // indirect
+ github.com/antchfx/xpath v1.3.3 // indirect
github.com/bep/debounce v1.2.1 // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/gobwas/glob v0.2.3 // indirect
+ github.com/gocolly/colly v1.2.0 // indirect
+ github.com/gocolly/colly/v2 v2.1.0 // indirect
+ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
+ github.com/kennygrant/sanitize v1.2.4 // indirect
+ github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- golang.org/x/net v0.19.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
+ github.com/temoto/robotstxt v1.1.2 // indirect
+ golang.org/x/net v0.32.0 // indirect
+ golang.org/x/sys v0.28.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
+ google.golang.org/appengine v1.6.8 // indirect
+ google.golang.org/protobuf v1.36.0 // indirect
)
diff --git a/go.sum b/go.sum
index 28ab25c..917504f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,28 +1,195 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
+github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4=
+github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4=
github.com/aarol/reload v1.1.3 h1:cL/LnKVJq1nb9DkOte9kRbPk2qmShFAAItyhvZRlxoA=
github.com/aarol/reload v1.1.3/go.mod h1:TmwcyY3/j9gx1Tn3pGjanIQwd/weeFEJFNRTsn7wFDI=
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
+github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
+github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
+github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
+github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
+github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE=
+github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU=
+github.com/antchfx/xmlquery v1.2.4/go.mod h1:KQQuESaxSlqugE2ZBcM/qn+ebIpt+d+4Xx7YcSGAIrM=
+github.com/antchfx/xmlquery v1.4.2 h1:MZKd9+wblwxfQ1zd1AdrTsqVaMjMCwow3IqkCSe00KA=
+github.com/antchfx/xmlquery v1.4.2/go.mod h1:QXhvf5ldTuGqhd1SHNvvtlhhdQLks4dD0awIVhXIDTA=
+github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
+github.com/antchfx/xpath v1.1.8/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
+github.com/antchfx/xpath v1.3.2/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
+github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs=
+github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
+github.com/gocolly/colly v1.2.0 h1:qRz9YAn8FIH0qzgNUw+HT9UN7wm1oF9OBAilwEWpyrI=
+github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA=
+github.com/gocolly/colly/v2 v2.1.0 h1:k0DuZkDoCsx51bKpRJNEmcxcp+W5N8ziuwGaSDuFoGs=
+github.com/gocolly/colly/v2 v2.1.0/go.mod h1:I2MuhsLjQ+Ex+IzK3afNS8/1qP3AedHOusRPcRdC5o0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8 h1:4txT5G2kqVAKMjzidIabL/8KqjIK71yj30YOeuxLn10=
github.com/gomarkdown/markdown v0.0.0-20240930133441-72d49d9543d8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg=
+github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
+github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
+github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
+github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
+github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg=
+github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
+golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
+golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
+google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
+google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/emoji.go b/internal/emoji.go
new file mode 100644
index 0000000..5959ac1
--- /dev/null
+++ b/internal/emoji.go
@@ -0,0 +1,130 @@
+package internal
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+ "text/template"
+
+ "github.com/gocolly/colly/v2"
+)
+
+const emojiMapTemplate = `// Code generated by cmd/emojiscraper. DO NOT EDIT.
+
+package pkg
+
+var EmojiMap = map[string]string{
+{{- range $key, $value := . }}
+ "{{$key}}": "{{$value}}",
+{{- end }}
+}`
+
+func ScrapeEmojis(emojiOut string, emojiMapOut string) {
+ c := colly.NewCollector(
+ colly.AllowedDomains("gist.github.com"),
+ )
+
+ emojiMap := map[string]string{}
+
+ c.OnHTML("th", func(e *colly.HTMLElement) {
+ code, icon := getEmojiFromHtml(emojiOut, e)
+ if code != "" {
+ emojiMap[code] = icon
+ }
+ })
+
+ c.OnHTML("td", func(e *colly.HTMLElement) {
+ code, icon := getEmojiFromHtml(emojiOut, e)
+ if code != "" {
+ emojiMap[code] = icon
+ }
+ })
+
+ c.OnRequest(func(r *colly.Request) {
+ fmt.Println("Visiting", r.URL.String())
+ })
+
+ if err := c.Visit("https://gist.github.com/rxaviers/7360908"); err != nil {
+ panic(err)
+ }
+
+ if err := createEmojiMapFile(emojiMap, emojiMapOut); err != nil {
+ panic(err)
+ }
+}
+
+func getEmojiFromHtml(outPath string, e *colly.HTMLElement) (string, string) {
+ content := strings.Split(e.Text, " ")
+
+ if e.ChildText("code") == "" {
+ return "", ""
+ }
+
+ emoji := strings.TrimSpace(content[0])
+ if emoji == "" {
+ url := e.ChildAttr("img", "src")
+ path, err := downloadIcon(outPath, url)
+ if err != nil {
+ panic(err)
+ }
+ emoji = path
+ }
+
+ if emoji == content[1] {
+ return "", ""
+ }
+
+ return content[1], emoji
+}
+
+func downloadIcon(baseDir, url string) (string, error) {
+ resp, err := http.Get(url)
+ if err != nil {
+ return "", fmt.Errorf("failed to download file: %v", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return "", fmt.Errorf("bad status: %s", resp.Status)
+ }
+
+ parts := strings.Split(url, "/")
+ fileName := parts[len(parts)-1]
+ destPath := filepath.Join(baseDir, fileName)
+ htmlPath := filepath.Join("/static/emojis", fileName)
+
+ if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil {
+ return "", fmt.Errorf("failed to create directories: %v", err)
+ }
+
+ out, err := os.Create(destPath)
+ if err != nil {
+ return "", fmt.Errorf("failed to create file: %v", err)
+ }
+ defer out.Close()
+
+ _, err = io.Copy(out, resp.Body)
+ if err != nil {
+ return "", fmt.Errorf("failed to write file: %v", err)
+ }
+
+ return htmlPath, nil
+}
+
+func createEmojiMapFile(emojiMap map[string]string, outputPath string) error {
+ file, err := os.Create(outputPath)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ tmpl, err := template.New("emojiMap").Parse(emojiMapTemplate)
+ if err != nil {
+ return err
+ }
+
+ return tmpl.Execute(file, emojiMap)
+}
diff --git a/pkg/emoji_map.go b/pkg/emoji_map.go
new file mode 100644
index 0000000..f3181e1
--- /dev/null
+++ b/pkg/emoji_map.go
@@ -0,0 +1,868 @@
+// Code generated by cmd/emojiscraper. DO NOT EDIT.
+
+package pkg
+
+var EmojiMap = map[string]string{
+ ":+1:": "👍",
+ ":-1:": "👎",
+ ":100:": "💯",
+ ":1234:": "🔢",
+ ":8ball:": "🎱",
+ ":a:": "🅰️",
+ ":ab:": "🆎",
+ ":abc:": "🔤",
+ ":abcd:": "🔡",
+ ":accept:": "🉑",
+ ":aerial_tramway:": "🚡",
+ ":airplane:": "✈️",
+ ":alarm_clock:": "⏰",
+ ":alien:": "👽",
+ ":ambulance:": "🚑",
+ ":anchor:": "⚓",
+ ":angel:": "👼",
+ ":anger:": "💢",
+ ":angry:": "😠",
+ ":anguished:": "😧",
+ ":ant:": "🐜",
+ ":apple:": "🍎",
+ ":aquarius:": "♒",
+ ":aries:": "♈",
+ ":arrow_backward:": "◀️",
+ ":arrow_double_down:": "⏬",
+ ":arrow_double_up:": "⏫",
+ ":arrow_down:": "⬇️",
+ ":arrow_down_small:": "🔽",
+ ":arrow_forward:": "▶️",
+ ":arrow_heading_down:": "⤵️",
+ ":arrow_heading_up:": "⤴️",
+ ":arrow_left:": "⬅️",
+ ":arrow_lower_left:": "↙️",
+ ":arrow_lower_right:": "↘️",
+ ":arrow_right:": "➡️",
+ ":arrow_right_hook:": "↪️",
+ ":arrow_up:": "⬆️",
+ ":arrow_up_down:": "↕️",
+ ":arrow_up_small:": "🔼",
+ ":arrow_upper_left:": "↖️",
+ ":arrow_upper_right:": "↗️",
+ ":arrows_clockwise:": "🔃",
+ ":arrows_counterclockwise:": "🔄",
+ ":art:": "🎨",
+ ":articulated_lorry:": "🚛",
+ ":astonished:": "😲",
+ ":atm:": "🏧",
+ ":b:": "🅱️",
+ ":baby:": "👶",
+ ":baby_bottle:": "🍼",
+ ":baby_chick:": "🐤",
+ ":baby_symbol:": "🚼",
+ ":baggage_claim:": "🛄",
+ ":balloon:": "🎈",
+ ":ballot_box_with_check:": "☑️",
+ ":bamboo:": "🎍",
+ ":banana:": "🍌",
+ ":bangbang:": "‼️",
+ ":bank:": "🏦",
+ ":bar_chart:": "📊",
+ ":barber:": "💈",
+ ":baseball:": "⚾",
+ ":basketball:": "🏀",
+ ":bath:": "🛀",
+ ":bathtub:": "🛁",
+ ":battery:": "🔋",
+ ":bear:": "🐻",
+ ":beer:": "🍺",
+ ":beers:": "🍻",
+ ":beetle:": "🪲",
+ ":beginner:": "🔰",
+ ":bell:": "🔔",
+ ":bento:": "🍱",
+ ":bicyclist:": "🚴",
+ ":bike:": "🚲",
+ ":bikini:": "👙",
+ ":bird:": "🐦",
+ ":birthday:": "🎂",
+ ":black_circle:": "⚫",
+ ":black_joker:": "🃏",
+ ":black_nib:": "✒️",
+ ":black_square_button:": "🔲",
+ ":blossom:": "🌼",
+ ":blowfish:": "🐡",
+ ":blue_book:": "📘",
+ ":blue_car:": "🚙",
+ ":blue_heart:": "💙",
+ ":blush:": "😊",
+ ":boar:": "🐗",
+ ":boat:": "⛵",
+ ":bomb:": "💣",
+ ":book:": "📖",
+ ":bookmark:": "🔖",
+ ":bookmark_tabs:": "📑",
+ ":books:": "📚",
+ ":boom:": "💥",
+ ":boot:": "👢",
+ ":bouquet:": "💐",
+ ":bow:": "🙇",
+ ":bowling:": "🎳",
+ ":bowtie:": "/static/emojis/bowtie.png",
+ ":boy:": "👦",
+ ":bread:": "🍞",
+ ":bride_with_veil:": "👰♀️",
+ ":bridge_at_night:": "🌉",
+ ":briefcase:": "💼",
+ ":broken_heart:": "💔",
+ ":bug:": "🐛",
+ ":bulb:": "💡",
+ ":bullettrain_front:": "🚅",
+ ":bullettrain_side:": "🚄",
+ ":bus:": "🚌",
+ ":busstop:": "🚏",
+ ":bust_in_silhouette:": "👤",
+ ":busts_in_silhouette:": "👥",
+ ":cactus:": "🌵",
+ ":cake:": "🍰",
+ ":calendar:": "📆",
+ ":calling:": "📲",
+ ":camel:": "🐫",
+ ":camera:": "📷",
+ ":cancer:": "♋",
+ ":candy:": "🍬",
+ ":capital_abcd:": "🔠",
+ ":capricorn:": "♑",
+ ":car:": "🚗",
+ ":card_index:": "📇",
+ ":carousel_horse:": "🎠",
+ ":cat2:": "🐈",
+ ":cat:": "🐱",
+ ":cd:": "💿",
+ ":chart:": "💹",
+ ":chart_with_downwards_trend:": "📉",
+ ":chart_with_upwards_trend:": "📈",
+ ":checkered_flag:": "🏁",
+ ":cherries:": "🍒",
+ ":cherry_blossom:": "🌸",
+ ":chestnut:": "🌰",
+ ":chicken:": "🐔",
+ ":children_crossing:": "🚸",
+ ":chocolate_bar:": "🍫",
+ ":christmas_tree:": "🎄",
+ ":church:": "⛪",
+ ":cinema:": "🎦",
+ ":circus_tent:": "🎪",
+ ":city_sunrise:": "🌇",
+ ":city_sunset:": "🌆",
+ ":cl:": "🆑",
+ ":clap:": "👏",
+ ":clapper:": "🎬",
+ ":clipboard:": "📋",
+ ":clock1030:": "🕥",
+ ":clock10:": "🕙",
+ ":clock1130:": "🕦",
+ ":clock11:": "🕚",
+ ":clock1230:": "🕧",
+ ":clock12:": "🕛",
+ ":clock130:": "🕜",
+ ":clock1:": "🕐",
+ ":clock230:": "🕝",
+ ":clock2:": "🕑",
+ ":clock330:": "🕞",
+ ":clock3:": "🕒",
+ ":clock430:": "🕟",
+ ":clock4:": "🕓",
+ ":clock530:": "🕠",
+ ":clock5:": "🕔",
+ ":clock630:": "🕡",
+ ":clock6:": "🕕",
+ ":clock730:": "🕢",
+ ":clock7:": "🕖",
+ ":clock830:": "🕣",
+ ":clock8:": "🕗",
+ ":clock930:": "🕤",
+ ":clock9:": "🕘",
+ ":closed_book:": "📕",
+ ":closed_lock_with_key:": "🔐",
+ ":closed_umbrella:": "🌂",
+ ":cloud:": "☁️",
+ ":clubs:": "♣️",
+ ":cn:": "🇨🇳",
+ ":cocktail:": "🍸",
+ ":coffee:": "☕",
+ ":cold_sweat:": "😰",
+ ":collision:": "💥",
+ ":computer:": "💻",
+ ":confetti_ball:": "🎊",
+ ":confounded:": "😖",
+ ":confused:": "😕",
+ ":congratulations:": "㊗️",
+ ":construction:": "🚧",
+ ":construction_worker:": "👷",
+ ":convenience_store:": "🏪",
+ ":cookie:": "🍪",
+ ":cool:": "🆒",
+ ":cop:": "👮",
+ ":copyright:": "©️",
+ ":corn:": "🌽",
+ ":couple:": "👫",
+ ":couple_with_heart:": "💑",
+ ":couplekiss:": "💏",
+ ":cow2:": "🐄",
+ ":cow:": "🐮",
+ ":credit_card:": "💳",
+ ":crocodile:": "🐊",
+ ":crossed_flags:": "🎌",
+ ":crown:": "👑",
+ ":cry:": "😢",
+ ":crying_cat_face:": "😿",
+ ":crystal_ball:": "🔮",
+ ":cupid:": "💘",
+ ":curly_loop:": "➰",
+ ":currency_exchange:": "💱",
+ ":curry:": "🍛",
+ ":custard:": "🍮",
+ ":customs:": "🛃",
+ ":cyclone:": "🌀",
+ ":dancer:": "💃",
+ ":dancers:": "👯",
+ ":dango:": "🍡",
+ ":dart:": "🎯",
+ ":dash:": "💨",
+ ":date:": "📅",
+ ":de:": "🇩🇪",
+ ":deciduous_tree:": "🌳",
+ ":department_store:": "🏬",
+ ":diamond_shape_with_a_dot_inside:": "💠",
+ ":diamonds:": "♦️",
+ ":disappointed:": "😞",
+ ":disappointed_relieved:": "😥",
+ ":dizzy:": "💫",
+ ":dizzy_face:": "😵",
+ ":do_not_litter:": "🚯",
+ ":dog2:": "🐕",
+ ":dog:": "🐶",
+ ":dollar:": "💵",
+ ":dolls:": "🎎",
+ ":dolphin:": "🐬",
+ ":door:": "🚪",
+ ":doughnut:": "🍩",
+ ":dragon:": "🐉",
+ ":dragon_face:": "🐲",
+ ":dress:": "👗",
+ ":dromedary_camel:": "🐪",
+ ":droplet:": "💧",
+ ":dvd:": "📀",
+ ":e-mail:": "📧",
+ ":ear:": "👂",
+ ":ear_of_rice:": "🌾",
+ ":earth_africa:": "🌍",
+ ":earth_americas:": "🌎",
+ ":earth_asia:": "🌏",
+ ":egg:": "🥚",
+ ":eggplant:": "🍆",
+ ":eight:": "8️⃣",
+ ":eight_pointed_black_star:": "✴️",
+ ":eight_spoked_asterisk:": "✳️",
+ ":electric_plug:": "🔌",
+ ":elephant:": "🐘",
+ ":email:": "📧",
+ ":end:": "🔚",
+ ":envelope:": "✉️",
+ ":es:": "🇪🇸",
+ ":euro:": "💶",
+ ":european_castle:": "🏰",
+ ":european_post_office:": "🏤",
+ ":evergreen_tree:": "🌲",
+ ":exclamation:": "❗",
+ ":expressionless:": "😑",
+ ":eyeglasses:": "👓",
+ ":eyes:": "👀",
+ ":facepunch:": "👊",
+ ":factory:": "🏭",
+ ":fallen_leaf:": "🍂",
+ ":family:": "👪",
+ ":fast_forward:": "⏩",
+ ":fax:": "📠",
+ ":fearful:": "😨",
+ ":feelsgood:": "/static/emojis/feelsgood.png",
+ ":feet:": "🐾",
+ ":ferris_wheel:": "🎡",
+ ":file_folder:": "📁",
+ ":finnadie:": "/static/emojis/finnadie.png",
+ ":fire:": "🔥",
+ ":fire_engine:": "🚒",
+ ":fireworks:": "🎆",
+ ":first_quarter_moon:": "🌓",
+ ":first_quarter_moon_with_face:": "🌛",
+ ":fish:": "🐟",
+ ":fish_cake:": "🍥",
+ ":fishing_pole_and_fish:": "🎣",
+ ":fist:": "✊",
+ ":five:": "5️⃣",
+ ":flags:": "🎏",
+ ":flashlight:": "🔦",
+ ":floppy_disk:": "💾",
+ ":flower_playing_cards:": "🎴",
+ ":flushed:": "😳",
+ ":foggy:": "🌁",
+ ":football:": "🏈",
+ ":fork_and_knife:": "🍴",
+ ":fountain:": "⛲",
+ ":four:": "4️⃣",
+ ":four_leaf_clover:": "🍀",
+ ":fr:": "🇫🇷",
+ ":free:": "🆓",
+ ":fried_shrimp:": "🍤",
+ ":fries:": "🍟",
+ ":frog:": "🐸",
+ ":frowning:": "😦",
+ ":fu:": "🖕",
+ ":fuelpump:": "⛽",
+ ":full_moon:": "🌕",
+ ":full_moon_with_face:": "🌝",
+ ":game_die:": "🎲",
+ ":gb:": "🇬🇧",
+ ":gem:": "💎",
+ ":gemini:": "♊",
+ ":ghost:": "👻",
+ ":gift:": "🎁",
+ ":gift_heart:": "💝",
+ ":girl:": "👧",
+ ":globe_with_meridians:": "🌐",
+ ":goat:": "🐐",
+ ":goberserk:": "/static/emojis/goberserk.png",
+ ":godmode:": "/static/emojis/godmode.png",
+ ":golf:": "⛳",
+ ":grapes:": "🍇",
+ ":green_apple:": "🍏",
+ ":green_book:": "📗",
+ ":green_heart:": "💚",
+ ":grey_exclamation:": "❕",
+ ":grey_question:": "❔",
+ ":grimacing:": "😬",
+ ":grin:": "😁",
+ ":grinning:": "😀",
+ ":guardsman:": "💂♂️",
+ ":guitar:": "🎸",
+ ":gun:": "🔫",
+ ":haircut:": "💇",
+ ":hamburger:": "🍔",
+ ":hammer:": "🔨",
+ ":hamster:": "🐹",
+ ":hand:": "✋",
+ ":handbag:": "👜",
+ ":hankey:": "💩",
+ ":hash:": "#️⃣",
+ ":hatched_chick:": "🐥",
+ ":hatching_chick:": "🐣",
+ ":headphones:": "🎧",
+ ":hear_no_evil:": "🙉",
+ ":heart:": "❤️",
+ ":heart_decoration:": "💟",
+ ":heart_eyes:": "😍",
+ ":heart_eyes_cat:": "😻",
+ ":heartbeat:": "💓",
+ ":heartpulse:": "💗",
+ ":hearts:": "♥️",
+ ":heavy_check_mark:": "✔️",
+ ":heavy_division_sign:": "➗",
+ ":heavy_dollar_sign:": "💲",
+ ":heavy_exclamation_mark:": "❗",
+ ":heavy_minus_sign:": "➖",
+ ":heavy_multiplication_x:": "✖️",
+ ":heavy_plus_sign:": "➕",
+ ":helicopter:": "🚁",
+ ":herb:": "🌿",
+ ":hibiscus:": "🌺",
+ ":high_brightness:": "🔆",
+ ":high_heel:": "👠",
+ ":hocho:": "🔪",
+ ":honey_pot:": "🍯",
+ ":honeybee:": "🐝",
+ ":horse:": "🐴",
+ ":horse_racing:": "🏇",
+ ":hospital:": "🏥",
+ ":hotel:": "🏨",
+ ":hotsprings:": "♨️",
+ ":hourglass:": "⌛",
+ ":hourglass_flowing_sand:": "⏳",
+ ":house:": "🏠",
+ ":house_with_garden:": "🏡",
+ ":hurtrealbad:": "/static/emojis/hurtrealbad.png",
+ ":hushed:": "😯",
+ ":ice_cream:": "🍨",
+ ":icecream:": "🍦",
+ ":id:": "🆔",
+ ":ideograph_advantage:": "🉐",
+ ":imp:": "👿",
+ ":inbox_tray:": "📥",
+ ":incoming_envelope:": "📨",
+ ":information_desk_person:": "💁",
+ ":information_source:": "ℹ️",
+ ":innocent:": "😇",
+ ":interrobang:": "⁉️",
+ ":iphone:": "📱",
+ ":it:": "🇮🇹",
+ ":izakaya_lantern:": "🏮",
+ ":jack_o_lantern:": "🎃",
+ ":japan:": "🗾",
+ ":japanese_castle:": "🏯",
+ ":japanese_goblin:": "👺",
+ ":japanese_ogre:": "👹",
+ ":jeans:": "👖",
+ ":joy:": "😂",
+ ":joy_cat:": "😹",
+ ":jp:": "🇯🇵",
+ ":key:": "🔑",
+ ":keycap_ten:": "🔟",
+ ":kimono:": "👘",
+ ":kiss:": "💋",
+ ":kissing:": "😗",
+ ":kissing_cat:": "😽",
+ ":kissing_closed_eyes:": "😚",
+ ":kissing_heart:": "😘",
+ ":kissing_smiling_eyes:": "😙",
+ ":koala:": "🐨",
+ ":koko:": "🈁",
+ ":kr:": "🇰🇷",
+ ":large_blue_circle:": "🔵",
+ ":large_blue_diamond:": "🔷",
+ ":large_orange_diamond:": "🔶",
+ ":last_quarter_moon:": "🌗",
+ ":last_quarter_moon_with_face:": "🌜",
+ ":laughing:": "😆",
+ ":leaves:": "🍃",
+ ":ledger:": "📒",
+ ":left_luggage:": "🛅",
+ ":left_right_arrow:": "↔️",
+ ":leftwards_arrow_with_hook:": "↩️",
+ ":lemon:": "🍋",
+ ":leo:": "♌",
+ ":leopard:": "🐆",
+ ":libra:": "♎",
+ ":light_rail:": "🚈",
+ ":link:": "🔗",
+ ":lips:": "👄",
+ ":lipstick:": "💄",
+ ":lock:": "🔒",
+ ":lock_with_ink_pen:": "🔏",
+ ":lollipop:": "🍭",
+ ":loop:": "➿",
+ ":loudspeaker:": "📢",
+ ":love_hotel:": "🏩",
+ ":love_letter:": "💌",
+ ":low_brightness:": "🔅",
+ ":m:": "Ⓜ️",
+ ":mag:": "🔍",
+ ":mag_right:": "🔎",
+ ":mahjong:": "🀄",
+ ":mailbox:": "📫",
+ ":mailbox_closed:": "📪",
+ ":mailbox_with_mail:": "📬",
+ ":mailbox_with_no_mail:": "📭",
+ ":man:": "👨",
+ ":man_with_gua_pi_mao:": "👲",
+ ":man_with_turban:": "👳♂️",
+ ":mans_shoe:": "👞",
+ ":maple_leaf:": "🍁",
+ ":mask:": "😷",
+ ":massage:": "💆",
+ ":meat_on_bone:": "🍖",
+ ":mega:": "📣",
+ ":melon:": "🍈",
+ ":memo:": "📝",
+ ":mens:": "🚹",
+ ":metal:": "🤘",
+ ":metro:": "🚇",
+ ":microphone:": "🎤",
+ ":microscope:": "🔬",
+ ":milky_way:": "🌌",
+ ":minibus:": "🚐",
+ ":minidisc:": "💽",
+ ":mobile_phone_off:": "📴",
+ ":money_with_wings:": "💸",
+ ":moneybag:": "💰",
+ ":monkey:": "🐒",
+ ":monkey_face:": "🐵",
+ ":monorail:": "🚝",
+ ":moon:": "🌔",
+ ":mortar_board:": "🎓",
+ ":mount_fuji:": "🗻",
+ ":mountain_bicyclist:": "🚵",
+ ":mountain_cableway:": "🚠",
+ ":mountain_railway:": "🚞",
+ ":mouse2:": "🐁",
+ ":mouse:": "🐭",
+ ":movie_camera:": "🎥",
+ ":moyai:": "🗿",
+ ":muscle:": "💪",
+ ":mushroom:": "🍄",
+ ":musical_keyboard:": "🎹",
+ ":musical_note:": "🎵",
+ ":musical_score:": "🎼",
+ ":mute:": "🔇",
+ ":nail_care:": "💅",
+ ":name_badge:": "📛",
+ ":neckbeard:": "/static/emojis/neckbeard.png",
+ ":necktie:": "👔",
+ ":negative_squared_cross_mark:": "❎",
+ ":neutral_face:": "😐",
+ ":new:": "🆕",
+ ":new_moon:": "🌑",
+ ":new_moon_with_face:": "🌚",
+ ":newspaper:": "📰",
+ ":ng:": "🆖",
+ ":nine:": "9️⃣",
+ ":no_bell:": "🔕",
+ ":no_bicycles:": "🚳",
+ ":no_entry:": "⛔",
+ ":no_entry_sign:": "🚫",
+ ":no_good:": "🙅",
+ ":no_mobile_phones:": "📵",
+ ":no_mouth:": "😶",
+ ":no_pedestrians:": "🚷",
+ ":no_smoking:": "🚭",
+ ":non-potable_water:": "🚱",
+ ":nose:": "👃",
+ ":notebook:": "📓",
+ ":notebook_with_decorative_cover:": "📔",
+ ":notes:": "🎶",
+ ":nut_and_bolt:": "🔩",
+ ":o2:": "🅾️",
+ ":o:": "⭕",
+ ":ocean:": "🌊",
+ ":octocat:": "/static/emojis/octocat.png",
+ ":octopus:": "🐙",
+ ":oden:": "🍢",
+ ":office:": "🏢",
+ ":ok:": "🆗",
+ ":ok_hand:": "👌",
+ ":ok_woman:": "🙆♀️",
+ ":older_man:": "👴",
+ ":older_woman:": "👵",
+ ":on:": "🔛",
+ ":oncoming_automobile:": "🚘",
+ ":oncoming_bus:": "🚍",
+ ":oncoming_police_car:": "🚔",
+ ":oncoming_taxi:": "🚖",
+ ":one:": "1️⃣",
+ ":open_file_folder:": "📂",
+ ":open_hands:": "👐",
+ ":open_mouth:": "😮",
+ ":ophiuchus:": "⛎",
+ ":orange_book:": "📙",
+ ":outbox_tray:": "📤",
+ ":ox:": "🐂",
+ ":page_facing_up:": "📄",
+ ":page_with_curl:": "📃",
+ ":pager:": "📟",
+ ":palm_tree:": "🌴",
+ ":panda_face:": "🐼",
+ ":paperclip:": "📎",
+ ":parking:": "🅿️",
+ ":part_alternation_mark:": "〽️",
+ ":partly_sunny:": "⛅",
+ ":passport_control:": "🛂",
+ ":paw_prints:": "🐾",
+ ":peach:": "🍑",
+ ":pear:": "🍐",
+ ":pencil2:": "✏️",
+ ":pencil:": "📝",
+ ":penguin:": "🐧",
+ ":pensive:": "😔",
+ ":performing_arts:": "🎭",
+ ":persevere:": "😣",
+ ":phone:": "☎️",
+ ":pig2:": "🐖",
+ ":pig:": "🐷",
+ ":pig_nose:": "🐽",
+ ":pill:": "💊",
+ ":pineapple:": "🍍",
+ ":pisces:": "♓",
+ ":pizza:": "🍕",
+ ":point_down:": "👇",
+ ":point_left:": "👈",
+ ":point_right:": "👉",
+ ":point_up:": "☝️",
+ ":point_up_2:": "👆",
+ ":police_car:": "🚓",
+ ":poodle:": "🐩",
+ ":poop:": "💩",
+ ":post_office:": "🏣",
+ ":postal_horn:": "📯",
+ ":postbox:": "📮",
+ ":potable_water:": "🚰",
+ ":pouch:": "👝",
+ ":poultry_leg:": "🍗",
+ ":pound:": "💷",
+ ":pouting_cat:": "😾",
+ ":pray:": "🙏",
+ ":princess:": "👸",
+ ":punch:": "👊",
+ ":purple_heart:": "💜",
+ ":purse:": "👛",
+ ":pushpin:": "📌",
+ ":put_litter_in_its_place:": "🚮",
+ ":question:": "❓",
+ ":rabbit2:": "🐇",
+ ":rabbit:": "🐰",
+ ":racehorse:": "🐎",
+ ":radio:": "📻",
+ ":radio_button:": "🔘",
+ ":rage1:": "/static/emojis/rage1.png",
+ ":rage2:": "/static/emojis/rage2.png",
+ ":rage3:": "/static/emojis/rage3.png",
+ ":rage4:": "/static/emojis/rage4.png",
+ ":rage:": "😡",
+ ":railway_car:": "🚃",
+ ":rainbow:": "🌈",
+ ":raised_hand:": "✋",
+ ":raised_hands:": "🙌",
+ ":raising_hand:": "🙋",
+ ":ram:": "🐏",
+ ":ramen:": "🍜",
+ ":rat:": "🐀",
+ ":recycle:": "♻️",
+ ":red_car:": "🚗",
+ ":red_circle:": "🔴",
+ ":registered:": "®️",
+ ":relaxed:": "☺️",
+ ":relieved:": "😌",
+ ":repeat:": "🔁",
+ ":repeat_one:": "🔂",
+ ":restroom:": "🚻",
+ ":revolving_hearts:": "💞",
+ ":rewind:": "⏪",
+ ":ribbon:": "🎀",
+ ":rice:": "🍚",
+ ":rice_ball:": "🍙",
+ ":rice_cracker:": "🍘",
+ ":rice_scene:": "🎑",
+ ":ring:": "💍",
+ ":rocket:": "🚀",
+ ":roller_coaster:": "🎢",
+ ":rooster:": "🐓",
+ ":rose:": "🌹",
+ ":rotating_light:": "🚨",
+ ":round_pushpin:": "📍",
+ ":rowboat:": "🚣",
+ ":ru:": "🇷🇺",
+ ":rugby_football:": "🏉",
+ ":runner:": "🏃",
+ ":running:": "🏃",
+ ":running_shirt_with_sash:": "🎽",
+ ":sa:": "🈂️",
+ ":sagittarius:": "♐",
+ ":sailboat:": "⛵",
+ ":sake:": "🍶",
+ ":sandal:": "👡",
+ ":santa:": "🎅",
+ ":satellite:": "📡",
+ ":satisfied:": "😆",
+ ":saxophone:": "🎷",
+ ":school:": "🏫",
+ ":school_satchel:": "🎒",
+ ":scissors:": "✂️",
+ ":scorpius:": "♏",
+ ":scream:": "😱",
+ ":scream_cat:": "🙀",
+ ":scroll:": "📜",
+ ":seat:": "💺",
+ ":secret:": "㊙️",
+ ":see_no_evil:": "🙈",
+ ":seedling:": "🌱",
+ ":seven:": "7️⃣",
+ ":shaved_ice:": "🍧",
+ ":sheep:": "🐑",
+ ":shell:": "🐚",
+ ":ship:": "🚢",
+ ":shipit:": "/static/emojis/shipit.png",
+ ":shirt:": "👕",
+ ":shit:": "💩",
+ ":shoe:": "👞",
+ ":shower:": "🚿",
+ ":signal_strength:": "📶",
+ ":six:": "6️⃣",
+ ":six_pointed_star:": "🔯",
+ ":ski:": "🎿",
+ ":skull:": "💀",
+ ":sleeping:": "😴",
+ ":sleepy:": "😪",
+ ":slot_machine:": "🎰",
+ ":small_blue_diamond:": "🔹",
+ ":small_orange_diamond:": "🔸",
+ ":small_red_triangle:": "🔺",
+ ":small_red_triangle_down:": "🔻",
+ ":smile:": "😄",
+ ":smile_cat:": "😸",
+ ":smiley:": "😃",
+ ":smiley_cat:": "😺",
+ ":smiling_imp:": "😈",
+ ":smirk:": "😏",
+ ":smirk_cat:": "😼",
+ ":smoking:": "🚬",
+ ":snail:": "🐌",
+ ":snake:": "🐍",
+ ":snowboarder:": "🏂",
+ ":snowflake:": "❄️",
+ ":snowman:": "⛄",
+ ":sob:": "😭",
+ ":soccer:": "⚽",
+ ":soon:": "🔜",
+ ":sos:": "🆘",
+ ":sound:": "🔉",
+ ":space_invader:": "👾",
+ ":spades:": "♠️",
+ ":spaghetti:": "🍝",
+ ":sparkler:": "🎇",
+ ":sparkles:": "✨",
+ ":sparkling_heart:": "💖",
+ ":speak_no_evil:": "🙊",
+ ":speaker:": "🔈",
+ ":speech_balloon:": "💬",
+ ":speedboat:": "🚤",
+ ":star2:": "🌟",
+ ":star:": "⭐",
+ ":stars:": "🌠",
+ ":station:": "🚉",
+ ":statue_of_liberty:": "🗽",
+ ":steam_locomotive:": "🚂",
+ ":stew:": "🍲",
+ ":straight_ruler:": "📏",
+ ":strawberry:": "🍓",
+ ":stuck_out_tongue:": "😛",
+ ":stuck_out_tongue_closed_eyes:": "😝",
+ ":stuck_out_tongue_winking_eye:": "😜",
+ ":sun_with_face:": "🌞",
+ ":sunflower:": "🌻",
+ ":sunglasses:": "😎",
+ ":sunny:": "☀️",
+ ":sunrise:": "🌅",
+ ":sunrise_over_mountains:": "🌄",
+ ":surfer:": "🏄",
+ ":sushi:": "🍣",
+ ":suspect:": "/static/emojis/suspect.png",
+ ":suspension_railway:": "🚟",
+ ":sweat:": "😓",
+ ":sweat_drops:": "💦",
+ ":sweat_smile:": "😅",
+ ":sweet_potato:": "🍠",
+ ":swimmer:": "🏊",
+ ":symbols:": "🔣",
+ ":syringe:": "💉",
+ ":tada:": "🎉",
+ ":tanabata_tree:": "🎋",
+ ":tangerine:": "🍊",
+ ":taurus:": "♉",
+ ":taxi:": "🚕",
+ ":tea:": "🍵",
+ ":telephone:": "☎️",
+ ":telephone_receiver:": "📞",
+ ":telescope:": "🔭",
+ ":tennis:": "🎾",
+ ":tent:": "⛺",
+ ":thought_balloon:": "💭",
+ ":three:": "3️⃣",
+ ":thumbsdown:": "👎",
+ ":thumbsup:": "👍",
+ ":ticket:": "🎫",
+ ":tiger2:": "🐅",
+ ":tiger:": "🐯",
+ ":tired_face:": "😫",
+ ":tm:": "™️",
+ ":toilet:": "🚽",
+ ":tokyo_tower:": "🗼",
+ ":tomato:": "🍅",
+ ":tongue:": "👅",
+ ":top:": "🔝",
+ ":tophat:": "🎩",
+ ":tractor:": "🚜",
+ ":traffic_light:": "🚥",
+ ":train2:": "🚆",
+ ":train:": "🚋",
+ ":tram:": "🚊",
+ ":triangular_flag_on_post:": "🚩",
+ ":triangular_ruler:": "📐",
+ ":trident:": "🔱",
+ ":triumph:": "😤",
+ ":trolleybus:": "🚎",
+ ":trollface:": "/static/emojis/trollface.png",
+ ":trophy:": "🏆",
+ ":tropical_drink:": "🍹",
+ ":tropical_fish:": "🐠",
+ ":truck:": "🚚",
+ ":trumpet:": "🎺",
+ ":tshirt:": "👕",
+ ":tulip:": "🌷",
+ ":turtle:": "🐢",
+ ":tv:": "📺",
+ ":twisted_rightwards_arrows:": "🔀",
+ ":two:": "2️⃣",
+ ":two_hearts:": "💕",
+ ":two_men_holding_hands:": "👬",
+ ":two_women_holding_hands:": "👭",
+ ":u5272:": "🈹",
+ ":u5408:": "🈴",
+ ":u55b6:": "🈺",
+ ":u6307:": "🈯",
+ ":u6708:": "🈷️",
+ ":u6709:": "🈶",
+ ":u6e80:": "🈵",
+ ":u7121:": "🈚",
+ ":u7533:": "🈸",
+ ":u7981:": "🈲",
+ ":u7a7a:": "🈳",
+ ":uk:": "🇬🇧",
+ ":umbrella:": "☔",
+ ":unamused:": "😒",
+ ":underage:": "🔞",
+ ":unlock:": "🔓",
+ ":up:": "🆙",
+ ":us:": "🇺🇸",
+ ":v:": "✌️",
+ ":vertical_traffic_light:": "🚦",
+ ":vhs:": "📼",
+ ":vibration_mode:": "📳",
+ ":video_camera:": "📹",
+ ":video_game:": "🎮",
+ ":violin:": "🎻",
+ ":virgo:": "♍",
+ ":volcano:": "🌋",
+ ":vs:": "🆚",
+ ":walking:": "🚶",
+ ":waning_crescent_moon:": "🌘",
+ ":waning_gibbous_moon:": "🌖",
+ ":warning:": "⚠️",
+ ":watch:": "⌚",
+ ":water_buffalo:": "🐃",
+ ":watermelon:": "🍉",
+ ":wave:": "👋",
+ ":wavy_dash:": "〰️",
+ ":waxing_crescent_moon:": "🌒",
+ ":waxing_gibbous_moon:": "🌔",
+ ":wc:": "🚾",
+ ":weary:": "😩",
+ ":wedding:": "💒",
+ ":whale2:": "🐋",
+ ":whale:": "🐳",
+ ":wheelchair:": "♿",
+ ":white_check_mark:": "✅",
+ ":white_circle:": "⚪",
+ ":white_flower:": "💮",
+ ":white_square_button:": "🔳",
+ ":wind_chime:": "🎐",
+ ":wine_glass:": "🍷",
+ ":wink:": "😉",
+ ":wolf:": "🐺",
+ ":woman:": "👩",
+ ":womans_clothes:": "👚",
+ ":womans_hat:": "👒",
+ ":womens:": "🚺",
+ ":worried:": "😟",
+ ":wrench:": "🔧",
+ ":x:": "❌",
+ ":yellow_heart:": "💛",
+ ":yen:": "💴",
+ ":yum:": "😋",
+ ":zap:": "⚡",
+ ":zero:": "0️⃣",
+ ":zzz:": "💤",
+}
diff --git a/pkg/parser.go b/pkg/parser.go
index fb4a44e..88d57ff 100644
--- a/pkg/parser.go
+++ b/pkg/parser.go
@@ -7,6 +7,7 @@ import (
"io"
"log"
"path/filepath"
+ "regexp"
"strings"
"github.com/alecthomas/chroma/v2/quick"
@@ -118,16 +119,34 @@ func renderHookBlockquote(w io.Writer, node ast.Node, entering bool) (ast.WalkSt
func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) {
block := node.(*ast.Text)
+ r := regexp.MustCompile(`(:\S+:)`)
+ withEmoji := r.ReplaceAllStringFunc(string(block.Literal), func(s string) string {
+ val, ok := EmojiMap[s]
+ if !ok {
+ return s
+ }
+
+ if strings.HasPrefix(val, "/") {
+ return fmt.Sprintf(`
`, s, s, val)
+ }
+
+ return val
+ })
+
paragraph, ok := block.GetParent().(*ast.Paragraph)
if !ok {
- return ast.GoToNext, false
+ _, err := io.WriteString(w, withEmoji)
+ if err != nil {
+ log.Println("Error:", err)
+ }
+ return ast.GoToNext, true
}
_, ok = paragraph.GetParent().(*ast.BlockQuote)
if ok {
// Remove prefixes
for _, b := range blockquotes {
- content, found := strings.CutPrefix(string(block.Literal), fmt.Sprintf("[!%s]", strings.ToUpper(b)))
+ content, found := strings.CutPrefix(withEmoji, fmt.Sprintf("[!%s]", strings.ToUpper(b)))
if found {
_, err := io.WriteString(w, content)
if err != nil {
@@ -140,7 +159,7 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) {
_, ok = paragraph.GetParent().(*ast.ListItem)
if ok {
- content, found := strings.CutPrefix(string(block.Literal), "[ ]")
+ content, found := strings.CutPrefix(withEmoji, "[ ]")
content = ` ` + content
if found {
_, err := io.WriteString(w, content)
@@ -150,7 +169,7 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) {
return ast.GoToNext, true
}
- content, found = strings.CutPrefix(string(block.Literal), "[x]")
+ content, found = strings.CutPrefix(withEmoji, "[x]")
content = ` ` + content
if found {
_, err := io.WriteString(w, content)
@@ -160,7 +179,11 @@ func renderHookText(w io.Writer, node ast.Node) (ast.WalkStatus, bool) {
}
}
- return ast.GoToNext, false
+ _, err := io.WriteString(w, withEmoji)
+ if err != nil {
+ log.Println("Error:", err)
+ }
+ return ast.GoToNext, true
}
func renderHookListItem(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {