diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..a47a616 --- /dev/null +++ b/LICENCE @@ -0,0 +1,4 @@ +No Copyright +The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. + +You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. diff --git a/README.md b/README.md index 3824939..d761a0c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,35 @@ -# shblog +Generate blog by ShellScript +============================= + +Run +--- + +``` +make serve +``` + +Open url http://localhost:8999 to view. + +Build +--- + +``` +make +``` + +Write post +--- + +``` +make post +``` + +Notes: +====== + +[01] You should write code by yourself. + +[02] Article suffix is txt. The first row is the time, the second row is the title. + +[03] Use the GNU version of `sed`. -Make blog website by shellscripts \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..284c8e4 --- /dev/null +++ b/makefile @@ -0,0 +1,16 @@ +.DEFAULT: build + +.PHONY: build +build: + @echo "Building ..." + @mkdir tmp + @echo "Loading" + @sh src/script/xml.sh > public/feed.xml + @sh src/script/home.sh > public/index.html + @sh src/script/list.sh > public/archive.html + @sh src/script/page.sh + @rm -rf tmp + @echo "Static files are saved at public/" + @echo "\033[36mSuccess!\033[0m" +push: build + @rm -rf /var/www/htdocs/ity.moe && cp -r public /var/www/htdocs/ity.moe diff --git a/posts/chat.txt b/posts/chat.txt new file mode 100644 index 0000000..55becd6 --- /dev/null +++ b/posts/chat.txt @@ -0,0 +1,5 @@ +2025/02/23 +我的第一篇博客 + +当然是 2025 年的第一篇啦~ + diff --git a/public/archive.html b/public/archive.html new file mode 100644 index 0000000..a6dd2b2 --- /dev/null +++ b/public/archive.html @@ -0,0 +1,15 @@ +ITY's Site
+

Writings

+ +

+

+ +
+

+ +
diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..61fe2f0 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/feed.xml b/public/feed.xml new file mode 100644 index 0000000..dc81709 --- /dev/null +++ b/public/feed.xml @@ -0,0 +1,23 @@ + + + + + Title + https://ityspace.github.io + Your Description + CC 1.0 + 60 + + 2025/02/23 18:20:46 UTC + 2025/02/23 + 我的第一篇博客 + https://ityspace.github.io/posts/chat.html + + 当然是 2025 年的第一篇啦~]]> + + unknown + https://ityspace.github.io/posts/chat.html + + + diff --git a/public/imgsrv.svg b/public/imgsrv.svg new file mode 100644 index 0000000..74ae19a --- /dev/null +++ b/public/imgsrv.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..220a4a0 --- /dev/null +++ b/public/index.html @@ -0,0 +1,7 @@ +ITY's Site
+SVG +

Stay kind, stay pure

+

I love nature and my dream is to explore the universe!

+ +
diff --git a/public/posts/chat.html b/public/posts/chat.html new file mode 100644 index 0000000..2270d7b --- /dev/null +++ b/public/posts/chat.html @@ -0,0 +1,164 @@ + + + + + 我的第一篇博客 + + + + + + + + +
+
+

我的第一篇博客

+

2025/02/23

+ + +

+当然是 2025 年的第一篇啦~ +

+
diff --git a/public/rss.xsl b/public/rss.xsl new file mode 100644 index 0000000..443afff --- /dev/null +++ b/public/rss.xsl @@ -0,0 +1 @@ + <xsl:value-of select="/rss/channel/title"/>
diff --git a/src/pages/footer b/src/pages/footer new file mode 100644 index 0000000..3d7dbdb --- /dev/null +++ b/src/pages/footer @@ -0,0 +1,2 @@ + diff --git a/src/pages/header b/src/pages/header new file mode 100644 index 0000000..598286c --- /dev/null +++ b/src/pages/header @@ -0,0 +1 @@ +ITY's Site
diff --git a/src/pages/home b/src/pages/home new file mode 100644 index 0000000..e37d407 --- /dev/null +++ b/src/pages/home @@ -0,0 +1,4 @@ +SVG +

