inicio
authorReisub Repositorio Git <mama21mama2000@yahoo.com.ar>
Wed, 12 Oct 2022 19:34:47 +0000 (16:34 -0300)
committerReisub Repositorio Git <mama21mama2000@yahoo.com.ar>
Wed, 12 Oct 2022 19:34:47 +0000 (16:34 -0300)
ejemplo.txt [new file with mode: 0644]
fesh.sh [new file with mode: 0755]

diff --git a/ejemplo.txt b/ejemplo.txt
new file mode 100644 (file)
index 0000000..96d6c3d
--- /dev/null
@@ -0,0 +1,2 @@
+vladimir@debian ~/D/gemini> fesh.sh -r . -d reisub.nsupdate.info/fabianbonetti -c "Cápsula Gemini de Fabián Bonetti" -a "Fabián Bonetti" -n 80
+cat atom.xml
diff --git a/fesh.sh b/fesh.sh
new file mode 100755 (executable)
index 0000000..9ef2dec
--- /dev/null
+++ b/fesh.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# fesh - An Atom feed generator for Gemini capsules written in POSIX sh.
+#
+# Copyright (C) 2021-2022 - Ricardo García Jiménez <ricardogj08@riseup.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+
+#
+# Muestra mensajes de errores.
+#
+errors() {
+  printf '%s.\n' "$1" >&2
+  exit 1
+}
+
+#
+# Muestra un mensaje de ayuda.
+#
+shelp() { printf '%s' "\
+fesh 2.2 - An Atom feed generator for Gemini capsules written in POSIX sh.
+
+Synopsis:
+  fesh [OPTIONS]
+
+Options:
+  -a <NAME>   - Author name [default: capsule].
+  -c <STRING> - Capsule name [default: fesh].
+  -d <DOMAIN> - Capsule domain name [default: localhost].
+  -l <LANG>   - Capsule content language [default: es].
+  -n <NUMBER> - Number of entries [default: 15].
+  -o <PATH>   - Output directory [default: .].
+  -r <PATH>   - Capsule root directory [default: .].
+
+Example:
+  fesh -d myblog.com -c 'My blog'
+"
+exit 0
+}
+
+#
+# Genera el encabezado del feed de Atom.
+#
+header() { cat << EOF
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="${FESH_LANG:-es}">
+<id>${FESH_DOMAIN}/atom.xml</id>
+<title>${FESH_CAPSULE}</title>
+<updated>$(LC_ALL=C date "$FDATE")</updated>
+<author>
+  <name>${FESH_AUTHOR}</name>
+</author>
+<link rel="self" href="${FESH_DOMAIN}/atom.xml" type="application/atom+xml"/>
+<link rel="alternate" href="${FESH_DOMAIN}" type="text/gemini"/>
+<generator uri="https://github.com/ricardogj08/fesh" version="2.2">fesh</generator>
+EOF
+}
+
+#
+# Elimina espacios sobrantes de un string.
+# shellcheck disable=SC2048,SC2086
+#
+trim_all() {
+  set -f
+
+  set -- $*
+
+  printf '%s' "$*"
+
+  set +f
+}
+
+#
+# Genera una entrada para el feed de Atom.
+#
+entry() { cat << EOF
+<entry>
+  <id>${URL}</id>
+  <title>${TITLE}</title>
+  <updated>${DATE}</updated>
+  <author>
+    <name>${FESH_AUTHOR}</name>
+  </author>
+  <link rel="alternate" href="${URL}" type="text/gemini"/>
+</entry>
+EOF
+}
+
+#
+# Contruye un feed de atom.
+#
+render() {
+  FDATE=+%Y-%m-%dT%H:%M:%SZ
+
+  header
+
+  i=0
+
+  #
+  # Lista todos los archivos *.gmi o *.gemini
+  # ordenados por fecha de modificación.
+  #
+  find . -type f \( -name \*.gmi -o -name \*.gemini \) \
+    -a ! \( -name index.gmi -o -name index.gemini \) \
+    -exec ls -t {} + 2>/dev/null |
+
+  while read -r file; do
+    #
+    # URL Gemini del archivo.
+    #
+    URL="$FESH_DOMAIN/${file#./}"
+
+    #
+    # Título principal del archivo.
+    #
+    TITLE=$(grep -se '^#[[:space:]]' "$file" | head -n 1)
+    TITLE=${TITLE#\#[[:space:]]}
+    TITLE=$(trim_all "$TITLE")
+
+    #
+    # Fecha de modificación.
+    #
+    DATE=$(LC_ALL=C date -r "$file" "$FDATE" 2>/dev/null ||
+      LC_ALL=C date "$FDATE")
+
+    entry
+
+    i=$((i + 1))
+
+    [ "$i" -eq "$FESH_NUMBER" ] && break
+  done
+
+  printf '</feed>\n'
+}
+
+main() {
+  while getopts :a:c:d:l:n:o:r: opt; do
+    case $opt in
+      a) FESH_AUTHOR="$OPTARG";;
+      c) FESH_CAPSULE="$OPTARG";;
+      #d) FESH_DOMAIN=gemini://${OPTARG}:1965;;
+      d) FESH_DOMAIN=gemini://${OPTARG};; # Sin :1965
+      l) FESH_LANG="$OPTARG";;
+      n) FESH_NUMBER="$OPTARG";;
+      o) FESH_OUTPUT="$OPTARG";;
+      r) FESH_ROOT="$OPTARG";;
+      \?) shelp;;
+      :) errors "Option -$OPTARG requires an argument"
+    esac
+  done
+  #
+  # Decrementa el puntero del argumento $n
+  # para que apunte al siguente argumento.
+  #
+  shift $((OPTIND - 1))
+
+  #
+  # Configuración por defecto.
+  #
+  : "${FESH_CAPSULE=fesh}"
+  : "${FESH_AUTHOR:=$FESH_CAPSULE}"
+  #: "${FESH_DOMAIN:=gemini://localhost:1965}" 
+  : "${FESH_DOMAIN:=gemini://localhost}" # sin :1965
+  : "${FESH_NUMBER:=15}"
+  : "${FESH_OUTPUT:=.}"
+
+  :> "$FESH_OUTPUT/atom.xml" ||
+    errors "Couldn't create Atom feed file"
+
+  cd "${FESH_ROOT:-.}" ||
+    errors "Couldn't access capsule root directory"
+
+  render > "$FESH_OUTPUT/atom.xml"
+}
+
+main "$@"