Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
2 files changed, 363 insertions, 0 deletions
-rw-r--r--0001-csg-Reworked-pipeline-with-multiple-types-of-scripts.patch303
-rw-r--r--README.md60
diff --git a/0001-csg-Reworked-pipeline-with-multiple-types-of-scripts.patch b/0001-csg-Reworked-pipeline-with-multiple-types-of-scripts.patch
new file mode 100644
index 0000000..4b4342e
--- /dev/null
+++ b/0001-csg-Reworked-pipeline-with-multiple-types-of-scripts.patch
@@ -0,0 +1,303 @@
+From 83dbc95676d9dca7c5e787c89cf56dc1048f7c24 Mon Sep 17 00:00:00 2001
+From: Syndamia <kamen@syndamia.com>
+Date: Tue, 30 Apr 2024 08:37:11 +0300
+Subject: [PATCH] [csg] Reworked pipeline with multiple types of scripts
+
+---
+ csg | 225 +++++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 118 insertions(+), 107 deletions(-)
+
+diff --git a/csg b/csg
+index eb2a7c8..de8b6bd 100755
+--- a/csg
++++ b/csg
+@@ -65,8 +65,28 @@ URL="$4"
+ [ -z "$URL" ] && echo "[Error] <base_url> cannot be an empty string!" \
+ && csg_help 3
+
+-AWKSCRIPTS="$5"
+-[ -n "$AWKSCRIPTS" -a ! -d "$AWKSCRIPTS" ] && echo "[Error] $AWKSCRIPTS (<scripts_dir>) isn't a directory or doesn't exist!" \
++LIB_SCRIPT="$5"
++[ -n "$LIB_SCRIPT" -a ! -d "$LIB_SCRIPT" ] && echo "[Error] $LIB_SCRIPT (<scripts_dir>) isn't a directory or doesn't exist!" \
++ && csg_help 1
++
++PREV_ALL="$6"
++[ -n "$PREV_ALL" -a ! -d "$PREV_ALL" ] && echo "[Error] $PREV_ALL (<scripts_dir>) isn't a directory or doesn't exist!" \
++ && csg_help 1
++
++PREV_MD="$7"
++[ -n "$PREV_MD" -a ! -d "$PREV_MD" ] && echo "[Error] $PREV_MD (<scripts_dir>) isn't a directory or doesn't exist!" \
++ && csg_help 1
++
++ON_MD="$8"
++[ -n "$ON_MD" -a ! -d "$ON_MD" ] && echo "[Error] $ON_MD (<scripts_dir>) isn't a directory or doesn't exist!" \
++ && csg_help 1
++
++ON_HTML="$9"
++[ -n "$ON_HTML" -a ! -d "$ON_HTML" ] && echo "[Error] $ON_HTML (<scripts_dir>) isn't a directory or doesn't exist!" \
++ && csg_help 1
++
++ON_OTHER="${10}"
++[ -n "$ON_OTHER" -a ! -d "$ON_OTHER" ] && echo "[Error] $ON_OTHER (<scripts_dir>) isn't a directory or doesn't exist!" \
+ && csg_help 1
+
+ ### Preprocessing 3
+@@ -89,7 +109,8 @@ if [ -n "$CSG_AWK" ]
+ then :
+ elif isCommand 'gawk'
+ then
+- CSG_AWK='gawk --posix'
++ CSG_AWK='gawk
++ --posix'
+ else
+ echo '[Error] Couldn'\''t find an awk implementation!'
+ csg_help 4
+@@ -99,10 +120,10 @@ if [ -n "$CSG_MD_TO_HTML" ]
+ then :
+ elif isCommand 'lowdown'
+ then
+- CSG_MD_TO_HTML="lowdown \
+- --html-no-escapehtml \
+- --html-no-skiphtml \
+- --parse-no-metadata \
++ CSG_MD_TO_HTML="lowdown
++ --html-no-escapehtml
++ --html-no-skiphtml
++ --parse-no-metadata
+ --parse-no-autolink"
+ else
+ echo '[Error] Couldn'\''t find a Markdown to HTML convertion program!'
+@@ -168,89 +189,59 @@ done << EOF
+ $(find "$DESTINATION" -type f -name "*index.md" -links +1)
+ EOF
+
+-if [ -n "$AWKSCRIPTS" ] && [ -n "$(find $AWKSCRIPTS -type f -name "[A-Z]*.awk")" ]
+-then
+- overwriteLine "[Stage 1] Combining awk scripts"
++overwriteLine "[Stage 1] Combining awk scripts"
+
+- awk_scr="$($CSG_AWK -v TMP_DIR="$CSG_TMP_DIR" '
+- {
+- # Remove first field
+- $1=""; sub(FS, "")
+- # Associate current file with regex
+- if (awks[$0] == "") {
+- awks[$0] = FILENAME
+- regexes[regexcount++] = $0
+- }
+- else {
+- awks[$0] = awks[$0] " " FILENAME
+- }
+-
+- nextfile
+- }
+- END {
+- # Regexes are outputed in file alphabetic order
+- # Since certain scripts may require specific ordering
+- # between their rules, this is a crude way to allow that
+- for (regi = 0; regi < regexcount; regi++) {
+- print regexes[regi]
+- outf = TMP_DIR "/csg-" (awkcount++) ".awk"
+- print outf
+- system("cat " awks[regexes[regi]] " > " outf)
+- }
+- }
+- ' $(find $AWKSCRIPTS -type f -name "[A-Z]*.awk" | sort))"
++combine_scripts() {
++ rm "$CSG_TMP_DIR/$2" >/dev/null 2>&1
+
+- overwriteLine "[Stage 1] Finding awk libraries"
++ [ -z "$1" ] && echo "" && return
+
+- scr_libs=""
+- while read -r file
+- do
+- [ -n "$file" ] && scr_libs="$scr_libs -f $file "
+- done << EOF
+-$(find $AWKSCRIPTS -type f -name "#*.awk")
+-EOF
+-fi
++ scripts=$(find "$1" -type f -name "*.awk" | sort)
++ [ -z "$scripts" ] && echo "" && return
+
++ cat $scripts > "$CSG_TMP_DIR/$2"
++ echo "-f $CSG_TMP_DIR/$2"
++}
++
++lib_script="$(combine_scripts "$LIB_SCRIPT" "csg-lib_script.awk")"
++on_md="$(combine_scripts "$ON_MD" "csg-on_md.awk")"
++on_html="$(combine_scripts "$ON_HTML" "csg-on_html.awk")"
++on_other="$(combine_scripts "$ON_OTHER" "csg-on_other.awk")"
++prev_all="$(combine_scripts "$PREV_ALL" "csg-prev_all.awk")"
++prev_md="$(combine_scripts "$PREV_MD" "csg-prev_md.awk")"
++
++echo
+ endTimer "[Stage 1] Done"
+
+ ### Stage 2
+ ### Transforming Markdown
+ startTimer "[Stage 2] Transforming Markdown to HTML"
+
+-transform_file() {
+- local file="$1"
+- local outf="${file%md}html"
+-
+- # Gets special information from the file
+- local title descr words
+- { read -r title; read -r descr; read -r words; } << EOF
+-$($CSG_AWK -v titlef="$TITLEF" '
+- title == "" && /^# / {
+- # Remove first field
+- $1 = ""; sub(FS, "")
+- # Output title
+- sub(/.*/, titlef)
+- title = $0
+- next
++# prev_all
++cat << EOF > "$CSG_TMP_DIR/csg-export.awk"
++function export(name, value) {
++ if (name == "" || value == "") {
++ return
+ }
+- stopdesc == 0 && /^[[:alpha:]]/ {
+- startedGathering = 1
+- # Take only anchor text
+- gsub(/\]\([^)]*\)/, "")
+- gsub(/\[/, "")
+- # Append line
+- if (desc == "") desc = $0
+- else desc = desc " " $0
+- # Trim line to 200 characters
+- if (length(desc) > 200) {
+- desc = substr(desc, 1, 197) "..."
+- stopdesc = 1
+- }
++ # if is string
++ if (value + 0 != value) {
++ gsub(/"/, "\\\\\\"", value)
+ }
+- stopdesc == 0 && startedGathering == 1 && /^$/ { stopdesc = 1 }
+- { words += NF }
+- END { print title ORS desc ORS words }' "$file")
++
++ printf " -v " name "=" ((value + 0 == value) ? value : ("\\"" value "\\"")) " "
++}
+ EOF
++exports=$($CSG_AWK \
++ -f "$CSG_TMP_DIR/csg-export.awk" \
++ $lib_script $prev_all \
++ $(find "$DESTINATION" -type f -name "*.md"))
++
++echo '$0 != 0 {print}' > "$CSG_TMP_DIR/csg-print.awk"
++echo 'BEGIN { FILENAME = truefilename } NR == 1 { FILENAME = truefilename }' > "$CSG_TMP_DIR/csg-filename.awk"
++
++transform_file() {
++ local file="$1"
++ local outf="${file%md}html"
+
+ local created edited
+ if [ -f "$CSG_TIMESTAMP_FILE" ]
+@@ -265,50 +256,70 @@ $($CSG_AWK -v file="$outf" '
+ EOF
+ fi
+
+- # Generate
+- $CSG_MD_TO_HTML "$file" > "$outf"
+-
+- # Run custom awk scripts
+- local scripts="$(printf "$awk_scr" | $CSG_AWK -v file="$outf" '
+- capture == 1 { capture = 0; printf " -f " $0; next; }
+- capture == 2 { capture = 0; next; }
+- { capture = 1 + !match(file, $0) }
+- ')"
++ # prev_md
++ local_exports=$($CSG_AWK\
++ -f "$CSG_TMP_DIR/csg-export.awk"\
++ $lib_script $prev_md\
++ "$file")
+
++ # on_md and on_html
+ $CSG_AWK \
+- -v title="$title" \
+- -v description="$descr" \
+- -v words="$words" \
+ -v created="$created" \
+ -v edited="$edited" \
+- $scr_libs $scripts -f "$CSG_TMP_DIR/csg-print.awk" \
+- "$outf" > "$outf.tmp"
+- mv "$outf.tmp" "$outf"
++ $exports $local_exports \
++ $lib_script $on_md -f "$CSG_TMP_DIR/csg-print.awk" \
++ "$file" \
++ | $CSG_MD_TO_HTML \
++ | cat "$SOURCE/_header.html" - "$SOURCE/_footer.html" \
++ | $CSG_AWK \
++ -v created="$created" \
++ -v edited="$edited" \
++ $exports $local_exports \
++ -v truefilename="$outf" -f "$CSG_TMP_DIR/csg-filename.awk" \
++ $lib_script $on_html -f "$CSG_TMP_DIR/csg-print.awk" \
++ > "$outf"
+
+- # Create final file
+- $CSG_AWK \
+- -v title="$title" \
+- -v description="$descr" '
+- BEGIN { gsub(/&/, "\\\\&", title) }
+- /\[DESCRIPTION\]/ {
+- gsub(/\[DESCRIPTION\]/, description)
+- }
+- /\[TITLE\]/ {
+- gsub(/\[TITLE\]/, title)
+- }
+- {print}' "$SOURCE/_header.html" > "$file"
+- cat "$outf" "$SOURCE/_footer.html" >> "$file"
++ # For hardlinks
++ cat "$outf" > "$file"
+ mv "$file" "$outf"
+ }
+
+-echo '$0 != 0 {print}' > "$CSG_TMP_DIR/csg-print.awk"
++tempifs=$IFS
++IFS='
++ '
+
+ while read -r file
+ do
+- transform_file "$file" "$scripts" &
++ transform_file "$file" &
+ done << EOF
+ $(find "$DESTINATION" -type f -name "*.md")
+ EOF
++
++IFS=$tempifs
++
++if [ -n "$on_other" ]
++then
++ transform_other() {
++ local file="$1"
++
++ $CSG_AWK \
++ $exports $local_exports \
++ $lib_script $on_other -f "$CSG_TMP_DIR/csg-print.awk" \
++ "$file" > temp
++ mv temp "$file"
++ }
++
++ while read -r file
++ do
++ if [ -f "$file" ]
++ then
++ transform_other "$file" &
++ fi
++ done << EOF
++$(find "$DESTINATION" -type f -not -name "*.md")
++EOF
++fi
++
+ wait
+
+ overwriteLine "[Stage 2] Generating sitemap"
+--
+2.42.0
+
diff --git a/README.md b/README.md
index 1791830..3e62b8b 100644
--- a/README.md
+++ b/README.md
@@ -127,3 +127,63 @@ Created by Syndamia, https://gitlab.com/Syndamia/csg
3. Timestamps.txt but based on created/edited file stats
4. Need to add a `_ignore` file to not convert certain folders
5. Add native support for more awk parsers and markdown to html converters
+
+## Raison d'etre
+
+Comparing to other "portable" generators:
+
+(bash)
+
+Nanoblogger
+- ?
+
+Statix
+- requires GNU grep with certain compile flags
+- limited, template language
+
+Ultra Simle Site Maker
+- ocaml?
+
+utterson
++ drafts
+- way too complicated
+
+vee
++ gopher support
++ editing last x
+- very limited abilities
+
+simsalabash
+- way too bash-oriented
+
+bashblog
++ drafts
++ tags
+- template "customisation"
+- not really extensible
+
+dsw
++ arbitrary markup language
+
+(awk)
+
+zodiac
+- template language
+- template syntax makes source way too "ugly"
+
+simple-static
+- no customization
+
+mksite
+- templating
+
+(c)
+
+HSC
+- way too ugly formatter, more like fancy html
+
+GSL iMatrix
+- way to big an heavy and fancy
+
+blogc
+- way too big