This commit is contained in:
Charlie Root 2025-02-23 18:22:52 +00:00
parent 4a52dcece3
commit 6e5281c8fa
20 changed files with 877 additions and 2 deletions

4
LICENCE Normal file
View File

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

View File

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

16
makefile Normal file
View File

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

5
posts/chat.txt Normal file
View File

@ -0,0 +1,5 @@
2025/02/23
我的第一篇博客
当然是 2025 年的第一篇啦~

15
public/archive.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html><html lang="zh"><head><title>ITY&apos;s Site</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="ity.moe | blog | personal website"><meta name="author" content="ITY"><link rel="canonical"href="https://ity.moe"><style>: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)}</style></head><body><header class="header"><ul><li><a href="./index.html">Home</a></li><li><a href="./archive.html">Archive</a></li><li><a href="./feed.xml">RSS</a></li></ul></header><article class="content">
<h2>Writings</h2>
<p>
<div class="postlistdiv">
<ul>
<li>
<a href="posts/chat.html">2025-02-23 我的第一篇博客</a>
</li>
</ul>
</div>
</p>
</article><footer class="footer">
<p>ITY &copy; 2025 - now | <a href="https://git.nixos.world"/ity/shblog>shblog</a></p></footer></body></html>

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

23
public/feed.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet href="rss.xsl" type="text/xsl"?>
<rss version="2.0">
<channel>
<title>Title</title>
<link>https://ityspace.github.io</link>
<description>Your Description</description>
<copyright>CC 1.0</copyright>
<ttl>60</ttl>
<item>
<pubDate>2025/02/23 18:20:46 UTC</pubDate>
<category>2025/02/23</category>
<title>我的第一篇博客</title>
<link>https://ityspace.github.io/posts/chat.html</link>
<description>
<![CDATA[
<pre style='border: 0; white-space: pre-wrap; word-break: break-word;'>当然是 2025 年的第一篇啦~</pre>]]>
</description>
<author>unknown</author>
<guid>https://ityspace.github.io/posts/chat.html</guid>
</item>
</channel>
</rss>

2
public/imgsrv.svg Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="tiny" height="100" version="1.2" width="100" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><rect fill="none" height="100" width="100" x="0" y="0" /><path d="M 50.0,10.0 A 40,40 0 0,1 70.0,15.35898384862245 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /><path d="M 84.64101615137754,29.999999999999996 A 40,40 0 0,1 90.0,50.0 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /><path d="M 84.64101615137756,70.0 A 40,40 0 0,1 70.0,84.64101615137756 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /><path d="M 50.00000000000001,90.0 A 40,40 0 0,1 29.999999999999996,84.64101615137754 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /><path d="M 15.358983848622465,70.00000000000001 A 40,40 0 0,1 10.0,50.00000000000001 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /><path d="M 15.358983848622458,29.999999999999996 A 40,40 0 0,1 29.999999999999982,15.358983848622465 L 50,50 Z" fill="none" stroke="#ffffff" stroke-width="3" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

7
public/index.html Normal file
View File

@ -0,0 +1,7 @@
<!DOCTYPE html><html lang="zh"><head><title>ITY&apos;s Site</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="ity.moe | blog | personal website"><meta name="author" content="ITY"><link rel="canonical"href="https://ity.moe"><style>: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)}</style></head><body><header class="header"><ul><li><a href="./index.html">Home</a></li><li><a href="./archive.html">Archive</a></li><li><a href="./feed.xml">RSS</a></li></ul></header><article class="content">
<img class="avatar" src="./imgsrv.svg" alt="SVG">
<p>Stay kind, stay pure</p>
<p>I love nature and my dream is to explore the universe!</p>
</article><footer class="footer">
<p>ITY &copy; 2025 - now | <a href="https://git.nixos.world"/ity/shblog>shblog</a></p></footer></body></html>

164
public/posts/chat.html Normal file
View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>我的第一篇博客</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Your Description" >
<meta name="author" content="unknown">
<link rel="canonical" href="https://ityspace.github.io">
<style>
: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);
}
</style>
</head>
<body>
<header class="header"><ul><li><a href="/index.html">Home</a></li><li><a href="/archive.html">Archive</a></li><li><a href="/feed.xml">RSS</a></li></ul></header>
<article class="content">
<h1>我的第一篇博客</h1>
<h4>2025/02/23 </h4>
<p>
当然是 2025 年的第一篇啦~
</p>
</article><footer class="footer">
<p>ITY &copy; 2025 - now | <a href="https://git.nixos.world"/ity/shblog>shblog</a></p></footer></body></html>

