diff --git a/bb.sh b/bb.sh index a53ce6d..c071ea2 100755 --- a/bb.sh +++ b/bb.sh @@ -168,7 +168,7 @@ test_markdown() { good=/tmp/md-good-${RANDOM}.html echo -e "line 1\n\nline 2" > "$in" echo -e "

line 1

\n\n

line 2

" > "$good" - $markdown_bin $in > $out 2> /dev/null + "$markdown_bin" "$in" > "$out" 2> /dev/null diff $good $out &> /dev/null # output is irrelevant, we'll check $? if (($? != 0)); then rm -f "$in" "$good" "$out" @@ -182,8 +182,8 @@ test_markdown() { # Parse a Markdown file into HTML and return the generated file markdown() { - out=$(echo $1 | sed 's/md$/html/g') - while [[ -f $out ]]; do out=$(echo $out | sed 's/\.html$/\.'$RANDOM'\.html/'); done + out=${1%.md}.html + while [[ -f $out ]]; do out=${out%.html}.$RANDOM.html; done $markdown_bin "$1" > "$out" echo "$out" } @@ -256,15 +256,15 @@ disqus_footer() { # note that this does not remove
line itself, # so you can see if text was cut or not get_html_file_content() { - awk '//, //{ - if (!// && !//) print - if ("'$3'" == "cut" && /'"$cut_line"'/){ - if ("'$2'" == "text") exit # no need to read further + awk "//, //{ + if (!// && !//) print + if (\"$3\" == \"cut\" && /$cut_line/){ + if (\"$2\" == \"text\") exit # no need to read further while (getline > 0 && !//) { - if ("'$cut_tags'" == "no" && /^'"

$template_tags_line_header"'/ ) print + if (\"$cut_tags\" == \"no\" && /^

$template_tags_line_header/ ) print } } - }' + }" } # Edit an existing, published .html file while keeping its original timestamp @@ -300,11 +300,11 @@ edit() { filename=${1%%.*}.html else # Create the content file - TMPFILE=$(basename $1).$RANDOM.html + TMPFILE=$(basename "$1").$RANDOM.html # Title - echo "$(get_post_title $1)" > "$TMPFILE" + get_post_title "$1" > "$TMPFILE" # Post text with plaintext tags - get_html_file_content 'text' 'text' <$1 | sed "/^

$template_tags_line_header/s|\\1|\\1|g" >> "$TMPFILE" + get_html_file_content 'text' 'text' <"$1" | sed "/^

$template_tags_line_header/s|\\1|\\1|g" >> "$TMPFILE" $EDITOR "$TMPFILE" filename=$1 fi @@ -320,10 +320,10 @@ edit() { touch -t "$touch_timestamp" "$filename" chmod 644 "$filename" echo "Posted $filename" - tags_after=$(tags_in_post $filename) + tags_after=$(tags_in_post "$filename") relevant_tags=$(echo "$tags_before $tags_after" | tr ',' ' ' | tr ' ' '\n' | sort -u | tr '\n' ' ') if [[ ! -z $relevant_tags ]]; then - relevant_posts="$(posts_with_tags $relevant_tags) $filename" + relevant_posts="$(posts_with_tags "$relevant_tags") $filename" rebuild_tags "$relevant_posts" "$relevant_tags" fi } @@ -338,11 +338,11 @@ twitter_card() { echo "" echo "" echo "" # Twitter truncates at 70 char - description=$(grep -v "^