Stay kind, stay pure

+

I love nature and my dream is to explore the universe!

+ diff --git a/src/pages/post_styles b/src/pages/post_styles new file mode 100644 index 0000000..62c0b32 --- /dev/null +++ b/src/pages/post_styles @@ -0,0 +1,137 @@ +:root { +--color: #333333; +--border: #8b8b8b; +--bg: #fff; +--block-bg: #f5f5f5; +--brightness: 1; +--invert: 70%; +--description: #595959; +} +@media (prefers-color-scheme:dark) { +:root { +color-scheme: dark; +--color: #c7c7c7; +--border: #a1a1a1; +--bg: #1b1b1b; +--block-bg: #2b2b2b; +--brightness: .8; +--invert: 0%; +--description: #bbbbbb; +} +} +body { +font-family: sans-serif; +color: var(--color); +background: var(--bg); +line-height: 1.4; +margin: 1rem auto; +max-width: 72ch; +width: 85%; +} +.avatar { width: 4rem;filter: invert(var(--invert)); } +h1 { +margin-block-start: 0.67rem; +margin-block-end: 0.67rem; +font-size: 2.00rem; +font-weight: bold; +} + +article h1:first-of-type { +margin-block-start: 1.67rem; +} + +h2 { +margin-block-start: 0.83rem; +margin-block-end: 0.83rem; +font-size: 1.50rem; +font-weight: bold; +} + +h3 { +margin-block-start: 1rem; +margin-block-end: 1rem; +font-size: 1.17em; +font-weight: bold; +} + +h4 { +margin-block-start: 1.33rem; +margin-block-end: 1.33rem; +font-size: 1.00rem; +font-weight: bold; +} + +article h1+h4:first-of-type { +margin-block-start: 0rem; +} + +h5 { +margin-block-start: 1.67rem; +margin-block-end: 1.67rem; +font-size: 0.83rem; +font-weight: bold; +} + +h6 { +margin-block-start: 2.33rem; +margin-block-end: 2.33rem; +font-size: 0.67rem; +font-weight: bold; +} + +a { +text-decoration: none; +color: inherit; +} +a:hover { +background: var(--block-bg); +} + +img { +width: 100%; +height: auto; +filter: brightness(var(--brightness)); +} + +blockquote { +border-left: 3px solid var(--block-bg); +padding: 0 1rem; +margin-left: 0; +margin-right: 0; +} + +hr { +border: none; +height: 1px; +background: var(--small-text-color); +} + +pre, code, kbd, samp { font-family: monospace, monospace; } +code { overflow-wrap: break-word; background: var(--transparent); border-radius: 5px; } +pre { font-size: 95%; white-space: pre; white-space: pre-wrap; word-wrap: break-word; } +pre>code { white-space: pre-wrap; } + +small { +font-size: .95rem; +color: var(--description); +} + +.header ul { +list-style-type: none; +padding-left: 0; +} + +.header li { +display: inline; +font-size: 1.2rem; +margin-right: 1.2rem; +} + +.postlistdiv ul { +list-style-type: none; +padding-left: 0; +} + +.footer { +color: var(--small-text-color); +} diff --git a/src/script/home.sh b/src/script/home.sh new file mode 100644 index 0000000..c5efcdb --- /dev/null +++ b/src/script/home.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cat ./src/pages/header +cat ./src/pages/home +cat ./src/pages/footer diff --git a/src/script/list.sh b/src/script/list.sh new file mode 100644 index 0000000..4f68b8f --- /dev/null +++ b/src/script/list.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +POST_DIR="posts/" + +cat ./src/pages/header + +echo "

Writings

" + +for file in $POST_DIR*; do + +echo " +

+

+ +
+

+"; +done + +cat ./src/pages/footer; diff --git a/src/script/markdown.sh b/src/script/markdown.sh new file mode 100644 index 0000000..ce515f0 --- /dev/null +++ b/src/script/markdown.sh @@ -0,0 +1,342 @@ +#!/bin/bash + + + alias sed=gsed + +# move the original text to a temp file that can be progressively modified +temp_file="./tmp/markdown.$$" +cat "$@" > "$temp_file" + +# All of this below business is for reference-style links and images +# We need to loop across newlines and not spaces +IFS=' +' +refs=$(sed -nr "/^\[.+\]: +/p" "$@") +for ref in $refs +do + ref_id=$(echo -n "$ref" | sed -nr "s/^\[(.+)\]: .*/\1/p" | tr -d '\n') + ref_url=$(echo -n "$ref" | sed -nr "s/^\[.+\]: (.+)/\1/p" | cut -d' ' -f1 | tr -d '\n') + ref_title=$(echo -n "$ref" | sed -nr "s/^\[.+\]: (.+) \"(.+)\"/\2/p" | sed 's@|@!@g' | tr -d '\n') + + # reference-style image using the label + sed -ri "s|!\[([^]]+)\]\[($ref_id)\]|\"\1\"|gI" "$temp_file" + # reference-style link using the label + sed -ri "s|\[([^]]+)\]\[($ref_id)\]|\1|gI" "$temp_file" + + # implicit reference-style + sed -ri "s|!\[($ref_id)\]\[\]|\"\1\"|gI" "$temp_file" + # implicit reference-style + sed -ri "s|\[($ref_id)\]\[\]|\1|gI" "$temp_file" +done + +# delete the reference lines +sed -ri "/^\[.+\]: +/d" "$temp_file" + +# blockquotes +# use grep to find all the nested blockquotes +while grep '^> ' "$temp_file" >/dev/null +do + sed -nri ' +/^$/b blockquote + +H +$ b blockquote +b + +:blockquote +x +s/(\n+)(> .*)/\1
\n\2\n<\/blockquote>/ # wrap the tags in a blockquote +p +' "$temp_file" + + sed -i '1 d' "$temp_file" # cleanup superfluous first line + + # cleanup blank lines and remove subsequent blockquote characters + sed -ri ' +/^> /s/^> (.*)/\1/ +' "$temp_file" +done + +# Setext-style headers +sed -nri ' +# Setext-style headers need to be wrapped around newlines +/^$/ b print + +# else, append to holding area +H +$ b print +b + +:print +x +/=+$/{ +s/\n(.*)\n=+$/\n

