1 ViKi 编译脚本

为了方便生成的 HTML 的打包与上传,最好不要把 viki 文件与生成的 HTML 文件放在同一个目录下,滇狐提供的 Linux 和 Windows 下的编译脚本中,开头部分都含有目的 HTML 存放路径的定义,请根据需要进行修改。

在 Linux 下,滇狐编写了一段 shell 脚本来处理 ViKi 的编译,只要将以下脚本存放到 viki 文件所在的文件夹,修改“TARGET_DIR”一行,将它指向你存放 HTML 的目的文件夹,然后到 viki 所在文件夹下执行该脚本就可以了:

#!/usr/bin/env bash

umask 0022

TARGET_DIR=~/Public/html
ARGS="-m lang-zh_CN-autospace -m utf8 -m code-vim73 -t bright.html --css bright -X"

if [ $# -gt 0 ]; then
  all=yes
else
  all=no
fi

build_file() {
  filebase=`basename "$1" .$2`
  output="$TARGET_DIR/$filebase.html"
  shouldbuild=no
  if [ "$all" = "yes" -o "$1" -nt "$output" ]; then
    shouldbuild=yes
  fi
  if [ "$shouldbuild" = "no" ]; then
    for dep in `grep '^#WITH ' $1 | \
          sed -e 's/^#WITH file=//' -e 's/:.*$//'`; do
      if [ "$dep" -nt "$output" ]; then
        shouldbuild=yes
        break
      fi
    done
  fi
  if [ "$shouldbuild" = "yes" ]; then
    tempfile=`mktemp`
    if [ $2 = "md" ]; then
      sed -f md2viki.sed "$1" > $filebase.viki
      deplate -o "$output" $ARGS $filebase.viki
      rm $filebase.viki
    else
      deplate -o "$output" $ARGS "$1"
    fi
    echo "$filebase" >> upload.txt
    rm -rf $TARGET_DIR/*_code_*
    tags=`grep ^#KEYWORDS: $1 | head -1 | cut -c 1-11 --complement`
    if [ "$tags" != "" ]; then
      title=`grep ^#TITLE: $1 | head -1 | cut -c 1-8 --complement`
      if [ "$title" = "" ]; then
        title="<无标题文档>"
      fi
      echo "$tags" | sed 's/ *; */\n/g' | (
        while read tag; do
          tagfile=$(printf 'tag_%02x_%s' \
              "$(echo -n "$tag" | wc -c)" \
              "$(echo -n "$tag" | md5sum | awk '{ print $1 }')")
          echo -n "<a href=\"$tagfile.html\">$tag</a> " >> $tempfile
        done
      )
      command="s,TAGS_GO""ES_HERE,<div id=\"tags\"> 标签:`cat $tempfile`</div>,"
    else
      command="s,TAGS_GO""ES_HERE,,"
    fi
    if grep -q 'TAGS_GO''ES_HERE' $TARGET_DIR/$filebase.html ; then
      sed -i -e "$command" $TARGET_DIR/$filebase.html
    fi
    rm $tempfile
  fi
}

for file in *.viki; do
  build_file $file viki
done
for file in *.md; do
  build_file $file md
done

mv upload.txt upload.bak
sort upload.bak | uniq > upload.txt
rm -f upload.bak

另外,滇狐编写了一段简单的 sed 脚本把简单的 Markdown 文件转换为 viki 文件,只支持 Markdown 最最基本的功能的一个子集:

