diff options
Diffstat (limited to 'www')
-rw-r--r-- | www/Makefile | 5 | ||||
-rwxr-xr-x | www/scripts/build.sh | 172 |
2 files changed, 91 insertions, 86 deletions
diff --git a/www/Makefile b/www/Makefile index ab6a39e..cf45b29 100644 --- a/www/Makefile +++ b/www/Makefile | |||
@@ -4,8 +4,9 @@ ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) | |||
4 | # build html files for public/ | 4 | # build html files for public/ |
5 | build: | 5 | build: |
6 | cd $(ROOT_DIR) | 6 | cd $(ROOT_DIR) |
7 | export input_dir=~/log/public | 7 | export INPUT_DIR=~/log/public |
8 | export output_dir=/srv/http | 8 | export OUTPUT_DIR=/srv/http |
9 | export HOST=topo.tw | ||
9 | @scripts/build.sh | 10 | @scripts/build.sh |
10 | 11 | ||
11 | # Migrage frontmatter from '---' to HTML comment '<!-- -->' | 12 | # Migrage frontmatter from '---' to HTML comment '<!-- -->' |
diff --git a/www/scripts/build.sh b/www/scripts/build.sh index e3757ac..23c4a70 100755 --- a/www/scripts/build.sh +++ b/www/scripts/build.sh | |||
@@ -3,13 +3,15 @@ | |||
3 | set -e | 3 | set -e |
4 | 4 | ||
5 | # Executable command for markdown | 5 | # Executable command for markdown |
6 | markdown_bin="markdown -f fencedcode,autolink,alphalist,autolink,footnote,definitionlist" | 6 | declare -r MARKDOWN_BIN="markdown -f fencedcode,autolink,alphalist,autolink,footnote,definitionlist" |
7 | 7 | ||
8 | # Directory for input/output | 8 | # Directory for input/output |
9 | input_dir=${input_dir:?ENV \"input_dir\" is not set} | 9 | declare -r INPUT_DIR=${INPUT_DIR:?ENV \"INPUT_DIR\" is not set} |
10 | output_dir=${output_dir:?ENV \"output_dir\" is not set} | 10 | declare -r OUTPUT_DIR=${OUTPUT_DIR:?ENV \"OUTPUT_DIR\" is not set} |
11 | assets_dir=${assets_dir:-`pwd`/assets} | 11 | declare -r ASSET_DIR=${ASSET_DIR:-`pwd`/assets} |
12 | template_dir=${template_dir:-`pwd`/templates} | 12 | declare -r TEMPLATE_DIR=${TEMPLATE_DIR:-`pwd`/templates} |
13 | declare -r RSSFILE=feed.rss | ||
14 | declare -r HOST=${HOST:?} | ||
13 | 15 | ||
14 | # functions {{{ | 16 | # functions {{{ |
15 | 17 | ||
@@ -41,22 +43,22 @@ comment_block() { | |||
41 | } | 43 | } |
42 | 44 | ||
43 | # }}} | 45 | # }}} |
44 | # use heredoc to generate html from .md file and templates {{{ | 46 | # generate html by heredoc from .md file and templates {{{ |
45 | html() { | 47 | html() { |
46 | <<-END_OF_HTML sed '1d;$d' | 48 | <<-END_OF_HTML sed '1d;$d' |
47 | 49 | ||
48 | <!DOCTYPE html> | 50 | <!DOCTYPE html> |
49 | <html lang="en"> | 51 | <html lang="en"> |
50 | ${head} | 52 | $(echo "$HEAD" | { [ -z "${title}" ] && cat || sed "/^ *<title>/c \ \ <title>${title}</title>"; } ) |
51 | <body> | 53 | <body> |
52 | ${header} | 54 | ${HEADER} |
53 | <hr><br> | 55 | <hr><br> |
54 | <main> | 56 | <main> |
55 | $(${markdown_bin} | indent 4) | 57 | $(${MARKDOWN_BIN} | indent 4) |
56 | </main> | 58 | </main> |
57 | $(comment_block | indent 2) | 59 | $(comment_block | indent 2) |
58 | <br><hr> | 60 | <br><hr> |
59 | ${footer} | 61 | ${FOOTER} |
60 | </body> | 62 | </body> |
61 | </html> | 63 | </html> |
62 | 64 | ||
@@ -73,31 +75,28 @@ latest_posts() { | |||
73 | } | 75 | } |
74 | 76 | ||
75 | # }}} | 77 | # }}} |
76 | # print frontmatter from markdown file with format: "<key> <value>" {{{ | 78 | # process frontmatter {{{ |
77 | 79 | ||
78 | get_frontmatter() { | 80 | get_frontmatter() { |
79 | sed -n '1 {/<!--/ !q; n}; /-->/q; s/"//g; s/://p' | 81 | sed -n '1 {/<!--/ !q; n}; /-->/q; s/"//g; s/://p' |
80 | } | 82 | } |
81 | 83 | ||
82 | # }}} | 84 | check_frontmatter() { |
83 | # process frontmatter {{{ | 85 | unset title public index type date draft |
84 | |||
85 | add_index() { | ||
86 | unset title public index date draft | ||
87 | 86 | ||
88 | # define local variables for frontmatter | 87 | # define local variables for frontmatter |
89 | while read key value; do | 88 | while read key value; do |
90 | local -r $key="$value" | 89 | export ${key,,}="$value" |
91 | done <<<"$(get_frontmatter)" | 90 | done <<<"$(get_frontmatter)" |
92 | 91 | ||
93 | # don't process draft after function call | 92 | # don't process draft after function call |
94 | test "$draft" != "" && return 1 | 93 | test "$draft" != "" && return 1 |
95 | 94 | ||
96 | # skip making index in some cases | 95 | # skip making index in some cases |
96 | test "$title" = "" && return 0 | ||
97 | test "$public" = false && return 0 | 97 | test "$public" = false && return 0 |
98 | test "$index" = false && return 0 | 98 | test "$index" = false && return 0 |
99 | test "$type" = demo && return 0 | 99 | test "$type" = demo && return 0 |
100 | test "$title" = "" && return 0 | ||
101 | iso8601=$(date --iso --date "${date:-NULL}" 2>/dev/null) | 100 | iso8601=$(date --iso --date "${date:-NULL}" 2>/dev/null) |
102 | test "$iso8601" = "" && return 0 | 101 | test "$iso8601" = "" && return 0 |
103 | 102 | ||
@@ -109,99 +108,97 @@ add_index() { | |||
109 | # remove SGML comments but keep the top one as frontmatter {{{ | 108 | # remove SGML comments but keep the top one as frontmatter {{{ |
110 | 109 | ||
111 | ignore_comment() { | 110 | ignore_comment() { |
112 | sed '1 !{ /^<!--$/,/^-->$/ d }' | 111 | sed '1! { /^<!--$/,/^-->$/ d }' |
113 | } | 112 | } |
114 | 113 | ||
115 | # }}} | 114 | # }}} |
116 | # Generate the feed file {{{ | 115 | # RSS Feed {{{ |
116 | |||
117 | get_channel_item() { | ||
118 | path=${1#${OUTPUT_DIR}} | ||
119 | <<-ITEM cat | ||
120 | <item> | ||
121 | $(grep -Po '<title>.+</title>' ${1} | head -1) | ||
122 | <link>https://${HOST}${path}</link> | ||
123 | <guid isPermaLink="false">$(md5sum ${1} | cut -d' ' -f1)</guid> | ||
124 | <pubDate>$(date --rfc-email -r ${1})</pubDate> | ||
125 | </item> | ||
126 | ITEM | ||
127 | } | ||
117 | 128 | ||
118 | make_rss() { | 129 | make_rss() { |
119 | echo -n "Making RSS " | 130 | # Use modified time to get latest html files |
120 | 131 | items="$( | |
121 | rssfile=$blog_feed.$RANDOM | 132 | ls -1t $OUTPUT_DIR/**/**html \ |
122 | while [[ -f $rssfile ]]; do rssfile=$blog_feed.$RANDOM; done | 133 | | head -10 \ |
123 | 134 | | while read html_file; do | |
124 | { | 135 | get_channel_item $html_file |
125 | pubdate=$(LC_ALL=C date +"$date_format_full") | 136 | done \ |
126 | cat <<-EOF | 137 | | indent 2 \ |
127 | <?xml version="1.0" encoding="UTF-8" ?>' | 138 | )" |
128 | <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">' | 139 | |
129 | <channel><title>Dummy Website</title><link>https://topo.tw/index.xml</link>" | 140 | <<-RSS cat |
130 | <description>$global_description</description><language>en</language>" | 141 | <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" > |
131 | <lastBuildDate>$pubdate</lastBuildDate>" | 142 | <channel> |
132 | <pubDate>$pubdate</pubDate>" | 143 | <title>Dummy Website</title> |
133 | <atom:link href="$global_url/$blog_feed" rel="self" type="application/rss+xml" />" | 144 | <link>https://${HOST}</link> |
134 | EOF | 145 | <atom:link href="http://${HOST}/${RSSFILE}" rel="self" type="application/rss+xml" /> |
135 | 146 | <description>$global_description</description> | |
136 | n=0 | 147 | <language>zh-tw</language> |
137 | while IFS='' read -r i; do | 148 | <pubDate>$(date --rfc-email)</pubDate> |
138 | is_boilerplate_file "$i" && continue | 149 | <docs>https://www.rssboard.org/rss-specification</docs> |
139 | ((n >= number_of_feed_articles)) && break # max 10 items | 150 | ${items} |
140 | echo -n "." 1>&3 | 151 | </channel> |
141 | echo '<item><title>' | 152 | </rss> |
142 | get_post_title "$i" | 153 | RSS |
143 | echo '</title><description><![CDATA[' | ||
144 | get_html_file_content 'text' 'entry' $cut_do <"$i" | ||
145 | echo "]]></description><link>$global_url/${i#./}</link>" | ||
146 | echo "<guid>$global_url/$i</guid>" | ||
147 | echo "<dc:creator>$(get_post_author "$i")</dc:creator>" | ||
148 | echo "<pubDate>$(LC_ALL=C date -r "$i" +"$date_format_full")</pubDate></item>" | ||
149 | |||
150 | n=$(( n + 1 )) | ||
151 | done < <(ls -t ./*.html) | ||
152 | |||
153 | echo '</channel></rss>' | ||
154 | } 3>&1 >"$rssfile" | ||
155 | echo "" | ||
156 | |||
157 | mv "$rssfile" "$blog_feed" | ||
158 | chmod 644 "$blog_feed" | ||
159 | } | 154 | } |
160 | 155 | ||
161 | # }}} | 156 | # }}} |
157 | |||
162 | # }}} | 158 | # }}} |
163 | # prepare directory for outputs {{{ | 159 | # prepare directory for outputs {{{ |
164 | 160 | ||
165 | mkdir -p $output_dir/ | 161 | mkdir -p $OUTPUT_DIR/ |
166 | rm -rf $output_dir/** | 162 | rm -rf $OUTPUT_DIR/** |
167 | ln -s $assets_dir/* $output_dir/ | 163 | ln -s $ASSET_DIR/* $OUTPUT_DIR/ |
168 | 164 | ||
169 | # }}} | 165 | # }}} |
170 | # content of templates {{{ | 166 | # content of templates {{{ |
171 | 167 | ||
172 | head="$(cat $template_dir/head.html)" | 168 | declare -r HEAD="$(cat $TEMPLATE_DIR/head.html)" |
173 | header="$(cat $template_dir/header.html | indent 2)" | 169 | declare -r HEADER="$(<$TEMPLATE_DIR/header.html indent 2)" |
174 | footer="$(cat $template_dir/footer.html | indent 2)" | 170 | declare -r FOOTER="$(<$TEMPLATE_DIR/footer.html indent 2)" |
171 | declare -r INDEX_TEMPLATE="$(cat $TEMPLATE_DIR/index.md)" | ||
175 | index_list=() | 172 | index_list=() |
176 | index_template="$(cat $template_dir/index.md)" | ||
177 | 173 | ||
178 | # }}} | 174 | # }}} |
179 | # for each markdown file {{{ | 175 | # for each markdown file {{{ |
180 | 176 | ||
181 | files="$(find "$input_dir" -type f -name '*md')" | 177 | files="$(find "$INPUT_DIR" -type f -name '*md')" |
182 | total=$(wc -l <<<"$files") | 178 | total=$(wc -l <<<"$files") |
183 | declare -i counter | 179 | declare -i counter |
184 | for file in $files; do | 180 | for file in $files; do |
185 | # set variables | 181 | # set variables |
186 | path=$(<<<"$file" sed "s#^${input_dir}/##; s/\.md$//").html; mkdir -p $(dirname $output_dir/$path) | 182 | path=$(<<<"$file" sed "s#^${INPUT_DIR}/##; s/\.md$//").html; mkdir -p $(dirname $OUTPUT_DIR/$path) |
187 | content="$(<${file} ignore_comment)" | 183 | content="$(<${file} ignore_comment)" |
188 | 184 | ||
189 | # use frontmatter to decide making html file or not | 185 | # use frontmatter to decide making html file or not |
190 | <<<"$content" add_index || continue | 186 | <<<"$content" check_frontmatter || continue |
191 | 187 | ||
192 | # log | 188 | # log |
193 | echo -e "\033[1K\r$((counter+=1))/$total \t\t processing $path" | 189 | echo -e "\033[1K\r$((counter+=1))/$total \t\t processing $path" |
194 | 190 | ||
195 | # make html file for draft | 191 | # add original content to $OUTPUT_DIR |
196 | h1="$(<<<"$content" get_frontmatter | sed -n 's/^title *//p')" | ||
197 | comment="$(<<<"$content" get_frontmatter | sed -n 's/^comment *//p')" | ||
198 | |||
199 | # add original content to $output_dir | ||
200 | # and generate html file with <h1> | 192 | # and generate html file with <h1> |
201 | echo "$content" \ | 193 | echo "$content" \ |
202 | | tee $output_dir/${file#${input_dir}/} \ | 194 | | tee $OUTPUT_DIR/${file#${INPUT_DIR}/} \ |
203 | | { [ -n "$h1" ] && echo "# $h1"; cat; } \ | 195 | | { [ -n "$title" ] && echo "# $title"; cat; } \ |
204 | | html >$output_dir/$path | 196 | | html >$OUTPUT_DIR/$path |
197 | |||
198 | # Set modified time for index/RSS | ||
199 | mtime='@0' | ||
200 | [ ! "$public" = false ] && [ -n "$iso8601" ] && mtime="$iso8601" | ||
201 | touch -m -d "$mtime" $OUTPUT_DIR/$path | ||
205 | 202 | ||
206 | unset h1 comment | 203 | unset h1 comment |
207 | done | 204 | done |
@@ -210,19 +207,26 @@ echo | |||
210 | # }}} | 207 | # }}} |
211 | # make index.html {{{ | 208 | # make index.html {{{ |
212 | 209 | ||
210 | echo -en "Making\t\tindex.html" | ||
211 | export title="" | ||
213 | { | 212 | { |
214 | echo "${index_template}" | 213 | echo "${INDEX_TEMPLATE}" |
215 | echo -e '<br><br>\n\n' | 214 | echo -e '<br><br>\n\n' |
216 | latest_posts | 215 | latest_posts |
217 | } \ | 216 | } \ |
218 | | tee $output_dir/index.md \ | 217 | | tee $OUTPUT_DIR/index.md \ |
219 | | html >$output_dir/index.html | 218 | | html >$OUTPUT_DIR/index.html |
220 | 219 | ||
221 | echo -e index.html "\t" generated | 220 | touch -m -d @0 $OUTPUT_DIR/index.html |
221 | echo -e "\tgenerated" | ||
222 | 222 | ||
223 | # }}} | 223 | # }}} |
224 | # make index.xml {{{ | 224 | # make RSS file {{{ |
225 | |||
226 | 225 | ||
226 | echo -en "Making\t\tRSS" | ||
227 | make_rss >$OUTPUT_DIR/$RSSFILE | ||
228 | echo -e "\t\tgenerated" | ||
227 | 229 | ||
228 | # }}} | 230 | # }}} |
231 | |||
232 | # vim: fdm=marker fdl=0 | ||