\1<\/h1>/ +p +b +} +/\-+$/{ +s/\n(.*)\n\-+$/\n

\1<\/h2>/ +p +b +} +p +' "$temp_file" + +sed -i '1 d' "$temp_file" # cleanup superfluous first line + +# atx-style headers and other block styles +sed -ri ' +/^#+ /s/ #+$// # kill all ending header characters +/^# /s/# ([A-Za-z0-9 ]*)(.*)/

\1\2<\/h1>/g # H1 +/^#{2} /s/#{2} ([A-Za-z0-9 ]*)(.*)/

\1\2<\/h2>/g # H2 +/^#{3} /s/#{3} ([A-Za-z0-9 ]*)(.*)/

\1\2<\/h3>/g # H3 +/^#{4} /s/#{4} ([A-Za-z0-9 ]*)(.*)/

\1\2<\/h4>/g # H4 +/^#{5} /s/#{5} ([A-Za-z0-9 ]*)(.*)/

\1\2<\/h5>/g # H5 +/^#{6} /s/#{6} ([A-Za-z0-9 ]*)(.*)/
\1\2<\/h6>/g # H6 + +/^\*\*\*+$/s/\*\*\*+/
/ # hr with * +/^---+$/s/---+/
/ # hr with - +/^___+$/s/___+/
/ # hr with _ + +' "$temp_file" + +# unordered lists +# use grep to find all the nested lists +while grep '^[\*\+\-] ' "$temp_file" >/dev/null +do +sed -nri ' +# wrap the list +/^$/b list + +# wrap the li tags then add to the hold buffer +# use uli instead of li to avoid collisions when processing nested lists +/^[\*\+\-] /s/[\*\+\-] (.*)/<\/uli>\n\n\1/ + +H +$ b list # if at end of file, check for the end of a list +b # else, branch to the end of the script + +# this is where a list is checked for the pattern +:list +# exchange the hold space into the pattern space +x +# look for the list items, if there wrap the ul tags +//{ +s/(.*)/\n
    \1\n<\/uli>\n<\/ul>/ # close the ul tags +s/\n<\/uli>// # kill the first superfluous closing tag +p +b +} +p +' "$temp_file" + +sed -i '1 d' "$temp_file" # cleanup superfluous first line + +# convert to the proper li to avoid collisions with nested lists +sed -i 's/uli>/li>/g' "$temp_file" + +# prepare any nested lists +sed -ri '/^[\*\+\-] /s/(.*)/\n\1\n/' "$temp_file" +done + +# ordered lists +# use grep to find all the nested lists +while grep -E '^[1-9]+\. ' "$temp_file" >/dev/null +do +sed -nri ' +# wrap the list +/^$/b list + +# wrap the li tags then add to the hold buffer +# use oli instead of li to avoid collisions when processing nested lists +/^[1-9]+\. /s/[1-9]+\. (.*)/<\/oli>\n\n\1/ + +H +$ b list # if at end of file, check for the end of a list +b # else, branch to the end of the script + +:list +# exchange the hold space into the pattern space +x +# look for the list items, if there wrap the ol tags +//{ +s/(.*)/\n
      \1\n<\/oli>\n<\/ol>/ # close the ol tags +s/\n<\/oli>// # kill the first superfluous closing tag +p +b +} +p +' "$temp_file" + +sed -i '1 d' "$temp_file" # cleanup superfluous first line + +# convert list items into proper list items to avoid collisions with nested lists +sed -i 's/oli>/li>/g' "$temp_file" + +# prepare any nested lists +sed -ri '/^[1-9]+\. /s/(.*)/\n\1\n/' "$temp_file" +done + +# make escaped periods literal +sed -ri '/^[1-9]+\\. /s/([1-9]+)\\. /\1\. /' "$temp_file" + + +# code blocks +sed -nri ' +# if at end of file, append the current line to the hold buffer and print it +${ +H +b code +} + +# wrap the code block on any non code block lines +/^\t| {4}/!b code + +# else, append to the holding buffer and do nothing +H +b # else, branch to the end of the script + +:code +# exchange the hold space with the pattern space +x +# look for the code items, if there wrap the pre-code tags +/\t| {4}/{ +s/(\t| {4})(.*)/
      \n\1\2\n<\/code><\/pre>/ # wrap the ending tags
      +p
      +b
      +}
      +p
      +' "$temp_file"
      +
      +sed -i '1 d' "$temp_file" # cleanup superfluous first line
      +
      +# convert html characters inside pre-code tags into printable representations
      +sed -ri '
      +# get inside pre-code tags
      +/^
      /{
      +:inside
      +n
      +# if you found the end tags, branch out
      +/^<\/code><\/pre>/!{
      +s/&/\&/g # ampersand
      +s//\>/g # greater than
      +b inside
      +}
      +}
      +' "$temp_file"
      +
      +# remove the first tab (or 4 spaces) from the code lines
      +sed -ri 's/^\t| {4}(.*)/\1/' "$temp_file"
      +
      +# br tags
      +sed -ri '
      +# if an empty line, append it to the next line, then check on whether there is two in a row
      +/^$/ {
      +N
      +N
      +/^\n{2}/s/(.*)/\n
      \1/ +} +' "$temp_file" + +# emphasis and strong emphasis and strikethrough +sed -nri ' +# batch up the entire stream of text until a line break in the action +/^$/b emphasis + +H +$ b emphasis +b + +:emphasis +x +s/\*\*(.+)\*\*/\1<\/strong>/g +s/__([^_]+)__/\1<\/strong>/g +s/\*([^\*]+)\*/\1<\/em>/g +s/([^\\])_([^_]+)_/\1\2<\/em>/g +s/\~\~(.+)\~\~/\1<\/strike>/g +p +' "$temp_file" + +sed -i '1 d' "$temp_file" # cleanup superfluous first line + +# paragraphs +sed -nri ' +# if an empty line, check the paragraph +/^$/ b para +# else append it to the hold buffer +H +# at end of file, check paragraph +$ b para +# now branch to end of script +b +# this is where a paragraph is checked for the pattern +:para +# return the entire paragraph into the pattern space +x +# look for non block-level elements, if there - print the p tags +/\n<(div|table|pre|p|[ou]l|h[1-6]|[bh]r|blockquote|li)/!{ +s/(\n+)(.*)/\1

      \n\2\n<\/p>/ +p +b +} +p +' "$temp_file" + +sed -i '1 d' "$temp_file" # cleanup superfluous first line + +# cleanup area where P tags have broken nesting +sed -nri ' +# if the line looks like like an end tag +/^<\/(div|table|pre|p|[ou]l|h[1-6]|[bh]r|blockquote)>/{ +h +# if EOF, print the line +$ { +x +b done +} +# fetch the next line and check on whether or not it is a P tag +n +/^<\/p>/{ +G +b done +} +# else, append the line to the previous line and print them both +H +x +} +:done +p +' "$temp_file" + +# inline styles and special characters +sed -ri ' +s/<(http[s]?:\/\/.*)>/\1<\/a>/g # automatic links +s/<(.*@.*\..*)>/\1<\/a>/g # automatic email address links + +# inline code +s/([^\\])``+ *([^ ]*) *``+/\1\2<\/code>/g +s/([^\\])`([^`]*)`/\1\2<\/code>/g + +s/!\[(.*)\]\((.*) \"(.*)\"\)/\"\1\"/g # inline image with title +s/!\[(.*)\]\((.*)\)/\"\1\"/g # inline image without title + +s/\[(.*)]\((.*) "(.*)"\)/\1<\/a>/g # inline link with title +s/\[(.*)]\((.*)\)/\1<\/a>/g # inline link + +# special characters +/&.+;/!s/&/\&/g # ampersand +/<[\/a-zA-Z]/!s/ $(echo "./tmp$file" | sed 's/tmp\/posts//'); + +echo " + + + + $TITLE + + + + + + + + +

      +
      +

      $TITLE

      +

      $DATE

      +" >> $(echo "./public/posts$file" | sed 's/.txt/.html/' | sed 's/tmp\/posts//'); + +cat $(echo "./tmp$file"| sed 's/tmp\/posts//') >> $(echo "./public/posts$file" | sed 's/.txt/.html/' | sed 's/tmp\/posts//'); + + +cat ./src/pages/footer >> $(echo "./public/posts$file" | sed 's/.txt/.html/' | sed 's/tmp\/posts//'); + +done diff --git a/src/script/xml.sh b/src/script/xml.sh new file mode 100644 index 0000000..b94ee1e --- /dev/null +++ b/src/script/xml.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +#Configuration + DOMAIN="https://ityspace.github.io" + TITLE="Title" DESCRIPTION="Your Description" + COPYRIGHT="CC 1.0" + POST_DIR="posts/" + TTL="60" + AUTHOR="unknown" + TIME=$(date +"%T %Z") + +echo " + + + + $TITLE + $DOMAIN + $DESCRIPTION + $COPYRIGHT + $TTL"; + +for file in $POST_DIR*; do + +echo " + $(head -n 1 $file) $TIME + $(date -f "$(head -n 1 $file)" +"%Y/%m/%d") + $(head -n 2 $file | tail -n 1) + "$(echo "$DOMAIN/$file" | sed 's/.txt/.html/')" + + $(tail -n +4 $file | sed 's/&/\&/g; s//\>/g; s/"/\"/g; s/'"'"'/\'/g')
      ]]> + + $AUTHOR + $(echo "$DOMAIN/$file" | sed 's/.txt/.html/') + "; +done + +echo " +";