INITIAL COMMIT

This commit is contained in:
Simon Petit 2019-07-03 21:55:00 +02:00
commit 44aa28f25e
3 changed files with 545 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
drafts
drafts2
css
bash
posts
*.conf
index.html
README.html

63
README.md Normal file
View File

@ -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.

474
blog.sh Executable file
View File

@ -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
<!DOCTYPE html>
<html lang="$lang" dir="ltr">
<head>
<meta charset="utf-8">
<title>$post_name</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link href="https://fonts.googleapis.com/css?family=Cutive+Mono|IBM+Plex+Mono&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="$css">
</head>
<body>
<article class='post'>
EOF
}
_add_footer()
{
post_name=$1
cat >> ./posts/$post_name.html << EOF
</article>
<footer>
</footer>
</body>
</html>
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
<!DOCTYPE html>
<html lang="$lang" dir="ltr">
<head>
<meta charset="utf-8">
<title>$title</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link href="https://fonts.googleapis.com/css?family=Cutive+Mono|IBM+Plex+Mono&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="$css">
</head>
<body>
<h1 class='title'>$title</h1>
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 "<ul class='posts_list'>" >> index.html
fi
# Regex to extract just the name of the post
post_regex="([a-zA-Z]+)\.md"
for (( i=0; i<${#drafts_list[@]}; i++ ));
do
# Retrieve the date of the last modification of the draft
date=$(_get_last_modif_date "./drafts/${drafts_list[i]}")
# In case the next regex doesn't work, even though it's supposed to
# work everytime
post_name="unknown"
# Extract the strict name of the post in the same
# order of the drafts because they are sorted according
# to the last modification date
if [[ ${drafts_list[i]} =~ $post_regex ]]; then
post_name=${BASH_REMATCH[1]}
fi
# Function to add items to the posts list
_add_post_link "./posts/$post_name.html" "$post_name" "$date"
done
# If there are posts posted, close the list
if [ $nbposts -gt 0 ]; then
echo "</ul>" >> index.html
fi
cat >> index.html << EOF
</body>
</html>
EOF
}
_add_post_link()
{
url=$1
post_name=$2
date=$3
echo "<li class='post'>" >> index.html
echo "<a href="$url">$post_name</a>" >> index.html
echo "<span class='date'>$date</span>" >> index.html
echo "</li>" >> 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
<!DOCTYPE html>
<html lang="$lang" dir="ltr">
<head>
<meta charset="utf-8">
<title>$title</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<link href="https://fonts.googleapis.com/css?family=Cutive+Mono|IBM+Plex+Mono&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./css/indexstyle.css">
</head>
<body>
<h1 class='title'>$title</h1>
</body>
</html>
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