# Code block
s/^```\(.\+\)/#Code syntax=\1 <<---/
s/^```$/---/
# Code
s/`/''/g
# Link
s/\[\([^]]*\)](\([^)]*\))/[[\2][\1]]/g
# Unordered list
s/^\s*\* /  &/
s/^\s*/  &/
# Ordered list
s/^\(\s*\)[0-9]\+\./  \1/
# Headings
s/^###### /****** /
s/^##### /***** /
s/^#### /**** /
s/^### /*** /
s/^## /** /
s/^//
# Metadata
s/^@/#/

滇狐不在 Windows 下写 ViKi,不过还是为仍在 Windows 下受苦的朋友们提供了使用 vbs 编写的编译脚本。将这个脚本放到 viki 文件所在的文件夹下,命名为 build.vbs,修改“htmlPath”一行,将它指向你存放 HTML 的目的文件夹,然后到 viki 所在文件夹下双击该脚本就可以了。这个脚本是滇狐 2005 年写的,已经长时间没有在 Windows 下测试过该段脚本的有效性,所以如果这段脚本在你的机器上无法正常运行的话,请自行修改,欢迎将修改后的脚本发回给滇狐共享。

On Error Resume Next

htmlPath = "C:\Documents and Settings\edward\My Documents\html"
args = "-m zh-cn-autospace -m utf8 -m code-vim73 -t bright.html --css bright -X"

If Right(htmlPath, 1) <> "\" Then
    htmlPath = htmlPath & "\"
End If

sSelfPath = WScript.ScriptFullName
sSelfPath = Left(sSelfPath, InStrRev(sSelfPath, "\") - 1)

Set WshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
tSelfTime = fso.GetFile(WScript.ScriptFullName).DateLastModified

Set folder = fso.GetFolder(sSelfPath)
For Each file In folder.Files
    build = false
    vikiName = file.Name
    htmlFilename = ""

    If Len(vikiName) > 5 Then
        If LCase(Right(vikiName, 5)) = ".viki" Then
            htmlFilename = htmlPath & Left(vikiName, Len(vikiName) - 5) _
                & ".html"
            If fso.FileExists(htmlFilename) Then
                Set htmlFile = fso.GetFile(htmlFilename)
                If file.DateLastModified > htmlFile.DateLastModified Or _
                    tSelfTime> htmlFile.DateLastModified Then
                    build = True
                End if
            Else
                build = True
            End if
        End if
    End If

    If build Then
        cmdLine = "deplate.exe " & args & " -d " _
            & """" & Replace(htmlPath, "\", "/") & """ " _
            & """" & Replace(file.Path, "\", "/")  & """"
        WScript.StdOut.WriteLine cmdLine
        Set oExec = WshShell.Exec("cmd.exe /c " & cmdLine & " 2>&1")
        While Not oExec.StdOut.AtEndOfStream
            Line = oExec.StdOut.ReadLine
            WScript.StdOut.WriteLine Line
        Wend
    End if
Next

cmdLine = "del """ & htmlPath & "code_*"" """ & htmlPath & "deplateCodeAuto*"""
WScript.StdOut.WriteLine cmdLine
Set oExec = WshShell.Exec("cmd.exe /c " & cmdLine & " 2>&1")
While Not oExec.StdOut.AtEndOfStream
    Line = oExec.StdOut.ReadLine
    WScript.StdOut.WriteLine Line
Wend

Set fso = Nothing
Set WshShell = Nothing

2 更新日志生成脚本

滇狐曾经使用这段 sh 脚本生成网站的更新日志,目前暂不提供该脚本的 Windows 版本。

#!/bin/sh

get_title()
{
    titleline="`grep '^#TITLE:' $filename`"
    title="${titleline/\\#TITLE:/}"
    title=`echo $title`
    if test "$title" = ""; then
        title="<无标题文档>"
    fi
}

list_item()
{
    get_title
    echo >> $logfile
    echo "    * [[`basename $filename .viki`][$title]]" >> $logfile
}

logtitle=`date +"%Y 年 %m 月 %d 日 更新日志"`
logfile=`date +"log_%Y%m%d.viki"`
echo "#TITLE: $logtitle" > $logfile
echo >> $logfile
echo $logtitle >> $logfile

for item in `grep \\.html$ upload.txt`
do
    filename=`basename $item .html`.viki
    list_item
done

touch log.viki
grep -v '#TITLE:' log.viki > log.bak

echo "#TITLE: 更新日志" > log.viki
echo >> log.viki
echo "    * [[`basename $logfile .viki`][$logtitle]]" >> log.viki
cat log.bak >> log.viki
rm -f log.bak

3 打包上传脚本

由于学校提供的服务器不支持 FTP 上传,HTTP 上传总是比较麻烦。幸好服务器支持 zip 包的上传解压,为了节省工作量,滇狐使用这段脚本生成上传用的 zip 包。从上文的编译脚本可以看出,滇狐在编译时记录了被更新过的文件名列表,所以打包的时候就比较简单了:

#!/bin/sh

TARGET_DIR=~/Public
TARGET=html
ZIP_FILE=html.zip

curpath=`pwd`
pushd .

cd $TARGET_DIR
rm -f $ZIP_FILE

for file in `cat $curpath/upload.txt`
do
    zip $ZIP_FILE $TARGET/$file
done

popd

rm -f upload.txt

Windows 下的打包脚本就不提供了,因为 xcopy 命令可以自动判断文件修改时间,很容易自己写一个打包脚本。而且,大部分 Windows 机器上都不会安装 zip.exe,所以滇狐没法提供一个通用的 zip 打包脚本。