共计 7252 个字符,预计需要花费 19 分钟才能阅读完成。
Gar 是一个 Bash 脚本程序,用于治理 Markdown 文档我的项目,可将 Markdown 文档汇合其转化为 HTML 文档汇合。Gar 的运行,依赖 pandoc,git,tree 以及一个能在 Shell(命令行)里关上指定网页文件的网页浏览器。Gar 默认将 Firefox 作为网页浏览器,然而可在文档我的项目根目录的 gar.conf 文件中指定其它符合要求的网页浏览器。
文档我的项目初始化
命令:gar init 文档我的项目名
例如:
$ gar init demo
[master (root-commit) 6f7dd1c] init
1 file changed, 2 insertions(+)
create mode 100644 gar.conf
以下命令可察看 gar init
发明了什么:
$ cd demo
$ ls -a
.. gar.conf .git output source 图片
$ gar tree
demo
├── gar.conf
├── output
├── source
└── 图片
$ git log
commit 6f7dd1c23c0cc8b18eb84b6a5236605eebd2bfbf (HEAD -> master)
Author: xxx <xxx@yyy.zzz>
Date: Tue Mar 9 07:30:53 2021 +0800
init
文档我的项目初始化后,文档的撰写和编辑工作次要在 source
目录进行。Gar 将 Markdown 文档转化为 HTML 文档后,放在 output
子目录内。
文集创立与删除
进入 source
目录:
$ cd source
创立文集 foo:
$ gar new-class foo
可应用 gar tree
查看文档我的项目的目录变动,察看 gar new-class
发明了什么:
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
└── 图片
└── foo
可一次创立多个文集:
$ gar new-class a b c
后果为:
$ gar tree
demo
├── gar.conf
├── output
│ ├── a
│ ├── b
│ ├── c
│ └── foo
├── source
│ ├── a
│ ├── b
│ ├── c
│ └── foo
└── 图片
├── a
├── b
├── c
└── foo
删除文集:
$ gar remove-class a b c
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
└── 图片
└── foo
可在文集里创立子文集:
$ cd foo
$ gar new-class a
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
│ └── a
├── source
│ └── foo
│ └── a
└── 图片
└── foo
└── a
可创立文集档次序列:
$ gar new-class b/c/d/e/f
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
│ ├── a
│ └── b
│ └── c
│ └── d
│ └── e
│ └── f
├── source
│ └── foo
│ ├── a
│ └── b
│ └── c
│ └── d
│ └── e
│ └── f
└── 图片
└── foo
├── a
└── b
└── c
└── d
└── e
└── f
将试验复盘:
$ gar remove-class a b
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
└── 图片
└── foo
提醒,目前工作目录仍为 source/foo。
创立和删除文档
在文集目录内,应用 gar new-post
创立内容为空的文档。例如,在 source/foo 内创立 test.md 文档:
$ gar new-post test.md
[master 6a894eb] Added test.md
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 source/foo/test.md
查看产生了什么:
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
│ └── test.md
└── 图片
└── foo
└── test
$ git log
commit 6a894eb44cf66e95b4ff938e05c019b7218039e0 (HEAD -> master)
Author: xxx <xxx@yyy.zzz>
Date: Tue Mar 9 08:16:49 2021 +0800
Added test.md
commit 6f7dd1c23c0cc8b18eb84b6a5236605eebd2bfbf
Author: xxx <xxx@yyy.zzz>
Date: Tue Mar 9 07:30:53 2021 +0800
init
每次创立文档时,Gar 会调用 git 记录文档创立历史。
可一次创立多份空文档:
$ gar new-post a.md b.md c.md
[master 25e7d65] Added a.md b.md c.md
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 source/foo/a.md
create mode 100644 source/foo/b.md
create mode 100644 source/foo/c.md
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
│ ├── a.md
│ ├── b.md
│ ├── c.md
│ └── test.md
└── 图片
└── foo
├── a
├── b
├── c
└── test
应用 gar remove-post
可删除当前工作目录下的文档。以下命令可将上述创立的文档一举删除:
$ gar remove-post test.md a.md b.md c.md
[master 189da8b] Remove test.md a.md b.md c.md
4 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 source/foo/a.md
delete mode 100644 source/foo/b.md
delete mode 100644 source/foo/c.md
delete mode 100644 source/foo/test.md
每次删除文档,git 会记录文档的删除历史。
通过上述操作后,这个试验性的文档我的项目又复盘为:
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
├── source
│ └── foo
└── 图片
└── foo
网页的生成和预览
记住,以后的工作目录仍然是 source/foo
。上面的命令从新创立 test.md:
$ gar new-post test.md
而后用文本编辑器关上 test.md,减少以下内容:
<!--
.. title: Hello Gar!
-->
这只是一份无用的示例文档。
应用 gar convert
命令可将文档 test.md 转换为网页文件 test.html,并将其置于 文档我的项目根目录 /output/foo
目录内:
$ gar convert test.md
查看文档目录产生的变动:
$ gar tree
demo
├── gar.conf
├── output
│ └── foo
│ └── test.html
├── source
│ └── foo
│ └── test.md
└── 图片
└── foo
└── test
假使工作目录(以后文集)内有多份文档,也能够一次性将其转换为一组网页文件,例如:
$ gar convert test.md a.md b.md c.md
应用 gar preview
命令,可将文档转化为网页文件,并由 Gar 默认的网页浏览器关上:
$ gar preview test.md
gar preview
不反对多份文档一次性转换和预览。
附录
Gar 的全副代码:
#!/bin/bash
SCRIPT_PATH=$(cd "$(dirname"${BASH_SOURCE[0]}")" && pwd)
GAR_CONF=gar.conf
SOURCE=source
IMAGES= 图片
OUTPUT=output
function error_msg {
echo $1
exit -1
}
function goto_root {if [ ! -e $GAR_CONF]
then
if [$(pwd) = / ]
then
echo "gar.conf Not found!"
else
cd ..
goto_root
fi
fi
}
function class_name {
TARGET_PATH=$1
goto_root
SOURCE_PATH=$(pwd)/$SOURCE/
echo ${TARGET_PATH//$SOURCE_PATH/}
}
function get_title {NAME=${1%.md}
# 将文件名里用于距离中文和英文的短线替换为空格
L_SPACE_PAT='s/\([^a-zA-Z]\)-/\1 /g'
R_SPACE_PAT='s/-\([^a-zA-Z]\)/ \1/g'
FANCY_NAME="$(echo $NAME | sed -e"$L_SPACE_PAT; $R_SPACE_PAT")"
# 文章题目
PREFIX="^[[:space:]]*\.\.[[:space:]]*title:[[:space:]]*"
TITLE=$(grep -o "${PREFIX}.*$" $1 | sed -e "s/${PREFIX}\(.*\)$/\1/g")
if [-z "$TITLE"]
then
TITLE=$FANCY_NAME
fi
echo $TITLE
}
function markdown_to_html {HTML=$OUTPUT/$1/${2%.*}.html
pandoc $SOURCE/$1/$2 -s --mathjax \
-c $SCRIPT_PATH/gar.css \
--highlight-style pygments \
--metadata title="$TITLE" -o $HTML
}
case $1 in
init)
case $2 in
"")
error_msg "You should tell me the name of the project!"
;;
*)
mkdir $2
cd $2
echo '#!/bin/bash' > $GAR_CONF
echo "BROWSER_FOR_GAR=firefox" >> $GAR_CONF
mkdir $SOURCE $OUTPUT $IMAGES
git init -q
git add .
git commit -a -m "init"
;;
esac
;;
new-class)
case $2 in
"")
error_msg "You should tell me the name of the posts class!"
;;
*)
for i in ${@:2}
do
MARK=$(pwd)
mkdir -p $i
cd $i
CLASS_NAME=$(class_name $MARK/$i)
goto_root
mkdir -p $IMAGES/$CLASS_NAME
mkdir -p $OUTPUT/$CLASS_NAME
cd $MARK
done
;;
esac
;;
remove-class)
case $2 in
"")
error_msg "You should tell me the name of the posts class!"
;;
*)
for i in ${@:2}
do
MARK=$(pwd)
rm -rf $i
CLASS_NAME=$(class_name $MARK/$i)
goto_root
rm -rf $IMAGES/$CLASS_NAME
rm -rf $OUTPUT/$CLASS_NAME
cd $MARK
done
;;
esac
;;
new-post)
case $2 in
"")
error_msg "You should tell me the name of the post!"
;;
*)
MARK=$(pwd)
CLASS_NAME=$(class_name $MARK)
for i in ${@:2}
do
touch $i
goto_root
mkdir -p $IMAGES/$CLASS_NAME/${i%.*}
cd $MARK
done
goto_root
git add .
DOCUMENTS="${@:2}"
git commit -a -m "Added $DOCUMENTS"
;;
esac
;;
remove-post)
case $2 in
"")
error_msg "You should tell me the name of the post!"
;;
*)
MARK=$(pwd)
for i in ${@:2}
do
if [! -e $i]
then
error_msg "The file you want to remove is not found!"
fi
rm $i
CLASS_NAME=$(class_name $MARK)
goto_root
rm -rf $IMAGES/$CLASS_NAME/${i%.*}
HTML_OF_POST=$OUTPUT/$CLASS_NAME/${i%.*}.html
if [-e HTML_OF_POST]
then
rm $HTML_OF_POST
fi
cd $MARK
done
goto_root
git add .
DOCUMENTS="${@:2}"
git commit -a -m "Remove $DOCUMENTS"
;;
esac
;;
rename)
case $2 in
"")
error_msg "You should tell me the name of the post you want to rename!"
;;
*)
if [! -e $2]
then
error_msg "The file you want to rename is not found!"
fi
case $3 in
"")
error_msg "You should tell me new name of the post!"
;;
*)
mv $2 $3
CLASS_NAME=$(class_name $(pwd))
goto_root
mv $IMAGES/$CLASS_NAME/${2%.*} $IMAGES/$CLASS_NAME/${3%.*}
mv $OUTPUT/$CLASS_NAME/${2%.*} $OUTPUT/$CLASS_NAME/${3%.*}
git add .
git commit -a -m "Rename $2 $3"
;;
esac
;;
esac
;;
convert)
case $2 in
"")
error_msg "You should tell me the name of the post!"
;;
*)
MARK=$(pwd)
for i in ${@:2}
do
TITLE=$(get_title $i)
CLASS_NAME=$(class_name $MARK)
goto_root
markdown_to_html $CLASS_NAME $i
cd $MARK
done
;;
esac
;;
preview)
case $2 in
"")
error_msg "You should tell me the name of the post!"
;;
*)
TITLE=$(get_title $2)
CLASS_NAME=$(class_name $(pwd))
goto_root
source gar.conf
$BROWSER_FOR_GAR $OUTPUT/$CLASS_NAME/${2%.*}.html
;;
esac
;;
tree)
goto_root
GAR_ROOT=$(basename $(pwd))
cd ..
tree $GAR_ROOT
cd $GAR_ROOT
;;
*)
error_msg "I do not know what you want to do!"
;;
esac
Gar 在应用 pandoc 将 Markdown 文档转化为网页时,须要一个 CSS 文件 gar.css,其内容如下:
html {
font-size: 16px;
line-height: 1.8rem;
}
body {
margin: 0 auto;
max-width: 50rem;
padding: 50px;
hyphens: auto;
word-wrap: break-word;
font-kerning: normal;
}
header {
text-align: center;
margin-bottom: 4rem;
}
h1, h2, h3, h4, h5 {
margin-top: 2rem;
margin-bottom: 2rem;
color: #d35400;
}
h1.title {font-size: 2.5rem;}
h1 {font-size: 1.8rem;}
h2 {font-size: 1.65rem;}
h3 {font-size: 1.5em;}
h4 {font-size: 1.35rem;}
h5 {font-size: 1.2rem;}
p {
margin: 1.3rem 0;
text-align: justify;
}
figure {text-align: center;}
figure img {width: 80%;}
figure figcaption {font-size: 0.9rem;}
pre {
padding: 1rem;
font-size: 0.9rem;
line-height: 1.6em;
overflow:auto;
background: #f8f8f8;
border: 1px solid #ccc;
border-radius: 0.25rem;
}
p code {color: #d35400;}
/* 文章里大节题目的序号与题目名称之间的间距 */
span.section-sep {margin-left: 0.5rem; margin-right: 0.5rem;}
blockquote {
margin: 0px !important;
border-left: 4px solid #009A61;
}
blockquote p {
font-size: 1rem;
line-height: 1.8rem;
margin: 0px !important;
text-align: justify;
padding:0.5em;
}
上述 gar.css 并无特别之处,齐全可依据本人对 css 的相熟水平并联合须要自行定制,然而要记得将它放在 gar 脚本同一目录下。