$template_tags_line_header" $1 | sed -e 's/<[^>]*>//g' | head -c 250 | tr '\n' ' ' | sed "s/\"/'/g") + description=$(grep -v "^

$template_tags_line_header" "$1" | sed -e 's/<[^>]*>//g' | head -c 250 | tr '\n' ' ' | sed "s/\"/'/g") echo "" - image=$(sed -n 's/.*" } @@ -362,8 +362,8 @@ twitter() { echo "

$template_comments $template_twitter_button " echo " 

" # Get current tweet count - echo '' + echo "" return; else echo "

$template_comments "; @@ -387,7 +387,7 @@ twitter() { # Return 0 (bash return value 'true') if the input file is an index, feed, etc # or 1 (bash return value 'false') if it is a blogpost is_boilerplate_file() { - name=$(clean_filename $1) + name=$(clean_filename "$1") case $name in ( "$index_file" | "$archive_index" | "$tags_index" | "$footer_file" | "$header_file" | "$global_analytics_file" | "$prefix_tags"* ) return 0 ;; @@ -404,9 +404,7 @@ is_boilerplate_file() { # $1 the file name # returns the clean file name clean_filename() { - name=$1 - [[ ${name:0:2} == ./ ]] && name=${name:2} # Delete leading './' - echo $name + echo "${1#./}" # Delete leading './' } # Adds all the bells and whistles to format the html page @@ -429,59 +427,61 @@ create_html_page() { # Create the actual blog post # html, head - cat ".header.html" > "$filename" - echo "$title" >> "$filename" - google_analytics >> "$filename" - twitter_card "$content" "$title" >> "$filename" - echo "" >> "$filename" - # stuff to add before the actual body content - [[ -n $body_begin_file ]] && cat "$body_begin_file" >> "$filename" - # body divs - echo '

' >> "$filename" - echo '
' >> "$filename" - # blog title - echo '
' >> "$filename" - cat .title.html >> "$filename" - echo '
' >> "$filename" # title, header, headerholder - echo '
' >> "$filename" + { + cat ".header.html" + echo "$title" + google_analytics + twitter_card "$content" "$title" + echo "" + # stuff to add before the actual body content + [[ -n $body_begin_file ]] && cat "$body_begin_file" + # body divs + echo '
' + echo '
' + # blog title + echo '
' + cat .title.html + echo '
' # title, header, headerholder + echo '
' - file_url=$(clean_filename $filename) - file_url=$(sed 's/.rebuilt//g' <<< $file_url) # Get the correct URL when rebuilding - # one blog entry - if [[ $index == no ]]; then - echo '' >> "$filename" # marks the beginning of the whole post - echo '

' >> "$filename" - # remove possible

's on the title because of markdown conversion - echo "$(echo "$title" | sed 's/<\/*p>//g')" >> "$filename" - echo '

' >> "$filename" - if [[ -z $timestamp ]]; then - echo '
'$(LC_ALL=$date_locale date +"$date_format")' — ' >> "$filename" - else - echo '
'$(LC_ALL=$date_locale date +"$date_format" --date="$timestamp") ' — ' >> "$filename" + file_url=$(clean_filename "$filename") + file_url=$(sed 's/.rebuilt//g' <<< "$file_url") # Get the correct URL when rebuilding + # one blog entry + if [[ $index == no ]]; then + echo '' # marks the beginning of the whole post + echo "

" + # remove possible

's on the title because of markdown conversion + echo "$title" | sed 's/<\/*p>//g' + echo '

' + if [[ -z $timestamp ]]; then + echo "
$(LC_ALL=$date_locale date +"$date_format") — " + else + echo "
$(LC_ALL=$date_locale date +"$date_format" --date="$timestamp") — " + fi + echo "$global_author
" + echo '' # This marks the text body, after the title, date... fi - echo "$global_author
" >> "$filename" - echo '' >> "$filename" # This marks the text body, after the title, date... - fi - cat "$content" >> "$filename" # Actual content - if [[ $index == no ]]; then - echo -e '\n' >> "$filename" + cat "$content" # Actual content + if [[ $index == no ]]; then + echo -e '\n' - twitter "$global_url/$file_url" >> "$filename" + twitter "$global_url/$file_url" - echo '' >> "$filename" # absolute end of the post - fi + echo '' # absolute end of the post + fi - echo '
' >> "$filename" # content + echo '
' # content - # Add disqus commments except for index and all_posts pages - [[ $index == no ]] && disqus_body >> "$filename" + # Add disqus commments except for index and all_posts pages + [[ $index == no ]] && disqus_body - # page footer - cat .footer.html >> "$filename" - # close divs - echo '
' >> "$filename" # divbody and divbodyholder - disqus_footer >> "$filename" - echo '' >> "$filename" + # page footer + cat .footer.html + # close divs + echo '
' # divbody and divbodyholder + disqus_footer + echo '' + } > "$filename" } # Parse the plain text file into an html file @@ -504,7 +504,7 @@ parse_file() { else filename=$title [[ -n $convert_filename ]] && - filename=$(echo $title | eval $convert_filename) + filename=$(echo "$title" | eval "$convert_filename") [[ -n $filename ]] || filename=$RANDOM # don't allow empty filenames @@ -512,8 +512,7 @@ parse_file() { # Check for duplicate file names while [[ -f $filename ]]; do - suffix=$RANDOM - filename=$(echo $filename | sed 's/\.html/'$suffix'\.html/g') + filename=${filename%.html}$RANDOM.html done fi content=$filename.tmp @@ -600,13 +599,13 @@ EOF echo "To preview the entry, open $preview_url/$filename in your browser" echo -n "[P]ost this entry, [E]dit again, [D]raft for later? (p/E/d) " - read post_status + read -r post_status if [[ $post_status == d || $post_status == D ]]; then mkdir -p "drafts/" chmod 700 "drafts/" title=$(head -n 1 $TMPFILE) - [[ -n $convert_filename ]] && title=$(echo $title | eval $convert_filename) + [[ -n $convert_filename ]] && title=$(echo "$title" | eval "$convert_filename") [[ -n $title ]] || title=$RANDOM draft=drafts/$title.$fmt @@ -641,29 +640,31 @@ all_posts() { contentfile=$archive_index.$RANDOM done - echo "

$template_archive_title

" >> "$contentfile" - prev_month="" - for i in $(ls -t ./*.html); do - is_boilerplate_file "$i" && continue - echo -n "." - # Month headers - month=$(LC_ALL=$date_locale date -r "$i" +"$date_allposts_header") - if [[ $month != "$prev_month" ]]; then - [[ -n $prev_month ]] && echo "" >> "$contentfile" # Don't close ul before first header - echo "

$month

" >> "$contentfile" - echo "" >> "$contentfile" - echo '' >> "$contentfile" + { + echo "

$template_archive_title

" + prev_month="" + for i in $(ls -t ./*.html); do + is_boilerplate_file "$i" && continue + echo -n "." 1>&3 + # Month headers + month=$(LC_ALL=$date_locale date -r "$i" +"$date_allposts_header") + if [[ $month != "$prev_month" ]]; then + [[ -n $prev_month ]] && echo "" # Don't close ul before first header + echo "

$month

" + echo "" + echo "" + } 3>&1 >"$contentfile" create_html_page "$contentfile" "$archive_index.tmp" yes "$global_title — $template_archive_title" mv "$archive_index.tmp" "$archive_index" @@ -679,18 +680,21 @@ all_tags() { contentfile=$tags_index.$RANDOM done - echo "

$template_tags_title

" >> "$contentfile" - echo "" >> "$contentfile" - echo '' >> "$contentfile" + { + echo "

$template_tags_title

" + echo "" + echo "" + } 3>&1 > "$contentfile" create_html_page "$contentfile" "$tags_index.tmp" yes "$global_title — $template_tags_title" mv "$tags_index.tmp" "$tags_index" @@ -709,22 +713,24 @@ rebuild_index() { done # Create the content file - n=0 - for i in $(ls -t ./*.html); do # sort by date, newest first - is_boilerplate_file "$i" && continue; - if ((n >= number_of_index_articles)); then break; fi - if [[ -n $cut_do ]]; then - get_html_file_content 'entry' 'entry' 'cut' <$i | awk '/'"$cut_line"'/ { print "

'"$template_read_more"'

" ; next } 1' >> "$contentfile" - else - get_html_file_content 'entry' 'entry' <$i >> "$contentfile" - fi - echo -n "." - n=$(( n + 1 )) - done + { + n=0 + for i in $(ls -t ./*.html); do # sort by date, newest first + is_boilerplate_file "$i" && continue; + if ((n >= number_of_index_articles)); then break; fi + if [[ -n $cut_do ]]; then + get_html_file_content 'entry' 'entry' 'cut' <"$i" | awk "/$cut_line/ { print \"

$template_read_more

\" ; next } 1" + else + get_html_file_content 'entry' 'entry' <"$i" + fi + echo -n "." 1>&3 + n=$(( n + 1 )) + done - feed=$blog_feed - if [[ -n $global_feedburner ]]; then feed=$global_feedburner; fi - echo '' >> "$contentfile" + feed=$blog_feed + if [[ -n $global_feedburner ]]; then feed=$global_feedburner; fi + echo "" + } 3>&1 >"$contentfile" echo "" @@ -774,10 +780,10 @@ rebuild_tags() { echo -n "Rebuilding tag pages " n=0 if [[ -n $all_tags ]]; then - rm ./$prefix_tags*.html &> /dev/null + rm ./"$prefix_tags"*.html &> /dev/null else for i in $tags; do - rm ./$prefix_tags$i.html &> /dev/null + rm "./$prefix_tags$i.html" &> /dev/null done fi # First we will process all files and create temporal tag files @@ -787,11 +793,11 @@ rebuild_tags() { echo -n "." tmpfile=$(mktemp tmp.XXX) if [[ -n $cut_do ]]; then - get_html_file_content 'entry' 'entry' 'cut' <$i | awk '/'"$cut_line"'/ { print "

'"$template_read_more"'

" ; next } 1' >> "$tmpfile" + get_html_file_content 'entry' 'entry' 'cut' <"$i" | awk "/$cut_line/ { print \"

$template_read_more

\" ; next } 1" else - get_html_file_content 'entry' 'entry' <$i >> "$tmpfile" - fi - for tag in $(tags_in_post $i); do + get_html_file_content 'entry' 'entry' <"$i" + fi >"$tmpfile" + for tag in $(tags_in_post "$i"); do if [[ -n $all_tags || " $tags " == *" $tag "* ]]; then cat "$tmpfile" >> "$prefix_tags$tag".tmp.html fi @@ -800,7 +806,7 @@ rebuild_tags() { done # Now generate the tag files with headers, footers, etc for i in $(ls -t ./$prefix_tags*.tmp.html 2>/dev/null || echo ''); do - tagname=$(echo $i | cut -c $((${#prefix_tags}+3))- | sed 's/\.tmp\.html//g') + tagname=$(echo "$i" | cut -c "$((${#prefix_tags}+3))-" | sed 's/\.tmp\.html//g') create_html_page "$i" "$prefix_tags$tagname.html" yes "$global_title — $template_tag_title \"$tagname\"" rm "$i" done @@ -823,7 +829,7 @@ list_posts() { n=1 for i in $(ls -t ./*.html); do is_boilerplate_file "$i" && continue - line="$n # $(get_post_title "$i") # $(LC_ALL=$date_locale date -r $i +"$date_format")" + line="$n # $(get_post_title "$i") # $(LC_ALL=$date_locale date -r "$i" +"$date_format")" lines+=$line\\n n=$(( n + 1 )) done @@ -838,32 +844,35 @@ make_rss() { rssfile=$blog_feed.$RANDOM while [[ -f $rssfile ]]; do rssfile=$blog_feed.$RANDOM; done - echo '' >> "$rssfile" - echo '' >> "$rssfile" - echo ''$global_title''$global_url'' >> "$rssfile" - echo ''$global_description'en' >> "$rssfile" - echo ''$(LC_ALL=C date +"%a, %d %b %Y %H:%M:%S %z")'' >> "$rssfile" - echo ''$(LC_ALL=C date +"%a, %d %b %Y %H:%M:%S %z")'' >> "$rssfile" - echo '' >> "$rssfile" - - n=0 - for i in $(ls -t ./*.html); do - is_boilerplate_file "$i" && continue - ((n >= number_of_feed_articles)) && break # max 10 items - echo -n "." - echo '' >> "$rssfile" - echo "$(get_post_title "$i")" >> "$rssfile" - echo '> "$rssfile" - echo "$(get_html_file_content 'text' 'entry' $cut_do <$i)" >> "$rssfile" - echo "]]>$global_url/$(clean_filename $i)" >> "$rssfile" - echo "$global_url/$i" >> "$rssfile" - echo "$global_author" >> "$rssfile" - echo ''$(LC_ALL=C date -r "$i" +"%a, %d %b %Y %H:%M:%S %z")'' >> "$rssfile" - - n=$(( n + 1 )) - done - - echo '' >> "$rssfile" + { + pubdate=$(LC_ALL=C date +"%a, %d %b %Y %H:%M:%S %z") + echo '' + echo '' + echo "$global_title$global_url" + echo "$global_descriptionen" + echo "$pubdate" + echo "$pubdate" + echo "" + + n=0 + for i in $(ls -t ./*.html); do + is_boilerplate_file "$i" && continue + ((n >= number_of_feed_articles)) && break # max 10 items + echo -n "." 1>&3 + echo '' + get_post_title "$i" + echo '$global_url/$(clean_filename "$i")" + echo "$global_url/$i" + echo "$global_author" + echo "$(LC_ALL=C date -r "$i" +"%a, %d %b %Y %H:%M:%S %z")" + + n=$(( n + 1 )) + done + + echo '' + } 3>&1 >"$rssfile" echo "" mv "$rssfile" "$blog_feed" @@ -872,28 +881,33 @@ make_rss() { # generate headers, footers, etc create_includes() { - echo '

'$global_title'

' > ".title.html" - echo '
'$global_description'
' >> ".title.html" + { + echo "

$global_title

" + echo "
$global_description
" + } > ".title.html" if [[ -f $header_file ]]; then cp "$header_file" .header.html - else - echo '' > ".header.html" - echo '' >> ".header.html" - echo '' >> ".header.html" - echo '' >> ".header.html" - printf '\n' "${css_include[@]}" >> ".header.html" + else { + echo '' + echo '' + echo '' + echo '' + printf '\n' "${css_include[@]}" if [[ -z $global_feedburner ]]; then - echo '' >> ".header.html" + echo "" else - echo '' >> ".header.html" + echo "" fi + } > ".header.html" fi if [[ -f $footer_file ]]; then cp "$footer_file" .footer.html - else - protected_mail=$(echo "$global_email" | sed 's/@/\@/g' | sed 's/\./\./g') - echo '' >> ".footer.html" + else { + protected_mail=${global_email//@/@} + protected_mail=${protected_mail//./.} + echo "
$global_license $global_author$protected_mail
" + echo 'Generated with bashblog, a single bash script to easily create blogs like this one
' + } >> ".footer.html" fi } @@ -961,14 +975,14 @@ rebuild_all_entries() { echo -n "." # Get the title and entry, and rebuild the html structure from scratch (divs, title, description...) title=$(get_post_title "$i") - get_html_file_content 'text' 'text' <$i >> "$contentfile" + get_html_file_content 'text' 'text' <"$i" >> "$contentfile" # Original post timestamp - timestamp=$(LC_ALL=C date -r $i +"%a, %d %b %Y %H:%M:%S %z" ) + timestamp=$(LC_ALL=C date -r "$i" +"%a, %d %b %Y %H:%M:%S %z" ) create_html_page "$contentfile" "$i.rebuilt" no "$title" "$timestamp" # keep the original timestamp! - timestamp=$(LC_ALL=C date -r $i +'%Y%m%d%H%M') + timestamp=$(LC_ALL=C date -r "$i" +'%Y%m%d%H%M') mv "$i.rebuilt" "$i" chmod 644 "$i" touch -t "$timestamp" "$i" @@ -1026,11 +1040,11 @@ date_version_detect() { date() { if [[ $1 == -r ]]; then # Fall back to using stat for 'date -r' - format=$(echo $3 | sed 's/\+//g') + format=${3//+/} stat -f "%Sm" -t "$format" "$2" - elif [[ $* == *--date* ]]; then + elif [[ $2 == --date* ]]; then # convert between dates using BSD date syntax - command date -j -f "%a, %d %b %Y %H:%M:%S %z" "$(echo $2 | sed 's/\-\-date\=//g')" "$1" + command date -j -f "%a, %d %b %Y %H:%M:%S %z" "${2#--date=}" "$1" else # acceptable format for BSD date command date -j "$@"