line 1
\n\nline 2
' ]] || 201 | [[ $("$converter_bin" <<< $'line 1\n\nline 2') == $'line 1
\nline 2
' ]] 202 | ) 203 | } 204 | 205 | 206 | # Parse a Markdown file into HTML and return the generated file 207 | markdown() { 208 | out=${1%.md}.html 209 | while [[ -f $out ]]; do out=${out%.html}.$RANDOM.html; done 210 | $converter_bin ${convert_args} "$1" > "$out" 211 | echo "$out" 212 | } 213 | 214 | 215 | # Prints the required google analytics code 216 | google_analytics() { 217 | [[ -z $global_analytics && -z $global_analytics_file ]] && return 218 | 219 | if [[ -z $global_analytics_file ]]; then 220 | 221 | echo " 222 | 223 | " 230 | else 231 | cat "$global_analytics_file" 232 | fi 233 | } 234 | 235 | # Prints the iframe used to show a duckduckgo search box 236 | duckduckgo_body() { 237 | if $global_enable_duckduckgo; then 238 | site=`echo "${global_url}" | awk -F/ '{print $3}'` 239 | echo "" 240 | else 241 | echo "" 242 | fi 243 | } 244 | 245 | # Reads HTML file from stdin, prints its content to stdout 246 | # $1 where to start ("text" or "entry") 247 | # $2 where to stop ("text" or "entry") 248 | # $3 "cut" to remove text from$template_tags_line_header/ ) print
258 | }
259 | }
260 | }"
261 | }
262 |
263 | # Edit an existing, published .html file while keeping its original timestamp
264 | # Please note that this function does not automatically republish anything, as
265 | # it is usually called from 'main'.
266 | #
267 | # Note that it edits HTML file, even if you wrote the post as markdown originally
268 | # Note that if you edit title then filename might also change
269 | #
270 | # $1 the file to edit
271 | # $2 (optional) edit mode:
272 | # "keep" to keep old filename
273 | # "full" to edit full HTML, and not only text part (keeps old filename)
274 | # leave empty for default behavior (edit only text part and change name)
275 | edit() {
276 | [[ ! -f "${1%%.*}.html" ]] && echo "Can't edit post "${1%%.*}.html", did you mean to use \"bb.sh post $template_tags_line_header/s|\\1|\\1|g" >> "$TMPFILE"
302 | $EDITOR "$TMPFILE"
303 | filename=$1
304 | fi
305 | rm "$filename"
306 | if [[ $2 == keep ]]; then
307 | parse_file "$TMPFILE" "$edit_timestamp" "$filename"
308 | else
309 | parse_file "$TMPFILE" "$edit_timestamp" # this command sets $filename as the html processed file
310 | [[ ${1##*.} == md ]] && mv "$1" "${filename%%.*}.md" 2>/dev/null
311 | fi
312 | rm "$TMPFILE"
313 | fi
314 | touch -t "$touch_timestamp" "$filename"
315 | touch -t "$touch_timestamp" "$1"
316 | chmod 644 "$filename"
317 | echo "Posted $filename"
318 | tags_after=$(tags_in_post "$filename")
319 | relevant_tags=$(echo "$tags_before $tags_after" | tr ',' ' ' | tr ' ' '\n' | sort -u | tr '\n' ' ')
320 | if [[ ! -z $relevant_tags ]]; then
321 | relevant_posts="$(posts_with_tags $relevant_tags) $filename"
322 | rebuild_tags "$relevant_posts" "$relevant_tags"
323 | fi
324 | }
325 |
326 | # Create a Twitter summary (twitter "card") for the post
327 | #
328 | # $1 the post file
329 | # $2 the title
330 | twitter_card() {
331 | [[ -z $global_twitter_username ]] && return
332 |
333 | echo ""
334 | echo ""
335 | echo "" # Twitter truncates at 70 char
336 | description=$(grep -v "^ $template_tags_line_header" "$1" | sed -e 's/<[^>]*>//g' | head -c 250 | tr '\n' ' ' | sed "s/\"/'/g")
337 | echo ""
338 | image=$(sed -n 's/.* $template_comments $template_twitter_button "
356 | echo " $template_comments ";
360 | fi
361 |
362 | echo "$template_twitter_button "
365 | echo " 's on the title because of markdown conversion
442 | title=${title// /}
443 | title=${title//<\/p>/}
444 | echo "$title"
445 | echo ' and $template_tags_line_header"* ]]; then
520 | tags=$(echo "$line" | cut -d ":" -f 2- | sed -e 's/<\/p>//g' -e 's/^ *//' -e 's/ *$//' -e 's/, /,/g')
521 | IFS=, read -r -a array <<< "$tags"
522 |
523 | echo -n " $template_tags_line_header " >> "$content"
524 | for item in "${array[@]}"; do
525 | echo -n "$item, "
526 | done | sed 's/, $/<\/p>/g' >> "$content"
527 | else
528 | echo "$line" >> "$content"
529 | fi
530 | done < "$1"
531 |
532 | # Create the actual html page
533 | create_html_page "$content" "$filename" no "$title" "$2" "$global_author"
534 | rm "$content"
535 | }
536 |
537 | # Manages the creation of the text file and the parsing to html file
538 | # also the drafts
539 | write_entry() {
540 | test_markdown && fmt=md || fmt=html
541 | f=$2
542 | [[ $2 == -html ]] && fmt=html && f=$3
543 |
544 | if [[ -n $f ]]; then
545 | TMPFILE=$f
546 | if [[ ! -f $TMPFILE ]]; then
547 | echo "The file doesn't exist"
548 | delete_includes
549 | exit
550 | fi
551 | # guess format from TMPFILE
552 | extension=${TMPFILE##*.}
553 | [[ $extension == md || $extension == html ]] && fmt=$extension
554 | # but let user override it (`bb.sh post -html file.md`)
555 | [[ $2 == -html ]] && fmt=html
556 | # Test if Markdown is working before re-posting a .md file
557 | if [[ $extension == md ]]; then
558 | test_markdown
559 | if (($? != 0)); then
560 | echo "Markdown is not working, please edit HTML file directly."
561 | exit
562 | fi
563 | fi
564 | else
565 | TMPFILE=.entry-$RANDOM.$fmt
566 | echo -e "Title on this line\n" >> "$TMPFILE"
567 |
568 | [[ $fmt == html ]] && cat << EOF >> "$TMPFILE"
569 | The rest of the text file is an html blog post. The process will continue as soon
570 | as you exit your editor. $template_tags_line_header keep-this-tag-format, tags-are-optional, example $template_tags_line_header/{s/^ $template_tags_line_header//;s/<[^>]*>//g;s/[ ,]\+/ /g;p;}" "$1" | tr ', ' ' '
752 | }
753 |
754 | # Finds all posts referenced in a number of tags.
755 | # Arguments are tags
756 | # Prints one line with space-separated tags to stdout
757 | posts_with_tags() {
758 | (($# < 1)) && return
759 | set -- "${@/#/$prefix_tags}"
760 | set -- "${@/%/.html}"
761 | sed -n '/^"
441 | # remove possible
'
446 | if [[ -z $timestamp ]]; then
447 | echo ""
448 | else
449 | echo ""
450 | fi
451 | if [[ -z $timestamp ]]; then
452 | echo -n "$template_archive_title
"
644 | prev_month=""
645 | while IFS='' read -r i; do
646 | is_boilerplate_file "$i" && continue
647 | echo -n "." 1>&3
648 | # Month headers
649 | month=$(LC_ALL=$date_locale date -r "$i" +"$date_allposts_header")
650 | if [[ $month != "$prev_month" ]]; then
651 | [[ -n $prev_month ]] && echo "" # Don't close ul before first header
652 | echo "$month
"
653 | echo ""
654 | prev_month=$month
655 | fi
656 | # Title
657 | title=$(get_post_title "$i")
658 | echo -n "
"
665 | echo ""
666 | } 3>&1 >"$contentfile"
667 |
668 | create_html_page "$contentfile" "$archive_index.tmp" yes "$global_title — $template_archive_title" "$global_author"
669 | mv "$archive_index.tmp" "$archive_index"
670 | chmod 644 "$archive_index"
671 | rm "$contentfile"
672 | }
673 |
674 | # Create an index page with all the tags
675 | all_tags() {
676 | echo -n "Creating an index page with all the tags "
677 | contentfile=$tags_index.$RANDOM
678 | while [[ -f $contentfile ]]; do
679 | contentfile=$tags_index.$RANDOM
680 | done
681 |
682 | {
683 | echo "$template_tags_title
"
684 | echo ""
685 | for i in $prefix_tags*.html; do
686 | [[ -f "$i" ]] || break
687 | echo -n "." 1>&3
688 | nposts=$(grep -c "<\!-- text begin -->" "$i")
689 | tagname=${i#"$prefix_tags"}
690 | tagname=${tagname%.html}
691 | case $nposts in
692 | 1) word=$template_tags_posts_singular;;
693 | 2|3|4) word=$template_tags_posts_2_4;;
694 | *) word=$template_tags_posts;;
695 | esac
696 | echo "
"
700 | echo ""
701 | } 3>&1 > "$contentfile"
702 |
703 | create_html_page "$contentfile" "$tags_index.tmp" yes "$global_title — $template_tags_title" "$global_author"
704 | mv "$tags_index.tmp" "$tags_index"
705 | chmod 644 "$tags_index"
706 | rm "$contentfile"
707 | }
708 |
709 | # Generate the index.html with the content of the latest posts
710 | rebuild_index() {
711 | echo -n "Rebuilding the index "
712 | newindexfile=$index_file.$RANDOM
713 | contentfile=$newindexfile.content
714 | while [[ -f $newindexfile ]]; do
715 | newindexfile=$index_file.$RANDOM
716 | contentfile=$newindexfile.content
717 | done
718 |
719 | # Create the content file
720 | {
721 | n=0
722 | while IFS='' read -r i; do
723 | is_boilerplate_file "$i" && continue;
724 | if ((n >= number_of_index_articles)); then break; fi
725 | if [[ -n $cut_do ]]; then
726 | get_html_file_content 'entry' 'entry' 'cut' <"$i" | awk "/$cut_line/ { print \"\" ; next } 1"
727 | else
728 | get_html_file_content 'entry' 'entry' <"$i"
729 | fi
730 | echo -n "." 1>&3
731 | n=$(( n + 1 ))
732 | done < <(ls -t ./*.html) # sort by date, newest first
733 |
734 | feed=$blog_feed
735 | if [[ -n $global_feedburner ]]; then feed=$global_feedburner; fi
736 | echo ""
737 | } 3>&1 >"$contentfile"
738 |
739 | echo ""
740 |
741 | create_html_page "$contentfile" "$newindexfile" yes "$global_title" "$global_author"
742 | rm "$contentfile"
743 | mv "$newindexfile" "$index_file"
744 | chmod 644 "$index_file"
745 | }
746 |
747 | # Finds all tags referenced in one post.
748 | # Accepts either filename as first argument, or post content at stdin
749 | # Prints one line with space-separated tags to stdout
750 | tags_in_post() {
751 | sed -n "/^/{s/.*href="\([^"]*\)">.*/\1/;p;}' "$@" 2> /dev/null
762 | }
763 |
764 | # Rebuilds tag_*.html files
765 | # if no arguments given, rebuilds all of them
766 | # if arguments given, they should have this format:
767 | # "FILE1 [FILE2 [...]]" "TAG1 [TAG2 [...]]"
768 | # where FILEn are files with posts which should be used for rebuilding tags,
769 | # and TAGn are names of tags which should be rebuilt.
770 | # example:
771 | # rebuild_tags "one_post.html another_article.html" "example-tag another-tag"
772 | # mind the quotes!
773 | rebuild_tags() {
774 | if (($# < 2)); then
775 | # will process all files and tags
776 | files=$(ls -t ./*.html)
777 | all_tags=yes
778 | else
779 | # will process only given files and tags
780 | files=$(printf '%s\n' $1 | sort -u)
781 | files=$(ls -t $files)
782 | tags=$2
783 | fi
784 | echo -n "Rebuilding tag pages "
785 | n=0
786 | if [[ -n $all_tags ]]; then
787 | rm ./"$prefix_tags"*.html &> /dev/null
788 | else
789 | for i in $tags; do
790 | rm "./$prefix_tags$i.html" &> /dev/null
791 | done
792 | fi
793 | # First we will process all files and create temporal tag files
794 | # with just the content of the posts
795 | tmpfile=tmp.$RANDOM
796 | while [[ -f $tmpfile ]]; do tmpfile=tmp.$RANDOM; done
797 | while IFS='' read -r i; do
798 | is_boilerplate_file "$i" && continue;
799 | echo -n "."
800 | if [[ -n $cut_do ]]; then
801 | get_html_file_content 'entry' 'entry' 'cut' <"$i" | awk "/$cut_line/ { print \"\" ; next } 1"
802 | else
803 | get_html_file_content 'entry' 'entry' <"$i"
804 | fi >"$tmpfile"
805 | for tag in $(tags_in_post "$i"); do
806 | if [[ -n $all_tags || " $tags " == *" $tag "* ]]; then
807 | cat "$tmpfile" >> "$prefix_tags$tag".tmp.html
808 | fi
809 | done
810 | done <<< "$files"
811 | rm "$tmpfile"
812 | # Now generate the tag files with headers, footers, etc
813 | while IFS='' read -r i; do
814 | tagname=${i#./"$prefix_tags"}
815 | tagname=${tagname%.tmp.html}
816 | create_html_page "$i" "$prefix_tags$tagname.html" yes "$global_title — $template_tag_title \"$tagname\"" "$global_author"
817 | rm "$i"
818 | done < <(ls -t ./"$prefix_tags"*.tmp.html 2>/dev/null)
819 | echo
820 | }
821 |
822 | # Return the post title
823 | #
824 | # $1 the html file
825 | get_post_title() {
826 | awk '/
/, /<\/a><\/h3>/{if (!/
/ && !/<\/a><\/h3>/) print}' "$1"
827 | }
828 |
829 | # Return the post author
830 | #
831 | # $1 the html file
832 | get_post_author() {
833 | awk '/
$global_title
"
926 | echo "