1
public/rss.xsl Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title><xsl:value-of select="/rss/channel/title"/></title> <meta charset="UTF-8" /> <meta http-equiv="x-ua-compatible" content="IE=edge,chrome=1" /> <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no" /> <style> pre{ margin:0; white-space: pre-wrap; word-break: break-word; } .date{ margin-top: 1em; overflow: hidden; white-space: nowrap; width: 16ch; } </style> </head> <body> <pre><xsl:value-of select="/rss/channel/title"/></pre> <pre><xsl:value-of select="/rss/channel/description"/></pre> <xsl:for-each select="/rss/channel/item"> <xsl:sort select="category" order="descending"/> <pre class="date"><xsl:value-of select="pubDate" /></pre> <pre><xsl:value-of select="title"/></pre> <xsl:element name="a"> <xsl:attribute name="href"> <xsl:value-of select="link"/> </xsl:attribute> <pre><xsl:value-of select="link"/></pre> </xsl:element> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>

2
src/pages/footer Normal file
View File

@ -0,0 +1,2 @@
</article><footer class="footer">
<p>ITY &copy; 2025 - now | <a href="https://git.nixos.world"/ity/shblog>shblog</a></p></footer></body></html>

1
src/pages/header Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang="zh"><head><title>ITY&apos;s Site</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="ity.moe | blog | personal website"><meta name="author" content="ITY"><link rel="canonical"href="https://ity.moe"><style>: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)}</style></head><body><header class="header"><ul><li><a href="./index.html">Home</a></li><li><a href="./archive.html">Archive</a></li><li><a href="./feed.xml">RSS</a></li></ul></header><article class="content">

4
src/pages/home Normal file
View File

@ -0,0 +1,4 @@
<img class="avatar" src="./imgsrv.svg" alt="SVG">
<p>Stay kind, stay pure</p>
<p>I love nature and my dream is to explore the universe!</p>

137
src/pages/post_styles Normal file
View File

@ -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);
}

5
src/script/home.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
cat ./src/pages/header
cat ./src/pages/home
cat ./src/pages/footer

24
src/script/list.sh Normal file
View File

@ -0,0 +1,24 @@
#!/bin/sh
POST_DIR="posts/"
cat ./src/pages/header
echo "<h2>Writings</h2>"
for file in $POST_DIR*; do
echo "
<p>
<div class=\"postlistdiv\">
<ul>
<li>
<a href=\"$(echo "$file" | sed 's/.txt/.html/')\">$(date -f "$(head -n 1 $file)" +"%Y-%m-%d") $(head -n 2 $file | tail -n 1)</a>
</li>
</ul>
</div>
</p>
";
done
cat ./src/pages/footer;

342
src/script/markdown.sh Normal file
View File

