commit 44aa28f25ea239cb309c79dbba82ff4bc0ffc1c4 Author: Simon Petit Date: Wed Jul 3 21:55:00 2019 +0200 INITIAL COMMIT diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d40616 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +drafts +drafts2 +css +bash +posts +*.conf +index.html +README.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..c68b486 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# # Bob + +Bob is a small static generator, for those who wants to maintain a personal +website or blog, all from the command line. + +## Installation + +It only is designed in bash script, and should work perfectly fine on any Unix +like machine. + +``` +git clone +make install +``` + +## Usage + +For a start, to generate an empty blog, type in the following in the directory +where you want to put your blog in and follow the guide. + +``` +bob -i +``` + +It will create an `index.html` at the root of your folder, a `drafts` folder in +which you will store all the posts you want to publish and a `posts` folder +where the resulting posts in html will be stored. + +To write a post, create a markdown file in the `drafts` folder whose name will +also be its title, and convert it to an html file, type the following command +from the root : + +``` +bob -p +``` + +The publishing command `bob -p` will rep-ublish all the drafts, that is why +anytime you want a post removed, delete in from the drafts folder and re-publish +your blog. + +See the help for additional command, such as modification of the main configuration +of the blog. + +``` +bob -h +``` + +## TODO + +* Make a proper header/footer for the posts (e.g. adding links to social networks + such as tweeter, github, dev.to ...). +* Complete the CSS files. +* Support long arguments on the command line for more readability. +* Add a comment/like section ? +* Adding a git component, and a server configuration to allow synchronisation. + Maybe the drafts folder on the personal computer triggers changes on the git + repo of the server which re-publishes the blog automatically. +* Add a way to do all the construction of the blog on the personal computer but + to send the html files to a distant server. +* Consider adding configuration files for some/all posts (if they + need special javascript included e.g. MathJax, AJAX, sockets ...). +* Design a makefile to install the script on the bin directory for an easy + access on the command line. diff --git a/blog.sh b/blog.sh new file mode 100755 index 0000000..1768d97 --- /dev/null +++ b/blog.sh @@ -0,0 +1,474 @@ +#!/usr/bin/env bash + +_get_blog_name() +{ + # Extract the configuration file + conf=`cat .blog.conf` + #echo $conf + name_regex="blog\:([a-zA-Z ]+)" + + # Echo the name of the blog, if any was given + if [[ $conf =~ $name_regex ]]; then + echo ${BASH_REMATCH[1]} + fi +} + +_get_dark_param() +{ + conf=`cat .blog.conf` + dark_regex="dark:(y|n|N)" + + if [[ $conf =~ $dark_regex ]]; then + echo ${BASH_REMATCH[1]} + fi +} + +_get_blog_lang() +{ + conf=`cat .blog.conf` + lang_regex="lang:([a-z]+)" + + if [[ $conf =~ $lang_regex ]]; then + echo ${BASH_REMATCH[1]} + fi +} + +_add_header() +{ + + post_name=$1 + lang=$2 + dark=$3 + + css="../css/poststyle.css" + if [[ $dark =~ "y" ]]; then + css="../css/poststyle.dark.css" + fi + + cat > ./posts/$post_name.html << EOF + + + + + $post_name + + + + + +
+EOF +} + +_add_footer() +{ + post_name=$1 + cat >> ./posts/$post_name.html << EOF +
+ + + +EOF + +} + + +_get_last_modif_date() +{ + # Extract the date of the last modification of the file $1 + # and echo it with format dd/mm/yyyy + date=`stat -f "%Sm" -t "%d/%m/%Y" $1` + echo $date +} + +publish() +{ + delete_posts + + # Collect all configuration parameters so that the regex are only evaluted + # once per publication. Done to improve the speed of the publication + dark=$(_get_dark_param) + lang=$(_get_blog_lang) + blog_name=$(_get_blog_name) + + # list all the drafts stored as most recently modified to + # least recently modified, as it should appear on a blog + drafts=`ls -t ./drafts/` + # echo $drafts + + # Tranform the string into an array + list=($(echo "$drafts" | tr ' ' '\n')) + + # date=$(_get_last_modif_date "./drafts/${list[0]}") + + # Regex to extract the name without the extension + name_regex="([a-zA-Z]+)\.(md|markdown)" + + # Array to story only the names of the posts + posts_names=() + + for (( i=0; i<${#list[@]}; i++ )); + do + if [[ ${list[i]} =~ $name_regex ]]; then + # Append the names to the array + posts_names+=(${BASH_REMATCH[1]}) + fi + _create_posts "./drafts/${list[i]}" "$lang" "$dark" + done + + # function to update the index.html + # Passing the drafts as argument since it's sorted + _update_index "$drafts" "$blog_name" "$lang" "$dark" +} + +_create_posts() +{ + draft=$1 + lang=$2 + dark=$3 + + # Convert the markdown file $draft into html + # and store the result in $content + content=`multimarkdown --nolabels $draft` + + # Regex to extract the simple post name + md_regex="([a-zA-Z]+)\.(md|markdown)" + + if [[ $draft =~ $md_regex ]]; then + # If the file have md or markdown extension, cut it + post_name=${BASH_REMATCH[1]} + else + # if not and it has no extension, keep it this way + post_name=$draft + fi + + # Integrate the html converted content into a proper html file + _build_post "$post_name" "$content" "$lang" "$dark" +} + +_build_post() +{ + # Create the html file of the post $post_name with the + # previsouly converted markdown to html $content + post_name=$1 + content=$2 + lang=$3 + dark=$4 + + _add_header "$post_name" "$lang" "$dark" + echo $content >> ./posts/$post_name.html + _add_footer "$post_name" +} + +_update_index() +{ + title=$2 + lang=$3 + dark=$4 + + css="./css/indexstyle.css" + if [[ $dark =~ "y" ]]; then + css="./css/indexstyle.dark.css" + fi + + cat > index.html << EOF + + + + + $title + + + + + +

$title

+EOF + +# Retrieve the string containing all drafts names and splitting it +# into an array +drafts=$1 +drafts_list=($(echo "$drafts" | tr ' ' '\n')) + +# Number of posts in the draft list, needed for the for loop +nbposts=${#drafts_list[@]} + +# If there are posts to post, begin the list +if [ $nbposts -gt 0 ] +then + echo "" >> index.html +fi + +cat >> index.html << EOF + + +EOF +} + +_add_post_link() +{ + url=$1 + post_name=$2 + date=$3 + echo "
  • " >> index.html + echo "$post_name" >> index.html + echo "$date" >> index.html + echo "
  • " >> index.html +} + +init() +{ + echo Name of the author of the blog : + read author + echo "author:$author" > .blog.conf + echo Name of the blog : + read blog + echo "blog:$blog" >> .blog.conf + echo "Language of the blog : (en)" + read lang + if [ -z $lang ]; then + lang=en + fi + echo "lang:$lang" >> .blog.conf + echo "Activate dark mode : (y/N)" + read dark + if [ -z $lang ]; then + dark=N + fi + echo "dark:$dark" >> .blog.conf + mkdir drafts + mkdir posts + mkdir css + _init_css + _index "$blog" "$lang" +} + +_init_css() +{ + # Initiate css files for both the index and the posts, + # both dark and light themes + cat > ./css/indexstyle.css << EOF + .wrap { + width: 40vw; + margin-right: auto; + margin-left: auto; + } + .title { + margin-top: 5vh; + margin-bottom: 7vh; + text-align: center; + font-family: 'IBM Plex Mono', monospace; + } + .posts_list { + text-align: center; + padding-left: 0px; + list-style: none; + } + .post { + margin-bottom: 3vh; + font-family: 'IBM Plex Mono', monospace; + } + .post a:link { + text-decoration: none; + } + .post a:hover { + text-decoration: underline; + color: #AAA; + } + .post a { + color: black; + } + .date { + color: #777; + font-family: 'Cutive Mono', monospace; + } +EOF + +cat > ./css/indexstyle.dark.css << EOF +body { + background: #222; +} +.wrap { + width: 40vw; + margin-right: auto; + margin-left: auto; +} +.title { + margin-top: 5vh; + margin-bottom: 7vh; + color: #e1e1e1; + text-align: center; + font-family: 'IBM Plex Mono', monospace; +} +.posts_list { + text-align: center; + padding-left: 0px; + list-style: none; +} +.post { + margin-bottom: 3vh; + color: #e1e1e1; + font-family: 'IBM Plex Mono', monospace; +} +.post a:link { + color: #e1e1e1; + text-decoration: none; +} +.post a:hover { + text-decoration: underline; + color: #AAA; +} +.post a { + color: #e1e1e1; +} +.date { + color: #777; + font-family: 'Cutive Mono', monospace; +} +EOF + +cat > ./css/poststyle.css << EOF +body { + font-family: 'IBM Plex Mono', monospace; +} +.post { + width: 70vw; + margin-right: auto; + margin-left: auto; +} +EOF + +cat > ./css/poststyle.dark.css << EOF +body { + font-family: 'IBM Plex Mono', monospace; + background: #222; + color: #e1e1e1; +} +.post { + width: 70vw; + margin-right: auto; + margin-left: auto; +} +EOF + +} + +_index() +{ + title=$1 + lang=$2 + # Create the first index file, empty of any posts + cat > index.html << EOF + + + + + $title + + + + + +

    $title

    + + +EOF +} + +change_mode() +{ + # READ FILE LINE BY LINE SO THAT THE NEW CONF FILE IS NOT ON ONE LINE + echo "Activate dark mode : (y/N)" + read dark + if [ -z $lang ]; then + dark=N + fi + conf=`cat .blog.conf` + echo ${conf//dark:(y|n|N)/dark:$dark} > .blog.conf +} + +delete_posts() +{ + rm ./posts/*.html +} + +usage() +{ + echo + echo "This script is made for those who want to blog and are also addicted + to the command line" + echo + echo "Run the initiation for a start. After that, place all your future blog + posts, written in markdown (.md or .markdown), in the draft folder." + echo + echo "Once you publish your blog, all the drafts in the said folder will be + converted to html, added to the posts folder and append to the index.html" + echo + echo "To remove a post, just remove it from the draft folder and republish + your blog" + echo + echo "blog usage :" + echo " -h Display this help" + echo " -i initiate the blog" + echo " -p publish the blog" + echo " -d delete the posts" + echo " -m change mode of the blog (dark or light)" + echo " -n change the name of the blog (not implemented yet)" + echo " -l change the language of the blog (not implemented yet)" +} + +while getopts ":ihpdm" opt; do + case ${opt} in + i ) + init + ;; + p ) + publish + ;; + h ) + usage + ;; + m ) + change_mode + ;; + d ) + delete_posts + ;; + \? ) + usage + ;; + : ) + usage + ;; + esac +done