intitial commit

Dozens B. McCuzzins 2023-10-30 11:23:47 -06:00
commit eb46f77010
7 changed files with 377 additions and 0 deletions

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
www/index.html
www/webring.opml

43
README.md 100644
View File

@ -0,0 +1,43 @@
# DOZENSRING
> a webring for the dozensweb
## ABOUT
this project provides a webcomponent
for members of the dozensweb
it should:
- provide "next" and "previous" links, and a link to the index
- link to an opml file for all sites that provide a feed
- store member info in a recfile
see it live at https://tilde.town/~dozens/webring/dozens/
## GETTING STARTED
everything you need to know to get started
is in `src/example.html`.
you will need:
- git
- a text editor
- (optional) just: a task runner.
https://github.com/casey/just
- (optional) GNU recutils: a plain text database.
https://www.gnu.org/software/recutils/
## CONTRIBUTING
1. Download the code
2. Add an entry to the recfile
3. email a patch to dozens@tilde.team

124
db/members.rec 100644
View File

@ -0,0 +1,124 @@
%rec: member
%doc: a member of the webring
%key: id
%unique: id name url feed
%auto: id created
%type: id int
%type: created date
%type: title,url,feed line
%typedef: Name_t regexp /[a-z]{3,13}/
%type: name Name_t
%allowed: id created title name url feed
%mandatory: id title name url
%sort: id
id: 0
created: Thu, 12 Oct 2023 18:51:39 -0600
title: tilde.town
name: town
url: http://tilde.town/~dozens/
id: 1
created: Thu, 12 Oct 2023 18:52:05 -0600
title: dozens and dragons
name: dozensanddragons
url: https://dozensanddragons.neocities.org/
feed: https://dozensanddragons.neocities.org/rss.xml
id: 2
created: Thu, 12 Oct 2023 18:52:45 -0600
title: supervegan
name: supervegan
url: https://supervegan.neocities.org/
feed: https://supervegan.neocities.org/feed.xml
id: 3
created: Thu, 12 Oct 2023 18:53:18 -0600
title: Society For Putting Things On Top Of Other Things
name: society
url: https://society.neocities.org/
feed: https://society.neocities.org/rss.xml
id: 4
created: Thu, 12 Oct 2023 18:53:58 -0600
title: dream journal
name: dreams
url: https://tilde.team/~dozens/dreams/
feed: https://tilde.team/~dozens/dreams/rss.xml
id: 5
created: Thu, 12 Oct 2023 18:56:55 -0600
title: tildewhirl podcast
name: tildewhirl
url: http://tilde.town/~dozens/podcast/
feed: http://tilde.town/~dozens/podcast/rss.xml
id: 6
created: Thu, 12 Oct 2023 19:01:23 -0600
title: list blog
name: lists
url: http://tilde.town/~dozens/listblog/
feed: http://tilde.town/~dozens/listblog/feed.xml
id: 7
created: Thu, 12 Oct 2023 19:01:55 -0600
title: consume
name: consume
url: http://tilde.town/~dozens/consume/
feed: https://tilde.town/~dozens/consume/feed.xml
id: 8
created: Thu, 12 Oct 2023 19:07:48 -0600
title: piblog
name: piblog
url: http://tilde.town/~dozens/piblog/
feed: http://tilde.town/~dozens/piblog/feed.xml
id: 9
created: Thu, 12 Oct 2023 19:08:44 -0600
title: status cafe
name: statuscafe
url: https://status.cafe/users/dozens
feed: https://status.cafe/users/dozens.atom
id: 10
created: Thu, 12 Oct 2023 19:10:05 -0600
title: mastodon
name: mastodon
url: https://tiny.tilde.website/@dozens
feed: https://tiny.tilde.website/@dozens.rss
id: 11
created: Thu, 12 Oct 2023 19:11:34 -0600
title: linkhut
name: linkhut
url: https://ln.ht/~dozens
feed: https://ln.ht/_/feed/~dozens
id: 12
created: Thu, 12 Oct 2023 19:12:35 -0600
title: peertube
name: peertube
url: https://tube.tchncs.de/a/dozens/video-channels
feed: https://tube.tchncs.de/feeds/videos.xml?accountId=47463
id: 13
created: Thu, 12 Oct 2023 19:13:08 -0600
title: basement quest
name: quest
url: http://tilde.town/~dozens/quest/
feed: ttps://tilde.town/~dozens/quest/rss.xml
id: 14
created: Fri, 13 Oct 2023 19:28:08 -0600
title: gamelog
name: gamelog
url: http://tilde.town/~dozens/gamelog/
feed: https://tilde.town/~dozens/gamelog/feed.xml
id: 15
created: Fri, 13 Oct 2023 19:29:38 -0600
title: pro toad and superb owl
name: protoad
url: https://git.tilde.town/dozens/protoadandsuperbowl/
feed: https://git.tilde.town/dozens/protoadandsuperbowl/raw/branch/master/feed.xml

49
justfile 100644
View File