@ -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)\]|<img src=\"$ref_url\" title=\"$ref_title\" alt=\"\1\" />|gI" "$temp_file"
# reference-style link using the label
sed -ri "s|\[([^]]+)\]\[($ref_id)\]|<a href=\"$ref_url\" title=\"$ref_title\">\1</a>|gI" "$temp_file"
# implicit reference-style
sed -ri "s|!\[($ref_id)\]\[\]|<img src=\"$ref_url\" title=\"$ref_title\" alt=\"\1\" />|gI" "$temp_file"
# implicit reference-style
sed -ri "s|\[($ref_id)\]\[\]|<a href=\"$ref_url\" title=\"$ref_title\">\1</a>|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<blockquote>\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<h1>\1<\/h1>/
p
b
}
/\-+$/{
s/\n(.*)\n\-+$/\n<h2>\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 ]*)(.*)/<h1 id="\1">\1\2<\/h1>/g # H1
/^#{2} /s/#{2} ([A-Za-z0-9 ]*)(.*)/<h2 id="\1">\1\2<\/h2>/g # H2
/^#{3} /s/#{3} ([A-Za-z0-9 ]*)(.*)/<h3 id="\1">\1\2<\/h3>/g # H3
/^#{4} /s/#{4} ([A-Za-z0-9 ]*)(.*)/<h4 id="\1">\1\2<\/h4>/g # H4
/^#{5} /s/#{5} ([A-Za-z0-9 ]*)(.*)/<h5 id="\1">\1\2<\/h5>/g # H5
/^#{6} /s/#{6} ([A-Za-z0-9 ]*)(.*)/<h6 id="\1">\1\2<\/h6>/g # H6
/^\*\*\*+$/s/\*\*\*+/<hr \/>/ # hr with *
/^---+$/s/---+/<hr \/>/ # hr with -
/^___+$/s/___+/<hr \/>/ # 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<uli>\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
/<uli>/{
s/(.*)/\n<ul>\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<oli>\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
/<oli>/{
s/(.*)/\n<ol>\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})(.*)/<pre><code>\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
/^<pre><code>/{
:inside
n
# if you found the end tags, branch out
/^<\/code><\/pre>/!{
s/&/\&amp;/g # ampersand
s/</\&lt;/g # less than
s/>/\&gt;/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<br \/>\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/\*\*(.+)\*\*/<strong>\1<\/strong>/g
s/__([^_]+)__/<strong>\1<\/strong>/g
s/\*([^\*]+)\*/<em>\1<\/em>/g
s/([^\\])_([^_]+)_/\1<em>\2<\/em>/g
s/\~\~(.+)\~\~/<strike>\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<p>\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]?:\/\/.*)>/<a href=\"\1\">\1<\/a>/g # automatic links
s/<(.*@.*\..*)>/<a href=\"mailto:\1\">\1<\/a>/g # automatic email address links
# inline code
s/([^\\])``+ *([^ ]*) *``+/\1<code>\2<\/code>/g
s/([^\\])`([^`]*)`/\1<code>\2<\/code>/g
s/!\[(.*)\]\((.*) \"(.*)\"\)/<img alt=\"\1\" src=\"\2\" title=\"\3\" \/>/g # inline image with title
s/!\[(.*)\]\((.*)\)/<img alt=\"\1\" src=\"\2\" \/>/g # inline image without title
s/\[(.*)]\((.*) "(.*)"\)/<a href=\"\2\" title=\"\3\">\1<\/a>/g # inline link with title
s/\[(.*)]\((.*)\)/<a href=\"\2\">\1<\/a>/g # inline link
# special characters
/&.+;/!s/&/\&amp;/g # ampersand
/<[\/a-zA-Z]/!s/</\&lt;/g# less than bracket
# backslash escapes for literal characters
s/\\\*/\*/g # asterisk
s/\\_/_/g # underscore
s/\\`/`/g # underscore
s/\\#/#/g # pound or hash
s/\\\+/\+/g # plus
s/\\\-/\-/g # minus
s/\\\\/\\/g # backslash
' "$temp_file"
# display and cleanup
cat "$temp_file" && rm "$temp_file"

52
src/script/page.sh Normal file
View File

@ -0,0 +1,52 @@
#!/bin/sh
POST_DIR="tmp/posts/"
cp -r posts tmp/
for file in $POST_DIR*; do
DOMAIN="https://ityspace.github.io"
COPYRIGHT="CC0 1.0 Universal"
AUTHOR="unknown"
DESCRIPTION="Your Description"
TITLE=$(head -n 2 $file | tail -n 1)
DATE=$(head -n 1 $file )
sed -i '1, 2d' $file
test -d public/posts && rm -rf public/posts/* || mkdir public/posts;
sh src/script/markdown.sh $file > $(echo "./tmp$file" | sed 's/tmp\/posts//');
echo "
<!DOCTYPE html>
<html lang=\"zh\">
<head>
<title>$TITLE</title>
<meta charset=\"UTF-8\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
<meta name=\"description\" content=\"$DESCRIPTION\" >
<meta name=\"author\" content=\"$AUTHOR\">
<link rel=\"canonical\" href=\"$DOMAIN\">
<style>
" > $(echo "./public/posts$file" | sed 's/.txt/.html/' | sed 's/tmp\/posts//');
cat ./src/pages/post_styles >> $(echo "./public/posts$file" | sed 's/.txt/.html/' | sed 's/tmp\/posts//');
echo "
</style>
</head>
<body>
<header class=\"header\"><ul><li><a href=\"/index.html\">Home</a></li><li><a href=\"/archive.html\">Archive</a></li><li><a href=\"/feed.xml\">RSS</a></li></ul></header>
<article class=\"content\">
<h1>$TITLE</h1>
<h4>$DATE</h4>
" >> $(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

39
src/script/xml.sh Normal file
View File

@ -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 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
<?xml-stylesheet href=\"rss.xsl\" type=\"text/xsl\"?>
<rss version=\"2.0\">
<channel>
<title>$TITLE</title>
<link>$DOMAIN</link>
<description>$DESCRIPTION</description>
<copyright>$COPYRIGHT</copyright>
<ttl>$TTL</ttl>";
for file in $POST_DIR*; do
echo "<item>
<pubDate>$(head -n 1 $file) $TIME</pubDate>
<category>$(date -f "$(head -n 1 $file)" +"%Y/%m/%d")</category>
<title>$(head -n 2 $file | tail -n 1)</title>
<link>"$(echo "$DOMAIN/$file" | sed 's/.txt/.html/')"</link>
<description>
<![CDATA[
<pre style='border: 0; white-space: pre-wrap; word-break: break-word;'>$(tail -n +4 $file | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/g')</pre>]]>
</description>
<author>$AUTHOR</author>
<guid>$(echo "$DOMAIN/$file" | sed 's/.txt/.html/')</guid>
</item>";
done
echo " </channel>
</rss>";