sbrs

Simple blog and RSS system
git clone git://git.christosmarg.xyz/sbrs.git
Log | Files | Refs | README | LICENSE

commit 0e043834abe149d9550986dcecbad54c937bc4b3
parent 577b0ea3b45f656ada17603ad9aaf5d48b6cb893
Author: Christos Margiolis <christos@margiolis.net>
Date:   Wed, 26 May 2021 19:03:11 +0300

changed mail

Diffstat:
MLICENSE | 43++++++++++++++++---------------------------
MMakefile | 53+++++++++++++++++++++++------------------------------
MREADME | 12++++++------
Rblog.html -> articles.html | 0
Mindex.html | 4++--
Msbrs | 80+++++++++++++++++++++++++++++++++----------------------------------------------
Msbrs.1 | 44+++++++++++++++++---------------------------
7 files changed, 97 insertions(+), 139 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -1,31 +1,20 @@ -BSD 3-Clause License +MIT License -Copyright (c) 2020-present, Christos Margiolis. -All rights reserved. +(c) 2020-Present Christos Margiolis <christos@margiolis.net> -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +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: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY -THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +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/Makefile b/Makefile @@ -1,45 +1,38 @@ # See LICENSE file for copyright and license details. +# sbrs - simple blog and rss system .POSIX: -BIN = sbrs +SH = sbrs VERSION = 0.1 -DIST = ${BIN}-${VERSION} -MAN1 = ${BIN}.1 +DIST = ${SH}-${VERSION} +MAN1 = ${SH}.1 PREFIX = /usr/local -MAN_DIR = ${PREFIX}/man/man1 -BIN_DIR = ${PREFIX}/bin +MANPREFIX = ${PREFIX}/share/man -CP = cp -f -RM = rm -f -RM_DIR = rm -rf -MKDIR = mkdir -p -TAR = tar -cf -GZIP = gzip - -all: ${BIN} - chmod +x ${BIN} +all: ${SH} + chmod +x ${SH} dist: - ${MKDIR} ${DIST} - ${CP} -R ${BIN} ${MAN1} blog.html index.html LICENSE Makefile\ - README.md rss.xml styles.css template.html ${DIST} - ${TAR} ${DIST}.tar ${DIST} - ${GZIP} ${DIST}.tar - ${RM_DIR} ${DIST} + mkdir -p ${DIST} + cp -R articles.html index.html LICENSE Makefile rss.xml \ + sbrs sbrs.1 styles.css template.html ${DIST} + tar -cf ${DIST}.tar ${DIST} + gzip ${DIST}.tar + rm -rf ${DIST} install: all - ${MKDIR} ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN_DIR} - ${CP} ${BIN} ${DESTDIR}${BIN_DIR} - ${CP} ${MAN1} ${DESTDIR}${MAN_DIR} - sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MAN_DIR}/${MAN1} - chmod 755 ${DESTDIR}${BIN_DIR}/${BIN} - chmod 644 ${DESTDIR}${MAN_DIR}/${MAN1} + mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${MANPREFIX}/man1 + cp -f ${SH} ${DESTDIR}${PREFIX}/bin + cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MANPREFIX}/man1/${MAN1} + chmod 755 ${DESTDIR}${PREFIX}/bin/${SH} + chmod 644 ${DESTDIR}${MANPREFIX}/man1/${MAN1} -uninstall: all - ${RM} ${DESTDIR}${BIN_DIR}/${BIN} - ${RM} ${DESTDIR}${MAN_DIR}/${MAN1} +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/${SH} \ + ${DESTDIR}${MANPREFIX}/man1/${MAN1} clean: - ${RM} ${DIST}.tar.gz + rm -f ${DIST}.tar.gz .PHONY: all clean dist install uninstall diff --git a/README b/README @@ -11,17 +11,17 @@ In case you don't edit the script further, the structure of your website's directory should look like this. The files below need to exist with the same names. - ├── blog - | └── here reside your blog posts + ├── articles + | └── here reside your articles ├── index.html - ├── blog.html + ├── articles.html ├── template.html └── rss.xml -Inside 'index.html', 'blog.html' and 'rss.xml' sbrs will search for -<!--SBRS--> in order to put the blog post listings and RSS feed below it. +Inside 'index.html', 'articles.html' and 'rss.xml' sbrs will search for +<!--SBRS--> in order to put the article listings and RSS feed below it. -The 'template.html' file is how you want your blog post's page to look like. +The 'template.html' file is how you want your article's page to look like. See my own 'template.html' for more. The 'TITLE', 'HEADER' and 'AUTHOR' fields must exist and be left as is. diff --git a/blog.html b/articles.html diff --git a/index.html b/index.html @@ -3,11 +3,11 @@ <head> <meta charset="UTF-8"> <link rel="stylesheet" href="styles.css"/> - <title>Website Index</title> + <title>Foo Bar</title> </head> <body> - <h2>Recent blog posts</h2> + <h2>Latest articles</h2> <ul> <!--SBRS--> </ul> diff --git a/sbrs b/sbrs @@ -1,26 +1,27 @@ #!/bin/sh # See LICENSE file for copyright and license details. -WEBSITE="https://christosmarg.xyz" +WEBSITE="https://margiolis.net" AUTHOR="Christos Margiolis" -BLOGDIR="blog" +BLOGDIR="articles" DRAFTDIR=".drafts" -BLOGINDEX="blog.html" +BLOGINDEX="articles/index.html" INDEX="index.html" RSSFILE="rss.xml" TEMPLATE="template.html" test -z "${EDITOR}" && EDITOR="vim" main() { - test -f "${TEMPLATE}" || err "${TEMPLATE}: missing file" - test -f "${BLOGINDEX}" || err "${BLOGINDEX}: missing file" - test -f "${INDEX}" || err "${INDEX}: missing file" - test -f "${RSSFILE}" || err "${RSSFILE}: missing file" + test -f "${TEMPLATE}" || err "${TEMPLATE}: missing file" + test -f "${BLOGINDEX}" || err "${BLOGINDEX}: missing file" + test -f "${INDEX}" || err "${INDEX}: missing file" + test -f "${RSSFILE}" || err "${RSSFILE}: missing file" if ! test -d "${BLOGDIR}"; then confirmact "Blog directory doesn't exist. Intialize it here (y/n)? " "y" mkdir -pv "${BLOGDIR}" fi + # FIXME: ADD QUOTES INSIDE DATE ID case ${1} in -n) newpost ;; @@ -41,8 +42,8 @@ err() { echo "${0##*/}: $@" && exit } -# We could be using `read -erp` but the -e and -p options don't work -# or exist in all shells (e.g OpenBSD's `/bin/sh`). +# Could just use `read -erp` but the -e and -p options don't work +# or exist in all shells (e.g OpenBSD's ksh). xread() { printf "%s" "${1}" && read -r ${2} } @@ -51,19 +52,20 @@ xread() { # implementations require a backup file with the -i option. # In this case, we make the backup files and immidiately delete # them afterwards because we probably don't need them. -# We're using the extension `.psedbak` since we want to delete -# only the files affected by `psed` and nothing else, and that's +# We're using the extension `.sedibak` since we want to delete +# only the files affected by `sedi` and nothing else, and that's # an easy way to make sure. -psed() { - sed -i.psedbak "$@" && rm *.psedbak ${BLOGDIR}/*.psedbak 2>/dev/null +sedi() { + sed -i.sedibak "$@" && rm *.sedibak ${BLOGDIR}/*.sedibak 2>/dev/null } confirmact() { xread "${1}" act && test "${act}" = "${2}" || exit 1 } +# TODO: sort by date list() { - find "${1}" -type f -name '*\.html' ! -name '*\.final*' 2> /dev/null | + find "${1}" -type f -name '*\.html' ! -name '*\.final*' 2>/dev/null | awk -F/ '{print $NF}' } @@ -84,7 +86,7 @@ titlecheck() { } rmcontents() { - ls "${1}" | grep -x "${blogpost}\...*" | sed "s/^/${1}\//" | xargs rm + ls "${1}" | grep -x "${blogpost}\...*" | sed "s/^/${1}\//" | xargs -r rm } # -l option @@ -107,7 +109,7 @@ listposts() { fi } -# -n options +# -n option newpost() { mkdir -p "${DRAFTDIR}" xread "Title: " title @@ -136,7 +138,7 @@ titlechange() { # single instance of `and` in the file, and we don't want that. :-) # The < and > serve the same purpose, as `oldtitle` is # probably going to be inside an <a> or <title> tag. - psed "s/${blogpost}.html/${newtitlefmt}.html/g;s/>${oldtitle}</>${newtitle}</g" \ + sedi "s/${blogpost}.html/${newtitlefmt}.html/g;s/>${oldtitle}</>${newtitle}</g" \ "${BLOGDIR}/${blogpost}.html" "${INDEX}" "${BLOGINDEX}" "${RSSFILE}" && mv "${BLOGDIR}/${blogpost}.html" "${BLOGDIR}/${newtitlefmt}.html" && echo "Title changed successfully: ${oldtitle} -> ${newtitle}" @@ -145,7 +147,7 @@ titlechange() { # -v option view() { cat "${DRAFTDIR}/${blogpost}.final.html" > "${DRAFTDIR}/${blogpost}.final-view.html" - psed "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.html" "${DRAFTDIR}/${blogpost}.final-view.html" + sedi "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.html" "${DRAFTDIR}/${blogpost}.final-view.html" ${BROWSER} "${DRAFTDIR}/${blogpost}.final-view.html" } @@ -155,8 +157,8 @@ delete() { confirmact "Are you sure you want to delete \"${blogpost}\" (y/N)? " "y" if test "${dir}" = "${BLOGDIR}"; then - psed "/${blogpost}/d" "${INDEX}" "${BLOGINDEX}" - psed "/<\!--BEGIN ${blogpost}-->/,/<\!--END ${blogpost}-->/d" "${RSSFILE}" + sedi "/${blogpost}/d" "${INDEX}" "${BLOGINDEX}" + sedi "/<\!--BEGIN ${blogpost}-->/,/<\!--END ${blogpost}-->/d" "${RSSFILE}" fi rmcontents "${dir}" && echo "Removed ${blogpost}." } @@ -168,8 +170,8 @@ publish() { title=$(titleget "${DRAFTDIR}/${blogpost}.final.html") # Make the final HTML file. - psed "s/^/\ \ \ \ \ \ \ \ /" "${DRAFTDIR}/${blogpost}.html" - psed "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.html" "${DRAFTDIR}/${blogpost}.final.html" + sedi "s/^/\ \ \ \ \ \ \ \ /" "${DRAFTDIR}/${blogpost}.html" + sedi "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.html" "${DRAFTDIR}/${blogpost}.final.html" # Convert HTML tags to XML format. We're also wrapping all <pre> tags # in a CDATA block so that RSS readers can render it properly. @@ -186,26 +188,10 @@ publish() { # Prepare the RSS entry. rsscreate | expand -t8 > "${DRAFTDIR}/${blogpost}.final-rssentry" - # Update blog index to include the new post. - # In case there is not section for the current month, create that too. - dateid=$(date '+%b %Y' | sed 's/\ //' | tr '[:upper:]' '[:lower:]') - - if test -z "$(grep "${dateid}" "${BLOGINDEX}")"; then - datename=$(date '+%B %Y') - psed "/<\!--SBRS-->/a\\ -\ <h2 id=\\"${dateid}\\">${datename}<\\/h2> \\ -\ <ul> \\ -\ <\\!--SBRS ${datename}--> \\ -\ <\\/ul> \\ -" "${BLOGINDEX}" - fi - - # Using || because of `psed`. - psed "/<\!--SBRS $(date '+%B %Y')-->/r ${DRAFTDIR}/${blogpost}.final-htmlentry" \ - "${BLOGINDEX}" || echo "Blogindex... done." - - psed "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.final-htmlentry" "${INDEX}" || echo "Index... done" - psed "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.final-rssentry" "${RSSFILE}" || echo "RSS... done" + # Using || because of `sedi`. + sedi "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.final-htmlentry" "${BLOGINDEX}" || echo "blogindex: ok" + sedi "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.final-htmlentry" "${INDEX}" || echo "index: ok" + sedi "/<\!--SBRS-->/r ${DRAFTDIR}/${blogpost}.final-rssentry" "${RSSFILE}" || echo "rss: ok" # Remove the last blog entry from `index.html`. # Get only what's inside <!--SBRS--> and </ul>. Will not work on anything except @@ -214,25 +200,25 @@ publish() { if test $(expr $(echo "${indexentries}" | wc -l)) -gt 7; then lastentry=$(echo "${indexentries}" | tail -2 | head -1) && - psed "s|${lastentry}||;" "${INDEX}" + sedi "s|${lastentry}||;" "${INDEX}" fi - rmcontents "${DRAFTDIR}" && echo "Cleaning up ${DRAFTDIR}... done" + rmcontents "${DRAFTDIR}" && echo "clean up ${DRAFTDIR}: ok" echo "Published ${blogpost}." } # -r option #revise() { #${EDITOR} "${BLOGDIR}/${blogpost}.html" - #psed "/<\!--BEGIN ${blogpost}-->/,/<\!--END ${blogpost}-->/d" "${RSSFILE}" + #sedi "/<\!--BEGIN ${blogpost}-->/,/<\!--END ${blogpost}-->/d" "${RSSFILE}" #} rsscreate() { printf "<!--BEGIN %s-->\n" "${blogpost}" - printf "<item>" + printf "<item>\n" printf "\t<title>%s</title>\n" "${title}" printf "\t<guid>%s</guid>\n" "${WEBSITE}/${BLOGDIR}/${blogpost}.html" - printf "\t<pubDate>%s</pubDate>\n" "$(date '+%a, %d %b %Y')" + printf "\t<pubDate>%s</pubDate>\n" "$(date '+%a, %d %b %Y %T %z')" printf "\t<description>\n" printf "%s\n" "$(cat "${DRAFTDIR}/${blogpost}.xml")" printf "\t</description>\n" diff --git a/sbrs.1 b/sbrs.1 @@ -7,32 +7,22 @@ .Sh SYNOPSIS .Nm .Bro -.Fl n | -.Fl p | -.Fl e | -.Fl v | -.Fl t | -.Fl r | -.Fl c | -.Fl o | -.Fl d | -.Fl l +.Cm -n | -p | -e | -v | -t | -r | -c | -o | -d | -l .Sh DESCRIPTION .Nm -generates a blog post page and RSS feed. +generates an article post page and RSS feed. .Sh OPTIONS The options are as follows: .Bl -tag -width Ds .It Fl n -Prompt the user to write a new blog post in HTML. +Prompt the user to write a new article in HTML. .Nm will open the editor set in the 'EDITOR' environmental variable. In case -it is not set, it will set 'EDITOR' -.Xr Vim 1 +it is not set, it will set Vim as 'EDITOR'. .It Fl p Publish one of the posts stored in the '.drafts' directory. After a post has been published, it will be deleted from '.drafts' along with all the -files related to it and will be moved to 'blog'. This option also automatically +files related to it and will be moved to 'articles'. This option also automatically creates an RSS feed for the post. .It Fl e Edit one of the posts stored in the '.drafts' directory. @@ -47,7 +37,7 @@ in order for this option to work. .It Fl t Delete one of the posts stored in the '.drafts' directory. .It Fl r -Revise a published post stored in the 'blog' directory. After you're done +Revise a published post stored in the 'articles' directory. After you're done revising you don't need to re-publish the post again, since .Nm edits the post directly. @@ -56,15 +46,15 @@ Change a published post's title. This option will replace every instance of the old title with the new one both. The filename will also be changed. .It Fl o -View a published post stored in the 'blog' directory on your default browser. +View a published post stored in the 'articles' directory on your default browser. Same with the -v option; the 'BROWSER' environmental variable has to be set in order for this option to work. .It Fl d -Delete a published post stored in the 'blog' directory. This option will delete -the post from the blog's index file, the RSS feed, as well as the main page in +Delete a published post stored in the 'articles' directory. This option will delete +the post from the articles' index file, the RSS feed, as well as the main page in case it is found there too. .It Fl l -List all posts stored in the 'blog' directory. +List all posts stored in the 'articles' directory. .El .Pp Only one option at a time can be used. @@ -79,19 +69,19 @@ In case you don't edit the script further, the structure of your website's directory should look like this. The files below need to exist with the same names. .Pp - ├── blog - | └── here reside your blog posts + ├── articles + | └── here reside your articles ├── index.html - ├── blog.html + ├── articles.html ├── template.html └── rss.xml .Pp -Inside 'index.html', 'blog.html' and 'rss.xml' +Inside 'index.html', 'articles.html' and 'rss.xml' .Nm will search for -<!--SBRS--> in order to put the blog post listings and RSS feed below it. +<!--SBRS--> in order to put the article listings and RSS feed below it. .Pp -The 'template.html' file is how you want your blog post's page to look like. +The 'template.html' file is how you want your article's page to look like. See my own 'template.html' for more. The 'TITLE', 'HEADER' and 'AUTHOR' fields must exist and be left as is. .Sh USAGE @@ -103,4 +93,4 @@ at a time. Do NOT edit the various comments that the script writes inside the files, otherwise it'll not work properly, or work at all. .Sh AUTHORS -.An Christos Margiolis Aq Mt christos@christosmarg.xyz +.An Christos Margiolis Aq Mt christos@margiolis.net