From 4d7cba4ffb0c4294a73af1a9a0c688f1818cf9c6 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sat, 23 Sep 2023 09:20:38 -0400 Subject: delete old code Signed-off-by: Xe Iaso --- go.mod | 10 + go.sum | 27 + internal/lume/lume.go | 20 +- lib/jsonfeed/.gitignore | 4 - lib/jsonfeed/Cargo.toml | 17 - lib/jsonfeed/LICENSE-APACHE | 201 ------- lib/jsonfeed/LICENSE-MIT | 25 - lib/jsonfeed/README.adoc | 27 - lib/jsonfeed/src/builder.rs | 211 ------- lib/jsonfeed/src/errors.rs | 6 - lib/jsonfeed/src/feed.rs | 286 --------- lib/jsonfeed/src/item.rs | 529 ----------------- lib/jsonfeed/src/lib.rs | 230 -------- lib/mastodon2text/Cargo.toml | 9 - lib/mastodon2text/src/lib.rs | 39 -- lib/mi/Cargo.toml | 23 - lib/mi/src/lib.rs | 65 --- lib/patreon/.gitignore | 1 - lib/patreon/Cargo.toml | 24 - lib/patreon/examples/campaign.rs | 20 - lib/patreon/src/lib.rs | 238 -------- lib/xesite_markdown/Cargo.toml | 27 - lib/xesite_markdown/src/bin/xemd2html.rs | 15 - lib/xesite_markdown/src/lib.rs | 260 --------- lib/xesite_templates/Cargo.toml | 17 - lib/xesite_templates/src/lib.rs | 219 ------- lib/xesite_types/Cargo.toml | 14 - lib/xesite_types/src/lib.rs | 41 -- lib/xesite_types/src/mastodon.rs | 223 ------- lib/xesite_types/src/testdata/post_attachment.json | 62 -- lib/xesite_types/src/testdata/post_hashtags.json | 59 -- lib/xesite_types/src/testdata/post_mention.json | 54 -- lib/xesite_types/src/testdata/robocadey.json | 97 ---- main.go | 9 +- src/app/config.rs | 391 ------------- src/app/config/markdown_string.rs | 63 -- src/app/mod.rs | 159 ----- src/app/poke.rs | 38 -- src/bin/fetch_mastodon_post.rs | 68 --- src/build.rs | 25 - src/domainsocket.rs | 94 --- src/frontend/.gitignore | 1 - src/frontend/build.sh | 8 - src/frontend/build.ts | 19 - src/frontend/components/ConvSnippet.tsx | 45 -- src/frontend/components/MastodonShareButton.tsx | 77 --- src/frontend/components/NoFunAllowed.tsx | 22 - src/frontend/components/Video.tsx | 40 -- src/frontend/components/WASITerm.tsx | 83 --- src/frontend/deno.json | 14 - src/frontend/deno.lock | 35 -- src/frontend/import_map.json | 17 - src/handlers/api.rs | 92 --- src/handlers/blog.rs | 106 ---- src/handlers/feeds.rs | 76 --- src/handlers/gallery.rs | 47 -- src/handlers/mod.rs | 198 ------- src/handlers/streams.rs | 93 --- src/handlers/talks.rs | 57 -- src/lib.rs | 1 - src/main.rs | 250 -------- src/post/frontmatter.rs | 99 ---- src/post/mod.rs | 226 -------- src/post/schemaorg.rs | 14 - src/signalboost.rs | 21 - src/tmpl/asciiart.txt | 45 -- src/tmpl/blog.rs | 238 -------- src/tmpl/mod.rs | 638 --------------------- src/tmpl/nag.rs | 90 --- 69 files changed, 57 insertions(+), 6542 deletions(-) delete mode 100644 lib/jsonfeed/.gitignore delete mode 100644 lib/jsonfeed/Cargo.toml delete mode 100644 lib/jsonfeed/LICENSE-APACHE delete mode 100644 lib/jsonfeed/LICENSE-MIT delete mode 100644 lib/jsonfeed/README.adoc delete mode 100644 lib/jsonfeed/src/builder.rs delete mode 100644 lib/jsonfeed/src/errors.rs delete mode 100644 lib/jsonfeed/src/feed.rs delete mode 100644 lib/jsonfeed/src/item.rs delete mode 100644 lib/jsonfeed/src/lib.rs delete mode 100644 lib/mastodon2text/Cargo.toml delete mode 100644 lib/mastodon2text/src/lib.rs delete mode 100644 lib/mi/Cargo.toml delete mode 100644 lib/mi/src/lib.rs delete mode 100644 lib/patreon/.gitignore delete mode 100644 lib/patreon/Cargo.toml delete mode 100644 lib/patreon/examples/campaign.rs delete mode 100644 lib/patreon/src/lib.rs delete mode 100644 lib/xesite_markdown/Cargo.toml delete mode 100644 lib/xesite_markdown/src/bin/xemd2html.rs delete mode 100644 lib/xesite_markdown/src/lib.rs delete mode 100644 lib/xesite_templates/Cargo.toml delete mode 100644 lib/xesite_templates/src/lib.rs delete mode 100644 lib/xesite_types/Cargo.toml delete mode 100644 lib/xesite_types/src/lib.rs delete mode 100644 lib/xesite_types/src/mastodon.rs delete mode 100644 lib/xesite_types/src/testdata/post_attachment.json delete mode 100644 lib/xesite_types/src/testdata/post_hashtags.json delete mode 100644 lib/xesite_types/src/testdata/post_mention.json delete mode 100644 lib/xesite_types/src/testdata/robocadey.json delete mode 100644 src/app/config.rs delete mode 100644 src/app/config/markdown_string.rs delete mode 100644 src/app/mod.rs delete mode 100644 src/app/poke.rs delete mode 100644 src/bin/fetch_mastodon_post.rs delete mode 100644 src/build.rs delete mode 100644 src/domainsocket.rs delete mode 100644 src/frontend/.gitignore delete mode 100755 src/frontend/build.sh delete mode 100644 src/frontend/build.ts delete mode 100644 src/frontend/components/ConvSnippet.tsx delete mode 100644 src/frontend/components/MastodonShareButton.tsx delete mode 100644 src/frontend/components/NoFunAllowed.tsx delete mode 100644 src/frontend/components/Video.tsx delete mode 100644 src/frontend/components/WASITerm.tsx delete mode 100644 src/frontend/deno.json delete mode 100644 src/frontend/deno.lock delete mode 100644 src/frontend/import_map.json delete mode 100644 src/handlers/api.rs delete mode 100644 src/handlers/blog.rs delete mode 100644 src/handlers/feeds.rs delete mode 100644 src/handlers/gallery.rs delete mode 100644 src/handlers/mod.rs delete mode 100644 src/handlers/streams.rs delete mode 100644 src/handlers/talks.rs delete mode 100644 src/lib.rs delete mode 100644 src/main.rs delete mode 100644 src/post/frontmatter.rs delete mode 100644 src/post/mod.rs delete mode 100644 src/post/schemaorg.rs delete mode 100644 src/signalboost.rs delete mode 100644 src/tmpl/asciiart.txt delete mode 100644 src/tmpl/blog.rs delete mode 100644 src/tmpl/mod.rs delete mode 100644 src/tmpl/nag.rs diff --git a/go.mod b/go.mod index bd71f70..9122d07 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,8 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudflare/circl v1.3.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -22,18 +24,26 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/prometheus/client_golang v1.15.1 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/sergi/go-diff v1.3.1 // indirect github.com/skeema/knownhosts v1.2.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect + go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 // indirect golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.15.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/tools v0.13.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index f697523..099309c 100644 --- a/go.sum +++ b/go.sum @@ -11,7 +11,11 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= @@ -31,6 +35,8 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojt github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -43,6 +49,11 @@ github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrOb github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -58,6 +69,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -66,6 +79,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= @@ -107,6 +128,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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= @@ -150,6 +172,11 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 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/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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/lume/lume.go b/internal/lume/lume.go index c7947cb..1726a4a 100644 --- a/internal/lume/lume.go +++ b/internal/lume/lume.go @@ -22,12 +22,13 @@ var ( _ fs.ReadFileFS = (*FS)(nil) _ fs.ReadDirFS = (*FS)(nil) - opens = metrics.LabelMap{Label: "name"} - readFiles = metrics.LabelMap{Label: "name"} - readDirs = metrics.LabelMap{Label: "name"} - builds = expvar.NewInt("gauge_xesite_builds") - buildErrors = expvar.NewInt("gauge_xesite_build_errors") - updates = expvar.NewInt("gauge_xesite_updates") + opens = metrics.LabelMap{Label: "name"} + readFiles = metrics.LabelMap{Label: "name"} + readDirs = metrics.LabelMap{Label: "name"} + builds = expvar.NewInt("gauge_xesite_builds") + buildErrors = expvar.NewInt("gauge_xesite_build_errors") + updates = expvar.NewInt("gauge_xesite_updates") + updateErrors = expvar.NewInt("gauge_xesite_update_errors") ) func init() { @@ -124,11 +125,13 @@ func New(ctx context.Context, o *Options) (*FS, error) { } func (f *FS) Update(ctx context.Context) error { + updates.Add(1) f.lock.Lock() defer f.lock.Unlock() wt, err := f.repo.Worktree() if err != nil { + updateErrors.Add(1) return err } @@ -136,6 +139,7 @@ func (f *FS) Update(ctx context.Context) error { ReferenceName: plumbing.NewBranchReferenceName(f.opt.Branch), }) if err != nil { + updateErrors.Add(1) return err } @@ -143,6 +147,7 @@ func (f *FS) Update(ctx context.Context) error { Branch: plumbing.NewBranchReferenceName(f.opt.Branch), }) if err != nil { + updateErrors.Add(1) return err } @@ -151,6 +156,7 @@ func (f *FS) Update(ctx context.Context) error { Commit: plumbing.NewHash("HEAD"), }) if err != nil { + updateErrors.Add(1) return err } @@ -162,6 +168,7 @@ func (f *FS) Update(ctx context.Context) error { } func (f *FS) build(ctx context.Context) error { + builds.Add(1) destDir := filepath.Join(f.repoDir, f.opt.StaticSiteDir, "_site") cmd := exec.CommandContext(ctx, denoLocation, "task", "build", "--location", f.opt.URL, "--quiet") @@ -171,6 +178,7 @@ func (f *FS) build(ctx context.Context) error { cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { + buildErrors.Add(1) return err } diff --git a/lib/jsonfeed/.gitignore b/lib/jsonfeed/.gitignore deleted file mode 100644 index f382b9f..0000000 --- a/lib/jsonfeed/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -target/ -**/*.rs.bk -Cargo.lock -*.html diff --git a/lib/jsonfeed/Cargo.toml b/lib/jsonfeed/Cargo.toml deleted file mode 100644 index a99aa47..0000000 --- a/lib/jsonfeed/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -authors = ["Paul Woolcock ", "Xe Iaso "] -description = "Parser for the JSONFeed (https://jsonfeed.org) specification" -documentation = "https://docs.rs/xe_jsonfeed" -homepage = "https://github.com/Xe/site" -license = "MIT/Apache-2.0" -name = "xe_jsonfeed" -readme = "README.adoc" -version = "0.3.0" - -[dependencies] -error-chain = "0.12" -serde = "1" -serde_derive = "1" -serde_json = "1" - -xesite_types = { path = "../xesite_types" } diff --git a/lib/jsonfeed/LICENSE-APACHE b/lib/jsonfeed/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/lib/jsonfeed/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/lib/jsonfeed/LICENSE-MIT b/lib/jsonfeed/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/lib/jsonfeed/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/lib/jsonfeed/README.adoc b/lib/jsonfeed/README.adoc deleted file mode 100644 index ead4fc6..0000000 --- a/lib/jsonfeed/README.adoc +++ /dev/null @@ -1,27 +0,0 @@ -= JSON Feed Parser - -[link=https://github.com/pwoolcoc/jsonfeed] -image::https://img.shields.io/crates/v/jsonfeed.svg[JSON Feed crate version] - -This is a https://jsonfeed.org[JSON Feed] parser in Rust. Just a thin layer on top of `serde`, but it -provides serialization & deserialization, along with a Builder API for constructing feeds. - -Note that this is alpha, I still need to add a lot of tests and a couple more features. - -== Example - ----- -extern crate jsonfeed; -extern crate reqwest; - -fn main() { - let resp = reqwest::get("https://example.com/feed.json").unwrap(); - let feed = jsonfeed::from_reader(resp).unwrap(); - println!("Feed title is: {}", feed.title); -} ----- - -TODO: - -* Tests. Lots and lots of tests -* Implement ability to add, serialize, and deserialize custom attributes from the json feed spec diff --git a/lib/jsonfeed/src/builder.rs b/lib/jsonfeed/src/builder.rs deleted file mode 100644 index 4ce47a4..0000000 --- a/lib/jsonfeed/src/builder.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::default::Default; - -use errors::*; -use feed::{Attachment, Author, Feed}; -use item::{Content, Item}; - -/// Feed Builder -/// -/// This is used to programmatically build up a Feed object, -/// which can be serialized later into a JSON string -pub struct Builder(Feed); - -impl Builder { - pub fn new() -> Builder { - Builder(Feed::default()) - } - - pub fn title>(mut self, t: I) -> Builder { - self.0.title = t.into(); - self - } - - pub fn home_page_url>(mut self, url: I) -> Builder { - self.0.home_page_url = Some(url.into()); - self - } - - pub fn feed_url>(mut self, url: I) -> Builder { - self.0.feed_url = Some(url.into()); - self - } - - pub fn description>(mut self, desc: I) -> Builder { - self.0.description = Some(desc.into()); - self - } - - pub fn user_comment>(mut self, cmt: I) -> Builder { - self.0.user_comment = Some(cmt.into()); - self - } - - pub fn next_url>(mut self, url: I) -> Builder { - self.0.next_url = Some(url.into()); - self - } - - pub fn icon>(mut self, url: I) -> Builder { - self.0.icon = Some(url.into()); - self - } - - pub fn favicon>(mut self, url: I) -> Builder { - self.0.favicon = Some(url.into()); - self - } - - pub fn author(mut self, author: Author) -> Builder { - self.0.author = Some(author); - self - } - - pub fn expired(mut self) -> Builder { - self.0.expired = Some(true); - self - } - - pub fn item(mut self, item: Item) -> Builder { - self.0.items.push(item); - self - } - - pub fn build(self) -> Feed { - self.0 - } -} - -/// Builder object for an item in a feed -pub struct ItemBuilder { - pub id: Option, - pub url: Option, - pub external_url: Option, - pub title: Option, - pub content: Option, - pub summary: Option, - pub image: Option, - pub banner_image: Option, - pub date_published: Option, - pub date_modified: Option, - pub author: Option, - pub tags: Option>, - pub attachments: Option>, - pub xesite_frontmater: Option, -} - -impl ItemBuilder { - pub fn new() -> ItemBuilder { - ItemBuilder { - id: None, - url: None, - external_url: None, - title: None, - content: None, - summary: None, - image: None, - banner_image: None, - date_published: None, - date_modified: None, - author: None, - tags: None, - attachments: None, - xesite_frontmater: None, - } - } - - pub fn title>(mut self, i: I) -> ItemBuilder { - self.title = Some(i.into()); - self - } - - pub fn image>(mut self, i: I) -> ItemBuilder { - self.image = Some(i.into()); - self - } - - pub fn id>(mut self, i: I) -> ItemBuilder { - self.id = Some(i.into()); - self - } - - pub fn url>(mut self, i: I) -> ItemBuilder { - self.url = Some(i.into()); - self - } - - pub fn external_url>(mut self, i: I) -> ItemBuilder { - self.external_url = Some(i.into()); - self - } - - pub fn date_modified>(mut self, i: I) -> ItemBuilder { - self.date_modified = Some(i.into()); - self - } - - pub fn date_published>(mut self, i: I) -> ItemBuilder { - self.date_published = Some(i.into()); - self - } - - pub fn tags(mut self, tags: Vec) -> ItemBuilder { - self.tags = Some(tags); - self - } - - pub fn author(mut self, who: Author) -> ItemBuilder { - self.author = Some(who); - self - } - - pub fn content_html>(mut self, i: I) -> ItemBuilder { - match self.content { - Some(Content::Text(t)) => { - self.content = Some(Content::Both(i.into(), t)); - } - _ => { - self.content = Some(Content::Html(i.into())); - } - } - self - } - - pub fn content_text>(mut self, i: I) -> ItemBuilder { - match self.content { - Some(Content::Html(s)) => { - self.content = Some(Content::Both(s, i.into())); - } - _ => { - self.content = Some(Content::Text(i.into())); - } - } - self - } - - pub fn xesite_frontmatter(mut self, fm: xesite_types::Frontmatter) -> ItemBuilder { - self.xesite_frontmater = Some(fm); - self - } - - pub fn build(self) -> Result { - if self.id.is_none() || self.content.is_none() { - return Err("missing field 'id' or 'content_*'".into()); - } - Ok(Item { - id: self.id.unwrap(), - url: self.url, - external_url: self.external_url, - title: self.title, - content: self.content.unwrap(), - summary: self.summary, - image: self.image, - banner_image: self.banner_image, - date_published: self.date_published, - date_modified: self.date_modified, - author: self.author, - tags: self.tags, - attachments: self.attachments, - xesite_frontmatter: self.xesite_frontmater, - }) - } -} diff --git a/lib/jsonfeed/src/errors.rs b/lib/jsonfeed/src/errors.rs deleted file mode 100644 index b94779c..0000000 --- a/lib/jsonfeed/src/errors.rs +++ /dev/null @@ -1,6 +0,0 @@ -use serde_json; -error_chain! { - foreign_links { - Serde(serde_json::Error); - } -} diff --git a/lib/jsonfeed/src/feed.rs b/lib/jsonfeed/src/feed.rs deleted file mode 100644 index dc0a2b5..0000000 --- a/lib/jsonfeed/src/feed.rs +++ /dev/null @@ -1,286 +0,0 @@ -use std::default::Default; - -use builder::Builder; -use item::Item; - -const VERSION_1: &str = "https://jsonfeed.org/version/1"; - -/// Represents a single feed -/// -/// # Examples -/// -/// ```rust -/// // Serialize a feed object to a JSON string -/// -/// # extern crate jsonfeed; -/// # use std::default::Default; -/// # use jsonfeed::Feed; -/// # fn main() { -/// let feed: Feed = Feed::default(); -/// assert_eq!( -/// jsonfeed::to_string(&feed).unwrap(), -/// "{\"version\":\"https://jsonfeed.org/version/1\",\"title\":\"\",\"items\":[]}" -/// ); -/// # } -/// ``` -/// -/// ```rust -/// // Deserialize a feed objects from a JSON String -/// -/// # extern crate jsonfeed; -/// # use jsonfeed::Feed; -/// # fn main() { -/// let json = "{\"version\":\"https://jsonfeed.org/version/1\",\"title\":\"\",\"items\":[]}"; -/// let feed: Feed = jsonfeed::from_str(&json).unwrap(); -/// assert_eq!( -/// feed, -/// Feed::default() -/// ); -/// # } -/// ``` -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Feed { - pub version: String, - pub title: String, - pub items: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub home_page_url: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub feed_url: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub user_comment: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub next_url: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub icon: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub favicon: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub author: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub expired: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub hubs: Option>, -} - -impl Feed { - /// Used to construct a Feed object - pub fn builder() -> Builder { - Builder::new() - } -} - -impl Default for Feed { - fn default() -> Feed { - Feed { - version: VERSION_1.to_string(), - title: "".to_string(), - items: vec![], - home_page_url: None, - feed_url: None, - description: None, - user_comment: None, - next_url: None, - icon: None, - favicon: None, - author: None, - expired: None, - hubs: None, - } - } -} - -/// Represents an `attachment` for an item -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Attachment { - url: String, - mime_type: String, - title: Option, - size_in_bytes: Option, - duration_in_seconds: Option, -} - -/// Represents an `author` in both a feed and a feed item -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Author { - name: Option, - url: Option, - avatar: Option, -} - -impl Author { - pub fn new() -> Author { - Author { - name: None, - url: None, - avatar: None, - } - } - - pub fn name>(mut self, name: I) -> Self { - self.name = Some(name.into()); - self - } - - pub fn url>(mut self, url: I) -> Self { - self.url = Some(url.into()); - self - } - - pub fn avatar>(mut self, avatar: I) -> Self { - self.avatar = Some(avatar.into()); - self - } -} - -/// Represents a `hub` for a feed -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Hub { - #[serde(rename = "type")] - type_: String, - url: String, -} - -#[cfg(test)] -mod tests { - use super::*; - use serde_json; - use std::default::Default; - - #[test] - fn serialize_feed() { - let feed = Feed { - version: "https://jsonfeed.org/version/1".to_string(), - title: "some title".to_string(), - items: vec![], - home_page_url: None, - description: None, - expired: Some(true), - ..Default::default() - }; - assert_eq!( - serde_json::to_string(&feed).unwrap(), - r#"{"version":"https://jsonfeed.org/version/1","title":"some title","items":[],"expired":true}"# - ); - } - - #[test] - fn deserialize_feed() { - let json = - r#"{"version":"https://jsonfeed.org/version/1","title":"some title","items":[]}"#; - let feed: Feed = serde_json::from_str(&json).unwrap(); - let expected = Feed { - version: "https://jsonfeed.org/version/1".to_string(), - title: "some title".to_string(), - items: vec![], - ..Default::default() - }; - assert_eq!(feed, expected); - } - - #[test] - fn serialize_attachment() { - let attachment = Attachment { - url: "http://example.com".to_string(), - mime_type: "application/json".to_string(), - title: Some("some title".to_string()), - size_in_bytes: Some(1), - duration_in_seconds: Some(1), - }; - assert_eq!( - serde_json::to_string(&attachment).unwrap(), - r#"{"url":"http://example.com","mime_type":"application/json","title":"some title","size_in_bytes":1,"duration_in_seconds":1}"# - ); - } - - #[test] - fn deserialize_attachment() { - let json = r#"{"url":"http://example.com","mime_type":"application/json","title":"some title","size_in_bytes":1,"duration_in_seconds":1}"#; - let attachment: Attachment = serde_json::from_str(&json).unwrap(); - let expected = Attachment { - url: "http://example.com".to_string(), - mime_type: "application/json".to_string(), - title: Some("some title".to_string()), - size_in_bytes: Some(1), - duration_in_seconds: Some(1), - }; - assert_eq!(attachment, expected); - } - - #[test] - fn serialize_author() { - let author = Author { - name: Some("bob jones".to_string()), - url: Some("http://example.com".to_string()), - avatar: Some("http://img.com/blah".to_string()), - }; - assert_eq!( - serde_json::to_string(&author).unwrap(), - r#"{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"# - ); - } - - #[test] - fn deserialize_author() { - let json = - r#"{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"#; - let author: Author = serde_json::from_str(&json).unwrap(); - let expected = Author { - name: Some("bob jones".to_string()), - url: Some("http://example.com".to_string()), - avatar: Some("http://img.com/blah".to_string()), - }; - assert_eq!(author, expected); - } - - #[test] - fn serialize_hub() { - let hub = Hub { - type_: "some-type".to_string(), - url: "http://example.com".to_string(), - }; - assert_eq!( - serde_json::to_string(&hub).unwrap(), - r#"{"type":"some-type","url":"http://example.com"}"# - ) - } - - #[test] - fn deserialize_hub() { - let json = r#"{"type":"some-type","url":"http://example.com"}"#; - let hub: Hub = serde_json::from_str(&json).unwrap(); - let expected = Hub { - type_: "some-type".to_string(), - url: "http://example.com".to_string(), - }; - assert_eq!(hub, expected); - } - - #[test] - fn deser_podcast() { - let json = r#"{ - "version": "https://jsonfeed.org/version/1", - "title": "Timetable", - "home_page_url": "http://timetable.manton.org/", - "items": [ - { - "id": "http://timetable.manton.org/2017/04/episode-45-launch-week/", - "url": "http://timetable.manton.org/2017/04/episode-45-launch-week/", - "title": "Episode 45: Launch week", - "content_html": "I’m rolling out early access to Micro.blog this week. I talk about how the first 2 days have gone, mistakes with TestFlight, and what to do next.", - "date_published": "2017-04-26T01:09:45+00:00", - "attachments": [ - { - "url": "http://timetable.manton.org/podcast-download/139/episode-45-launch-week.mp3", - "mime_type": "audio/mpeg", - "size_in_bytes": 5236920 - } - ] - } - ] -}"#; - serde_json::from_str::(&json).expect("Failed to deserialize podcast feed"); - } -} diff --git a/lib/jsonfeed/src/item.rs b/lib/jsonfeed/src/item.rs deleted file mode 100644 index 49593ab..0000000 --- a/lib/jsonfeed/src/item.rs +++ /dev/null @@ -1,529 +0,0 @@ -use std::default::Default; -use std::fmt; - -use builder::ItemBuilder; -use feed::{Attachment, Author}; - -use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; -use serde::ser::{Serialize, SerializeStruct, Serializer}; - -/// Represents the `content_html` and `content_text` attributes of an item -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub enum Content { - Html(String), - Text(String), - Both(String, String), -} - -/// Represents an item in a feed -#[derive(Debug, Clone, PartialEq)] -pub struct Item { - pub id: String, - pub url: Option, - pub external_url: Option, - pub title: Option, - pub content: Content, - pub summary: Option, - pub image: Option, - pub banner_image: Option, - pub date_published: Option, // todo DateTime objects? - pub date_modified: Option, - pub author: Option, - pub tags: Option>, - pub attachments: Option>, - - // xesite extensions - pub xesite_frontmatter: Option, -} - -impl Item { - pub fn builder() -> ItemBuilder { - ItemBuilder::new() - } -} - -impl Default for Item { - fn default() -> Item { - Item { - id: "".to_string(), - url: None, - external_url: None, - title: None, - content: Content::Text("".into()), - summary: None, - image: None, - banner_image: None, - date_published: None, - date_modified: None, - author: None, - tags: None, - attachments: None, - xesite_frontmatter: None, - } - } -} - -impl Serialize for Item { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut state = serializer.serialize_struct("Item", 14)?; - state.serialize_field("id", &self.id)?; - if self.url.is_some() { - state.serialize_field("url", &self.url)?; - } - if self.external_url.is_some() { - state.serialize_field("external_url", &self.external_url)?; - } - if self.title.is_some() { - state.serialize_field("title", &self.title)?; - } - match self.content { - Content::Html(ref s) => { - state.serialize_field("content_html", s)?; - state.serialize_field("content_text", &None::>)?; - } - Content::Text(ref s) => { - state.serialize_field("content_html", &None::>)?; - state.serialize_field("content_text", s)?; - } - Content::Both(ref s, ref t) => { - state.serialize_field("content_html", s)?; - state.serialize_field("content_text", t)?; - } - }; - if self.summary.is_some() { - state.serialize_field("summary", &self.summary)?; - } - if self.image.is_some() { - state.serialize_field("image", &self.image)?; - } - if self.banner_image.is_some() { - state.serialize_field("banner_image", &self.banner_image)?; - } - if self.date_published.is_some() { - state.serialize_field("date_published", &self.date_published)?; - } - if self.date_modified.is_some() { - state.serialize_field("date_modified", &self.date_modified)?; - } - if self.author.is_some() { - state.serialize_field("author", &self.author)?; - } - if self.tags.is_some() { - state.serialize_field("tags", &self.tags)?; - } - if self.attachments.is_some() { - state.serialize_field("attachments", &self.attachments)?; - } - if self.xesite_frontmatter.is_some() { - state.serialize_field("_xesite_frontmatter", &self.xesite_frontmatter)?; - } - state.end() - } -} - -impl<'de> Deserialize<'de> for Item { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - enum Field { - Id, - Url, - ExternalUrl, - Title, - ContentHtml, - ContentText, - Summary, - Image, - BannerImage, - DatePublished, - DateModified, - Author, - Tags, - Attachments, - } - - impl<'de> Deserialize<'de> for Field { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct FieldVisitor; - - impl<'de> Visitor<'de> for FieldVisitor { - type Value = Field; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("non-expected field") - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - match value { - "id" => Ok(Field::Id), - "url" => Ok(Field::Url), - "external_url" => Ok(Field::ExternalUrl), - "title" => Ok(Field::Title), - "content_html" => Ok(Field::ContentHtml), - "content_text" => Ok(Field::ContentText), - "summary" => Ok(Field::Summary), - "image" => Ok(Field::Image), - "banner_image" => Ok(Field::BannerImage), - "date_published" => Ok(Field::DatePublished), - "date_modified" => Ok(Field::DateModified), - "author" => Ok(Field::Author), - "tags" => Ok(Field::Tags), - "attachments" => Ok(Field::Attachments), - _ => Err(de::Error::unknown_field(value, FIELDS)), - } - } - } - - deserializer.deserialize_identifier(FieldVisitor) - } - } - - struct ItemVisitor; - - impl<'de> Visitor<'de> for ItemVisitor { - type Value = Item; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("non-expected thing") - } - - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - let mut id = None; - let mut url = None; - let mut external_url = None; - let mut title = None; - let mut content_html: Option = None; - let mut content_text: Option = None; - let mut summary = None; - let mut image = None; - let mut banner_image = None; - let mut date_published = None; - let mut date_modified = None; - let mut author = None; - let mut tags = None; - let mut attachments = None; - - while let Some(key) = map.next_key()? { - match key { - Field::Id => { - if id.is_some() { - return Err(de::Error::duplicate_field("id")); - } - id = Some(map.next_value()?); - } - Field::Url => { - if url.is_some() { - return Err(de::Error::duplicate_field("url")); - } - url = map.next_value()?; - } - Field::ExternalUrl => { - if external_url.is_some() { - return Err(de::Error::duplicate_field("external_url")); - } - external_url = map.next_value()?; - } - Field::Title => { - if title.is_some() { - return Err(de::Error::duplicate_field("title")); - } - title = map.next_value()?; - } - Field::ContentHtml => { - if content_html.is_some() { - return Err(de::Error::duplicate_field("content_html")); - } - content_html = map.next_value()?; - } - Field::ContentText => { - if content_text.is_some() { - return Err(de::Error::duplicate_field("content_text")); - } - content_text = map.next_value()?; - } - Field::Summary => { - if summary.is_some() { - return Err(de::Error::duplicate_field("summary")); - } - summary = map.next_value()?; - } - Field::Image => { - if image.is_some() { - return Err(de::Error::duplicate_field("image")); - } - image = map.next_value()?; - } - Field::BannerImage => { - if banner_image.is_some() { - return Err(de::Error::duplicate_field("banner_image")); - } - banner_image = map.next_value()?; - } - Field::DatePublished => { - if date_published.is_some() { - return Err(de::Error::duplicate_field("date_published")); - } - date_published = map.next_value()?; - } - Field::DateModified => { - if date_modified.is_some() { - return Err(de::Error::duplicate_field("date_modified")); - } - date_modified = map.next_value()?; - } - Field::Author => { - if author.is_some() { - return Err(de::Error::duplicate_field("author")); - } - author = map.next_value()?; - } - Field::Tags => { - if tags.is_some() { - return Err(de::Error::duplicate_field("tags")); - } - tags = map.next_value()?; - } - Field::Attachments => { - if attachments.is_some() { - return Err(de::Error::duplicate_field("attachments")); - } - attachments = map.next_value()?; - } - } - } - - let id = id.ok_or_else(|| de::Error::missing_field("id"))?; - let content = match (content_html, content_text) { - (Some(s), Some(t)) => Content::Both(s, t), - (Some(s), _) => Content::Html(s), - (_, Some(t)) => Content::Text(t), - _ => return Err(de::Error::missing_field("content_html or content_text")), - }; - - Ok(Item { - id, - url, - external_url, - title, - content, - summary, - image, - banner_image, - date_published, - date_modified, - author, - tags, - attachments, - xesite_frontmatter: None, - }) - } - } - - const FIELDS: &[&str] = &[ - "id", - "url", - "external_url", - "title", - "content", - "summary", - "image", - "banner_image", - "date_published", - "date_modified", - "author", - "tags", - "attachments", - ]; - deserializer.deserialize_struct("Item", FIELDS, ItemVisitor) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use feed::Author; - use serde_json; - - #[test] - #[allow(non_snake_case)] - fn serialize_item__content_html() { - let item = Item { - id: "1".into(), - url: Some("http://example.com/feed.json".into()), - external_url: Some("http://example.com/feed.json".into()), - title: Some("feed title".into()), - content: Content::Html("

content

".into()), - summary: Some("feed summary".into()), - image: Some("http://img.com/blah".into()), - banner_image: Some("http://img.com/blah".into()), - date_published: Some("2017-01-01 10:00:00".into()), - date_modified: Some("2017-01-01 10:00:00".into()), - author: Some( - Author::new() - .name("bob jones") - .url("http://example.com") - .avatar("http://img.com/blah"), - ), - tags: Some(vec!["json".into(), "feed".into()]), - attachments: Some(vec![]), - }; - assert_eq!( - serde_json::to_string(&item).unwrap(), - r#"{"id":"1","url":"http://example.com/feed.json","external_url":"http://example.com/feed.json","title":"feed title","content_html":"

content

","content_text":null,"summary":"feed summary","image":"http://img.com/blah","banner_image":"http://img.com/blah","date_published":"2017-01-01 10:00:00","date_modified":"2017-01-01 10:00:00","author":{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"},"tags":["json","feed"],"attachments":[]}"# - ); - } - - #[test] - #[allow(non_snake_case)] - fn serialize_item__content_text() { - let item = Item { - id: "1".into(), - url: Some("http://example.com/feed.json".into()), - external_url: Some("http://example.com/feed.json".into()), - title: Some("feed title".into()), - content: Content::Text("content".into()), - summary: Some("feed summary".into()), - image: Some("http://img.com/blah".into()), - banner_image: Some("http://img.com/blah".into()), - date_published: Some("2017-01-01 10:00:00".into()), - date_modified: Some("2017-01-01 10:00:00".into()), - author: Some( - Author::new() - .name("bob jones") - .url("http://example.com") - .avatar("http://img.com/blah"), - ), - tags: Some(vec!["json".into(), "feed".into()]), - attachments: Some(vec![]), - }; - assert_eq!( - serde_json::to_string(&item).unwrap(), - r#"{"id":"1","url":"http://example.com/feed.json","external_url":"http://example.com/feed.json","title":"feed title","content_html":null,"content_text":"content","summary":"