@ -0,0 +1,49 @@
# list all recipes
default:
just --list --unsorted
# add a new webring member
new:
#!/usr/bin/env sh
read -p "name (lowercase, 3-13 characters): " name
read -p "title: " title
read -p "url: " url
read -p "feed: " feed
recins --verbose -t member \
-f "name" -v "$name" \
-f "title" -v "$title" \
-f "url" -v "$url" \
-f "feed" -v "$feed" \
db/members.rec
alias add := new
# rec2json
_json:
recsel db/members.rec \
| rec2csv \
| csvjson \
| jq '. | {data: .}'
# build html
html:
recsel db/members.rec \
| rec2csv \
| csvjson \
| jq '. | {data: .}' \
| mustache - src/example.html www/index.html
# build opml
opml:
recsel db/members.rec \
| rec2csv \
| csvjson \
| jq '. | {data: .}' \
| jq '{ data: [ .data[] | select(.feed != null) ] }' \
| mustache - src/example.opml www/webring.opml
# compile html and opml
build: html opml
# upload
up:
rsync -zaP www/ tilde:public_html/webring/dozens

143
src/example.html 100644
View File

@ -0,0 +1,143 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>webring</title>
<style type="text/css" media="screen">
body {
max-width: 70ch;
margin: 0 auto;
}
</style>
</head>
<body>
<header>
<h1>a very powerful webring</h1>
</header>
<main>
<section id="about">
<h2>about</h2>
<p>
this is a webring.
a webring is like an onion ring
except it is more abstract and intangible and you can't eat it.
but if you imagine the breading of the onion ring
as a series of websites instead of fried batter,
then you will notice that if you follow
the breadcrumbs, as it were,
by the time you've gotten to the bottom of the list,
then you've arrived back at the top!
</p>
</section>
<section>
<h2>members</h2>
<ul>
{{#data}}
<li>
<a href="{{{url}}}">{{{title}}}</a>
</li>
{{/data}}
</ul>
</section>
<section id="feeds">
<h2>feeds</h2>
<p>
here's a special bonus,
just for you,
our special friend.
a special little treat
for special little you.
it's an opml file of all webring members
that have a feed.
<a href="webring.opml">here you go!</a>
</p>
</section>
<section>
<h2>how it works</h2>
<p>
this webring requires no client/member-side javascript.
it works by navigating to this page
with certain query parameters. e.g.
<code>?name=town&amp;dir=next</code>.
then this page will do some javascript
and redirect the user to the next (or previous) page in the ring.
so you can make the whole thing work
with just a couple of anchor tags on your site.
</p>
</section>
<section id="join">
<h2>join</h2>
<p>
to join this <del>onion</del> webring,
add your information to <code>db/members.rec</code>
at <a href="https://git.tilde.town/dozens/webring">https://git.tilde.town/dozens/webring</a>
</p>
</section>
<section id="snippet">
<h2>snippet</h2>
<p>
once you have been added to the database,
you can include the webring html on your page however you like.
here's an example:
</p>
<code>
<pre>
&lt;div&gt;
&lt;p&gt;this site is a member of a very powerful webring!&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;https://tilde.town/~dozens/webring/dozens/index.html?name=yoursitename&amp;dir=prev&quot;&gt;previous&lt;/a&gt; |
&lt;a href=&quot;https://tilde.town/~dozens/webring/dozens/index.html&quot;&gt;all&lt;/a&gt; |
&lt;a href=&quot;https://tilde.town/~dozens/webring/dozens/index.html?name=yoursitename&amp;dir=next&quot;&gt;next&lt;/a&gt; &gt;
&lt;/p&gt;
&lt;/div&gt;
</pre>
</code>
<p>
that'd look like this:
</p>
<blockquote>
<div>
<p>this site is a member of a very powerful webring!</p>
<p>
&lt; <a href="https://tilde.town/~dozens/webring/dozens/index.html?name=yoursitename&dir=prev">previous</a> |
<a href="https://tilde.town/~dozens/webring/dozens/index.html">all</a> |
<a href="https://tilde.town/~dozens/webring/dozens/index.html?name=yoursitename&dir=next">next</a> &gt;
</p>
</div>
</blockquote>
</section>
</main>
</body>
</html>
<script>
const members = [
{{#data}}
{
"id": {{{id}}},
"name": "{{{name}}}",
"url": "{{{url}}}",
},
{{/data}}
]
const last = members.length - 1
const query = window.location.search
const params = new URLSearchParams(query)
const name = params.get('name')
const dir = params.get('dir')
if (name && dir) {
const step = (dir === 'next') ? 1 : (dir === 'prev') ? -1 : 0
const member = members.filter(member => member.name === name)[0]
if (!(typeof member === "undefined")) {
const next = (member.id + step > last)
? 0
: (member.id + step < 0)
? last
: member.id + step
const loc = members.filter(m => m.id === next)[0]
window.location.replace(loc.url)
}
}
</script>

16
src/example.opml 100644
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<opml version="2.0">
<head>
<title>webring</title>
<text>webring</text>
<ownerName>dozens</ownerName>
<ownerEmail>dozens@tilde.team</ownerEmail>
</head>
<body>
<outline text="webring" title="webring">
{{#data}}
<outline text="{{{name}}}" title="{{{title}}}" type="rss" xmlUrl="{{{feed}}}" />
{{/data}}
</outline>
</body>
</opml>

0
www/.gitkeep 100644
View File