diff options
| author | Ahmed <git@gumx.cc> | 2026-06-02 01:14:00 +0300 |
|---|---|---|
| committer | Ahmed <git@gumx.cc> | 2026-06-02 01:18:36 +0300 |
| commit | 3296eee590f795022dfae49567860270af5c6d51 (patch) | |
| tree | 5bf600021fc381e445f463988f4022b25e6d1cbc | |
| -rw-r--r-- | .gitignore | 32 | ||||
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | README.md | 36 | ||||
| -rw-r--r-- | ci-examples/.build.yml | 15 | ||||
| -rw-r--r-- | ci-examples/.github/workflows/wr.yml | 48 | ||||
| -rw-r--r-- | ci-examples/.gitlab-ci.yml | 9 | ||||
| -rw-r--r-- | entries/gumx.cc | 3 | ||||
| -rw-r--r-- | entries/webring.gumx.cc | 3 | ||||
| -rwxr-xr-x | wr | 211 |
9 files changed, 378 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8d22d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +secring.* +.*.kate-swp +.swp.* +*~ +.fuse_hidden* +.directory +.Trash-* +.nfs* +**/.ssh/id_* +**/.ssh/*_id_* +**/.ssh/known_hosts +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] +Session.vim +Sessionx.vim +.netrwhist +[._]*.un~ +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets +.history/ +*.vsix +.history +.ionide +public @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ahmed Mohamed Alaa + +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/README.md b/README.md new file mode 100644 index 0000000..7657840 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# ω webring + +This is an attempt to replicate [Devine Lu Linvega](https://wiki.xxiivv.com/site/devine_lu_linvega.html)'s [webring](https://webring.xxiivv.com/) in a very minimal way, and with a lower technical bar. + +## Add your website to this webring + +1. Clone this repository +2. Add your site using `./wr add example.com "my cool website" "John Doe"` \ + Replace `example.com` with your actual website url, `my cool website` with your entry title, and optionally add your name +3. Submit a patch by any of these methods + - Issuing a pull request from [GitHub](https://github.com/gumxcc/webring) or [GitLab](https://gitlab.com/gumxcc/webring) + - Sending a mail to the project's [mailing list](https://lists.sr.ht/~gumxcc/webring.gumx.cc) + - Using [`git send-email`](https://git-send-email.io/) +4. Add the ring links to your site, preferrably in the footer, for example + ```html + <ul> + <li><a href="https://webring.gumx.cc/{{example.com}}/previous">← previous</a></li> + <li><a href="https://webring.gumx.cc/">webring index</a></li> + <li><a href="https://webring.gumx.cc/{{example.com}}/next">next →</a></li> + </ul> + ``` + +## Host your own + +1. Clone the project [repository](https://git.sr.ht/~gumxcc/webring.gumx.cc), and add your remotes +2. Run `rm -fr entries/* public` to delete old entries and build artifacts +3. Add an entry for the webring itself by running `./wr add webring-example.com "my webring" "John Doe"` +4. Add other entries and run `./wr` to check the output +5. Upload your webring to a static site hosting provider, examples are available for + - [Sourcehut Pages](https://git.sr.ht/~gumxcc/webring.gumx.cc/tree/main/item/ci-examples/.build.yml) + - [GitHub Pages](https://git.sr.ht/~gumxcc/webring.gumx.cc/tree/main/item/ci-examples/.github) + - [GitLab Pages](https://git.sr.ht/~gumxcc/webring.gumx.cc/tree/main/item/ci-examples/.gitlab-ci.yml) + +## License + +This project is licensed under [MIT license](https://git.sr.ht/~gumxcc/webring.gumx.cc/tree/main/item/LICENSE) diff --git a/ci-examples/.build.yml b/ci-examples/.build.yml new file mode 100644 index 0000000..2bbd6ea --- /dev/null +++ b/ci-examples/.build.yml @@ -0,0 +1,15 @@ +image: alpine/edge +oauth: pages.sr.ht/PAGES:RW +packages: +- hut +environment: + site: webring.gumx.cc +sources: +- https://git.sr.ht/~a2/webring +tasks: +- package: | + cd webring + ./wr + tar -C public -cvz . > ../site.tar.gz +- upload: | + hut pages publish -d $site site.tar.gz
\ No newline at end of file diff --git a/ci-examples/.github/workflows/wr.yml b/ci-examples/.github/workflows/wr.yml new file mode 100644 index 0000000..1459a9e --- /dev/null +++ b/ci-examples/.github/workflows/wr.yml @@ -0,0 +1,48 @@ +name: Deploy webring to Pages + +on: + push: + branches: ["main"] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: true + +defaults: + run: + shell: sh + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + - name: Setup Pages + id: pages + uses: actions/configure-pages@v2 + - name: Build webring + run: ./wr + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: ./public + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 diff --git a/ci-examples/.gitlab-ci.yml b/ci-examples/.gitlab-ci.yml new file mode 100644 index 0000000..db7c574 --- /dev/null +++ b/ci-examples/.gitlab-ci.yml @@ -0,0 +1,9 @@ +image: alpine:latest +pages: + script: + - ./wr + artifacts: + paths: + - public + only: + - pages
\ No newline at end of file diff --git a/entries/gumx.cc b/entries/gumx.cc new file mode 100644 index 0000000..56af3a7 --- /dev/null +++ b/entries/gumx.cc @@ -0,0 +1,3 @@ +url="https://gumx.cc" +author="Ahmed (~gumxcc)" +title="gumx"
\ No newline at end of file diff --git a/entries/webring.gumx.cc b/entries/webring.gumx.cc new file mode 100644 index 0000000..ee2e2db --- /dev/null +++ b/entries/webring.gumx.cc @@ -0,0 +1,3 @@ +url="https://webring.gumx.cc" +author="Ahmed (~gumxcc)" +title="minimal webring"
\ No newline at end of file @@ -0,0 +1,211 @@ +#!/bin/sh +# wr - Minimal webring utility +# Licensed under the MIT License. + +# This script should not be sourced, make sure to change the string 'wr' +# in the following line to match this file's name +[ 'wr' = "$( basename ${0} )" ] || return 1 + +# Edit DOMAIN and AUTHOR for your instance +# Make sure that DOMAIN is ONLY the domain of your instance, and without trailing slash +DOMAIN="webring.gumx.cc" +AUTHOR="Ahmed (~gumxcc)" + +# Script metadata +SCRIPT=$( basename "$0" ) +VMAJOR=0 +VMINOR=1 +VPATCH=0 +HOMEPAGE="https://webring.gumx.cc/" + +print_help () { + cat << HELP_TEXT +${SCRIPT} v${VMAJOR}.${VMINOR}.${VPATCH} +Minimal webring utility + +Usage: + ${SCRIPT} add SITE_URL SITE_TITLE [AUTHOR_NAME] + Add a new entry to the webring + ${SCRIPT} [build] + Build the webring + ${SCRIPT} -h | --help | help + Display this help message and exit + ${SCRIPT} -v | --version | version + Display the script version and exit + +Project homepage: <${HOMEPAGE}> +HELP_TEXT +} + +print_version () { + VERSION="${VMAJOR}.${VMINOR}.${VPATCH}" + printf '%s Version %s\n' "${SCRIPT}" "${VERSION}" +} + +print_error () { + ERROR_MSG=${1:-Unknown error} + printf '%s: %s\n' "${SCRIPT}" "${ERROR_MSG}" >&2 +} + +build_webring() { + mkdir -p public + printf '' > public/index.html + + cat << INDEX_PAGE_TOP > public/index.html +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta content="IE=edge" http-equiv="X-UA-Compatible"> + <meta content="text/html; charset=UTF-8" http-equiv="content-type"> + <meta content="width=device-width,initial-scale=1" name="viewport"> + <title>webring</title> + <meta content="webring" name="title"> + <meta content="${AUTHOR}" name="author"> + <meta content="Minimal webring" name="description"> + <meta content="website" property="og:type"> + <meta content="${DOMAIN}" property="og:url"> + <meta content="webring" property="og:site_name"> + <meta content="webring" property="og:title"> + <meta content="Minimal webring" property="og:description"> + <meta content="summary" property="twitter:card"> + <meta content="${DOMAIN}" property="twitter:url"> + <meta content="webring" property="twitter:title"> + <meta content="Minimal webring" property="twitter:description"> + <link href="${DOMAIN}" rel="canonical"> + <link href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAACYktHRAAAqo0jMgAAAAd0SU1FB+YMGRUdK60VU+wAAAEzSURBVEjH7ZO9SgNBFIU/fyImEkgExRQquEiaQCwsDT6AnYWdnWCRx0jlA1ha+Q4WCvYWFimTgKzBRgUTRDSB6Fh4dzI7mJm1sNvT3DOHe787w7KQKtW/qIFCoTg3skPJbpIA7qT5yMhWJVMEvvGybt38FVu3B6atc01qj04sjy6/6wOUpbatPDpv+QCBBxAwlwzQtfKu7i+5AWtS+8AeISEhJ0BPdyzHB2YtwILUAVBgHYAVYKg7cu4bZKR+AVnxWeBz0kobMDCG8uLzsb3vbkD01hywZLx6DHhxA0Kpi4y/yAZQFK+4dwOaUivMsCO+QJWK+JZ+5AQd6H+hpZ3igTdxp3g0z5MxqLiMnRTbPgDsM9Ltz5S4Nsa9+39U44I+r1xRBYqc8cgHtxwzlQyQ6o/6BrGHacYUEyMVAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIyLTEyLTI1VDIxOjI5OjQzKzAwOjAwsFlEUAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMi0xMi0yNVQyMToyOTo0MyswMDowMMEE/OwAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjItMTItMjVUMjE6Mjk6NDMrMDA6MDCWEd0zAAAACHRFWHRsYWJlbADPieuXgVsAAAAASUVORK5CYII=" rel="icon"> + <script type="application/ld+json"> + { + "description":"Minimal webring", + "url":"${DOMAIN}", + "@type":"WebSite", + "headline":"webring", + "name":"webring", + "author":{ + "@type":"Person", + "name":"${AUTHOR}" + }, + "@context":"https://schema.org" + } + </script> + <style> + html { height:100%; background:white; } + body { background:white; color:black; font-family:monospace; font-size:16px; line-height:1.4; margin:0; padding:4rem 0; min-height:100%; overflow-wrap:break-word; } + main { max-width:640px; margin:0 auto; padding:0 2rem; } + h1 { text-align:center } + ul { display: flow-root; } + li, nav a { width: 40%; float: left; margin: 0 5%; } + nav a { text-decoration: none; display: block; text-align: center; } + body[theme="dark"] { filter:invert(1); } + @media (prefers-color-scheme: dark) { body[theme="auto"] { filter:invert(1); } } + @media (max-width:640px) { li { width: 90%; } } + </style> +</head> + +<body theme="auto"> + <main> + <h1>ω webring</h1> + <hr /> + <ul> +INDEX_PAGE_TOP + + #TODO: refactor this + count=0 + for entry in $( find ./entries -type f ); do + count=$(( count + 1 )) + . ${entry} + entry_name="$( basename ${entry} )" + [ ${count} -eq 1 ] && first_entry="${entry_name}" && prev_entry="${entry_name}" + mkdir -p "public/${entry_name}" \ + "public/${entry_name}/next" \ + "public/${entry_name}/previous" + printf "<html><meta http-equiv=\"Refresh\" content=\"0; url='%s'\" /></html>\n" "${url}" \ + > "public/${entry_name}/index.html" + cp "public/${entry_name}/index.html" "public/${prev_entry}/next/index.html" + cp "public/${prev_entry}/index.html" "public/${entry_name}/previous/index.html" + prev_entry="${entry_name}" + [ -n "${author}" ] \ + && printf ' <li><a href="%s">%s</a> by %s</li>\n' \ + "${url}" "${title}" "${author}" >> public/index.html \ + || printf ' <li><a href="%s">%s</a></li>\n' \ + "${url}" "${title}" >> public/index.html + unset url title author + done + cp "public/${first_entry}/index.html" "public/${entry_name}/next/index.html" + cp "public/${entry_name}/index.html" "public/${first_entry}/previous/index.html" + + cat << INDEX_PAGE_BOTTOM >> public/index.html + </ul> + <hr /> + <p>This is an attempt to replicate <a href="https://wiki.xxiivv.com/site/devine_lu_linvega.html">Devine Lu Linvega</a>'s <a href="https://webring.xxiivv.com/">webring</a> in a very minimal way, and with a lower technical bar.</p> + <p>To add your site to the webring, follow the instructions <a href="https://git.sr.ht/~gumxcc/webring.gumx.cc#host-your-own">here</a>. For issues, source code, documentation, visit the <a href="https://sr.ht/~a2/webring/">project page on sourcehut</a></p> + <p>This project is licensed under <a href="https://git.sr.ht/~gumxcc/webring.gumx.cc/tree/main/item/LICENSE">MIT license</a></p> + <hr /> + <nav> + <a href="/${DOMAIN}/previous">≺ previous</a> + <a href="/${DOMAIN}/next">next ≻</a> + </nav> + </main> +</body> + +</html> +INDEX_PAGE_BOTTOM +} + +add_entry() { + entry="$( basename ${1} )" + entry_file="entries/${entry}" + mkdir -p $( dirname ${entry_file} ) + + printf 'url="%s"\ntitle="%s"' "${1}" "${2}" > "${entry_file}" + [ -n "${3}" ] && printf '\nauthor="%s"' "${3}" >> "${entry_file}" + + cat << ENTRY_LINKS +Add the following links in your website, preferrably in the footer: + + <p> + <a href="https://${DOMAIN}/${entry}/previous">← previous</a> +   + <a href="https://${DOMAIN}/">webring index</a> +   + <a href="https://${DOMAIN}/${entry}/next">next →</a> + </p> + +You can style them as you please of course +ENTRY_LINKS +} + +if [ -z "${1}" ] || [ "${1}" = "build" ]; then + printf 'Building the webring..' + build_webring + printf ' done\n' + exit 0 +fi + +ENTRY_URL='' +ENTRY_TITLE='' +ENTRY_AUTHOR='' + +case "${1}" in + -h|--help|help) + print_help + exit 0 + ;; + -v|--version|version) + print_version + exit 0 + ;; + add) + shift + add_entry "${1}" "${2}" "${3}" + exit 0 + ;; + *) + print_error "${1}: Invalid argument" + print_help >&2 + exit 22 + ;; +esac + +trap "print_error 'Interrupt signal detected, output may be incomplete'" INT |
