mirror of
https://git.sakamoto.pl/laudom/http.sh.git
synced 2025-08-04 12:53:32 +02:00
Compare commits
3 commits
93271da824
...
c6311cf4c1
Author | SHA1 | Date | |
---|---|---|---|
|
c6311cf4c1 | ||
|
e9018284f5 | ||
|
e809c0be6b |
5 changed files with 123 additions and 18 deletions
|
@ -10,7 +10,7 @@ declare -A str
|
|||
str[title]="Hello, world!"
|
||||
str[test]="meow"
|
||||
|
||||
render str "${cfg[namespace]}/templates/main.htm"
|
||||
render str "templates/main.htm"
|
||||
```
|
||||
|
||||
`render` is the core of the templating engine; it takes an assoc array, iterates over it, applies
|
||||
|
@ -18,7 +18,10 @@ additional magic and outputs the response directly to stdout. It is likely the f
|
|||
to run in your script.
|
||||
|
||||
The script above has referenced an HTML file; For this example, we put it under
|
||||
`app/templates/main.htm`, but you're free to use any directory structure for this.
|
||||
`app/templates/main.htm`, but you're free to use any directory structure for this. An observant
|
||||
reader might have noticed the relative path; All paths are treated as relative to the namespace's
|
||||
directory. This behavior can be modified by setting `template_relative_paths`, which is described
|
||||
in greater detail by the [main template documentation](./template.md).
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
|
@ -100,7 +103,7 @@ done
|
|||
# once we have a full list of elements, assign it to the array passed to render
|
||||
str[_list]=list
|
||||
|
||||
render str "${cfg[namespace]}/templates/main.htm"
|
||||
render str "templates/main.htm"
|
||||
```
|
||||
|
||||
And the template...
|
||||
|
@ -182,7 +185,7 @@ declare -A str
|
|||
str[title]="time pretty-print"
|
||||
str[+time]="$EPOCHSECONDS"
|
||||
|
||||
render str "${cfg[namespace]}/templates/main.htm"
|
||||
render str "templates/main.htm"
|
||||
```
|
||||
|
||||

|
||||
|
|
|
@ -23,8 +23,34 @@ For practical examples, see the [template examples](template-examples.md) page.
|
|||
`render <assoc_array> <file> [recurse]`
|
||||
|
||||
The first param points to an associative array containing the replacement data. Second one points
|
||||
to a file containing the template itself. Third is optional, and controls whether `render` will
|
||||
recurse or not. This is mostly used internally, you likely won't ever need to set it.
|
||||
to a file containing the template itself (see section below for special usage). Third is optional,
|
||||
and controls whether `render` will recurse or not (this is mostly used internally, you likely
|
||||
won't ever need to set it).
|
||||
|
||||
### File paths
|
||||
|
||||
Starting with HTTP.sh 0.97.1 (2025-05-18), paths in calls to `render` and include tags are
|
||||
relative to the namespace directory (usually `app/`). This behavior can be changed by defining
|
||||
an array called `template_relative_paths`:
|
||||
|
||||
```
|
||||
template_relative_paths=(
|
||||
"${cfg[namespace]}/templates/neue_theme/"
|
||||
"${cfg[namespace]}/templates/default/"
|
||||
)
|
||||
```
|
||||
|
||||
The templating engine will check all the files in order and pick the first one that exists. This
|
||||
can be used to implement basic inheritance.
|
||||
|
||||
Before 0.97.1, paths were relative to the main HTTP.sh directory. Take care when upgrading, either
|
||||
fix the paths, or set `template_relative_paths="./"` to emulate the previous behavior.
|
||||
|
||||
### Inline templates
|
||||
|
||||
For some purposes, it may be beneficial to store the template within the script file itself.
|
||||
This can be done either through passing `/dev/stdin` as a file name, or through inlining
|
||||
a file substitution, such as `<(echo ...)`.
|
||||
|
||||
## Simple replace
|
||||
|
||||
|
@ -58,9 +84,8 @@ output (for filling out hidden form values, etc.)
|
|||
Template includes are special, in that you don't have to define them in the array.
|
||||
They get processed first to "glue together" one singular template.
|
||||
|
||||
Currently, the path starts at the root of HTTPsh's directory. We don't support expanding variables
|
||||
inside the include tag, so for now you'll need to hardcode `{{#app/templates/...}}`. This will
|
||||
likely get changed in a future release, starting the path in your namespace.
|
||||
The path starts at the root of your namespace (usually `app/`). This behavior can be changed,
|
||||
see section "File paths" above.
|
||||
|
||||
**Warning**: No recursion is supported within included templates; This means that you can't have
|
||||
an "include chain". Furthermore, some interactions between included templates and loops/ifs are
|
||||
|
|
|
@ -6,11 +6,18 @@
|
|||
function render() {
|
||||
local _tpl_newline=$'\01'
|
||||
local _tpl_ctrl=$'\02'
|
||||
local tplfile
|
||||
|
||||
_template_find_absolute_path "$2"
|
||||
|
||||
if [[ ! "$tplfile" ]]; then
|
||||
exit 1 # fail hard
|
||||
fi
|
||||
|
||||
if [[ "$3" != true ]]; then
|
||||
local template="$(tr -d "${_tpl_newline}${_tpl_ctrl}" < "$2" | sed 's/\&/<2F>UwU<77>/g')"
|
||||
local template="$(tr -d "${_tpl_newline}${_tpl_ctrl}" < "$tplfile" | sed 's/\&/<2F>UwU<77>/g')"
|
||||
else
|
||||
local template="$(tr -d "${_tpl_ctrl}" < "$2" | sed -E 's/\\/\\\\/g')"
|
||||
local template="$(tr -d "${_tpl_ctrl}" < "$tplfile" | sed -E 's/\\/\\\\/g')"
|
||||
fi
|
||||
local buf=
|
||||
local garbage="$template"$'\n'
|
||||
|
@ -24,14 +31,19 @@ function render() {
|
|||
# below check prevents the loop loading itself as a template.
|
||||
# this is possibly not enough to prevent all recursions, but
|
||||
# i see it as a last-ditch measure. so it'll do here.
|
||||
if [[ "$file" == "$2" ]]; then
|
||||
if [[ "$file" == "$tplfile" ]]; then
|
||||
subtemplate+="s${_tpl_ctrl}\{\{\#$key\}\}${_tpl_ctrl}I cowardly refuse to endlessly recurse\!${_tpl_ctrl}g;"
|
||||
elif [[ -f "$key" ]]; then
|
||||
local input="$(tr -d "${_tpl_ctrl}${_tpl_newline}" < "$key" | sed 's/\&/<2F>UwU<77>/g')"
|
||||
# elif [[ -f "$key" ]]; then
|
||||
else
|
||||
local i
|
||||
local IFS=''
|
||||
|
||||
_template_find_absolute_path "$key"
|
||||
local input="$(tr -d "${_tpl_ctrl}${_tpl_newline}" < "$tplfile" | sed 's/\&/<2F>UwU<77>/g')"
|
||||
garbage+="$input"$'\n'
|
||||
input="$(tr $'\n' "${_tpl_newline}" <<< "$input")" # for another hack
|
||||
subtemplate+="s${_tpl_ctrl}\{\{\#$key\}\}${_tpl_ctrl}${input}${_tpl_ctrl};"
|
||||
_template_find_special_uri "$(cat "$key")"
|
||||
_template_find_special_uri "$(cat "$tplfile")"
|
||||
fi
|
||||
done <<< "$(grep -Poh '{{#\K(.*?)(?=}})' <<< "$template")"
|
||||
|
||||
|
@ -118,6 +130,27 @@ function render() {
|
|||
[[ "$3" != true ]] && _template_uri_list=()
|
||||
}
|
||||
|
||||
# internal function that looks for the current template. uses path relative to
|
||||
# the namespace, unless overriden with ${template_relative_paths[@]}
|
||||
#
|
||||
# - /dev/stdin is a special value, which gets passed literally.
|
||||
# - /dev/fd/* allows file substitutions `<(echo ...)` to be used.
|
||||
#
|
||||
# _template_find_absolute_path(name) -> $tplfile
|
||||
_template_find_absolute_path() {
|
||||
if [[ ! "${template_relative_paths}" || "$1" == /dev/stdin || "$1" == "/dev/fd/"* ]]; then
|
||||
tplfile="$1"
|
||||
else
|
||||
for (( i=0; i<${#template_relative_paths[@]}; i++ )); do
|
||||
if [[ -f "${template_relative_paths[i]}/$1" ]]; then
|
||||
tplfile="${template_relative_paths[i]}/$1"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
_template_uri_list=()
|
||||
# internal function that finds all occurences of the special `{{-uri-N}}` tag.
|
||||
# here to also make it run on subtemplates
|
||||
|
@ -168,8 +201,9 @@ function nested_add() {
|
|||
ref+=("$nested_id")
|
||||
}
|
||||
|
||||
# nested_get(ref, i)
|
||||
# nested_get(ref, i, [res])
|
||||
function nested_get() {
|
||||
local -n ref=$1
|
||||
declare -g -n res=_${ref["$2"]}
|
||||
local name=${3:-res}
|
||||
declare -g -n $name=_${ref["$2"]}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
HTTPSH_VERSION=0.97
|
||||
HTTPSH_VERSION=0.97.1
|
||||
|
|
|
@ -51,6 +51,45 @@ tpl_date_invalid() {
|
|||
match="value: 1970-01-01 01:00:00"
|
||||
}
|
||||
|
||||
tpl_path_custom() {
|
||||
prepare() {
|
||||
declare -ga template_relative_paths=("/tmp/")
|
||||
|
||||
tempfile="$(mktemp)" || return 1
|
||||
}
|
||||
|
||||
tst() {
|
||||
declare -A meow
|
||||
render meow "$(basename "$tempfile")"
|
||||
}
|
||||
}
|
||||
|
||||
tpl_path_inheritance() {
|
||||
prepare() {
|
||||
tempdir="$(mktemp -d)" || return 1
|
||||
declare -ga template_relative_paths=(
|
||||
"$tempdir"
|
||||
"/tmp/"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tpl_path_include() {
|
||||
prepare() {
|
||||
another_tempfile="$(mktemp)"
|
||||
echo "meow?" > "$another_tempfile"
|
||||
echo "{{#$(basename "$another_tempfile")}}" > "$tempfile"
|
||||
}
|
||||
|
||||
match="meow?"
|
||||
|
||||
cleanup() {
|
||||
rm -R "$tempdir"
|
||||
rm "$tempfile" "$another_tempfile"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
subtest_list=(
|
||||
tpl_basic
|
||||
tpl_basic_specialchars
|
||||
|
@ -59,4 +98,8 @@ subtest_list=(
|
|||
tpl_date
|
||||
tpl_date_empty
|
||||
tpl_date_invalid
|
||||
|
||||
tpl_path_custom
|
||||
tpl_path_inheritance
|
||||
tpl_path_include
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue