meso-web

Sources of the |Méso|Star> website
git clone git://git.meso-star.fr/meso-web.git
Log | Files | Refs | README | LICENSE

commit 352607712f6b3ba93178459f295ed7cff71ee561
parent d489cce019a7f2d9a73709aa80542969c12e9dc9
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 25 Aug 2025 15:24:48 +0200

Move the build system shells to the scripts subdirectory

Update the scripts accordingly to reflect this update

Diffstat:
MMakefile | 25++++++++++++-------------
Dgenerate_header.sh | 256-------------------------------------------------------------------------------
Dhooks.sh | 111-------------------------------------------------------------------------------
Dindex.sh | 33---------------------------------
Dlist.sh | 114-------------------------------------------------------------------------------
Mschiff/hooks/01-generate-man.sh | 4++--
Mschiff/schiff-downloads.sh | 2+-
Rconvert_man.sh -> scripts/convert_man.sh | 0
Ascripts/generate_header.sh | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ascripts/hooks.sh | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ascripts/index.sh | 33+++++++++++++++++++++++++++++++++
Ascripts/list.sh | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rmeso-web.sh -> scripts/meso-web.sh | 0
Msolstice/hooks/01-generate-man.sh | 4++--
Msolstice/solstice-downloads.sh | 2+-
15 files changed, 532 insertions(+), 533 deletions(-)

diff --git a/Makefile b/Makefile @@ -24,11 +24,11 @@ default: build build clean distclean lint install: hooks index @$(MAKE) -f.hooks -f.index -fMakefile $@__ \ - HTML="$$($(SHELL) ./list.sh html | tr '\n' ' ')" \ - SH="$$( $(SHELL) ./list.sh shell | tr '\n' ' ')" + HTML="$$($(SHELL) ./scripts/list.sh html | tr '\n' ' ')" \ + SH="$$( $(SHELL) ./scripts/list.sh shell | tr '\n' ' ')" hooks index: - $(SHELL) $@.sh > .$@ + $(SHELL) scripts/$@.sh > .$@ build__: $(HTML) @@ -41,12 +41,12 @@ distclean__: clean__ install__: $(HTML) $(SIG) @rsync --mkpath -avzrR --delete-after --progress \ - meso.css $(HTML) $$($(SHELL) ./list.sh subdir) $(PREFIX) + meso.css $(HTML) $$($(SHELL) ./scripts/list.sh subdir) $(PREFIX) ################################################################################ # Generate content ################################################################################ -$(HTML): generate_header.sh menu.tsv +$(HTML): scripts/generate_header.sh menu.tsv .sh.md: @cd -- "$$(dirname "$<")"; \ @@ -55,7 +55,7 @@ $(HTML): generate_header.sh menu.tsv .md.html: @echo "Building $@" @{ \ - $(SHELL) generate_header.sh $${PWD}/$@; \ + $(SHELL) scripts/generate_header.sh $${PWD}/$@; \ $(MD2HTML) $<; \ cat footer.html; \ } > $@ @@ -69,15 +69,14 @@ $(HTML): generate_header.sh menu.tsv .sh.shlint: @echo "Linting $<" - @# Scripts are executed in their local directory, with the - @# exception of hooks, which are executed relative to the section - @# directory. + @# Scripts are executed relative to their section directory. + @# Scripts belonging to the compilation system are executed + @# relative to the working directory. @i="$<"; \ - if echo "$${i#*/}" | grep -qe '^hooks/'; then \ + if [ "$${i%%/*}" != "scripts" ]; then \ cd -- "$${i%%/*}"; \ - else \ - cd -- "$$(dirname "$<")"; \ + i="$${i#*/}"; \ fi; \ - shellcheck -o all -x "$${i#*/}" + shellcheck -o all -x "$${i}" lint__: $(LINT) diff --git a/generate_header.sh b/generate_header.sh @@ -1,256 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -set -e - -. "./meso-web.sh" - -######################################################################## -# Helper functions -######################################################################## -# Print the absolute dir of the input file -absdir() # file -{ - cd -- "$(dirname "$1")" && pwd - cd "${OLDPWD}" -} - -# List the indexed content in TSV format. Each line contains the index -# label, followed by the indexed content, and possibly an indicator of -# the language used. -# -# The input data is the content of an index.tsv file, submitted on -# standard input. -indexed_content() -( - strip_dummy | while read -r _line; do - _langs="$(echo "${_line}" | cut -d' ' -f3)" - - if [ -z "${_langs}" ]; then - # There is no lang field defined: print the line as it - printf '%s\n' "${_line}" - - else - # The lang field is defined. Duplicate the line as many times as - # there are languages listed. Define the content URI by replacing - # the @LANG@ string with the language value. - echo "${_langs}" \ - | sed 's/:/\n/g' \ - | while read -r _translation; do - echo "${_line}" \ - | sed -e "s/\t[^\t]\{1,\}$/\t${_translation}/g" \ - -e "s/@LANG@/${_translation}/g" - done - fi - done -) - -# Print relative path from input file to worktree -relpath_to_worktree() # file -( - # Build directory from worktree to path - _dir="$(absdir "$1")" - _dir="$(printf '%s\n' "${_dir}" | sed "s;^${worktree}[/]\{0,\};;g")" - - # Ensure that the directory if a subpath of the worktree - if ! [ -d "${_dir}" ]; then - return 1 - fi - - echo "${_dir}" | sed 's/\//\n/g' | while read -r _i; do - printf "../" - done -) - -print_head() -{ - printf '<!DOCTYPE html>\n' - printf '<html lang="%s">\n' "${lang}" - printf '<head>\n' - printf ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n' - printf ' <meta name="viewport" content="width=device-width, initial-scale=1">\n' - printf ' <title>|M|S> %s</title>\n' "${label}" - printf ' <link rel="stylesheet" title="default" href="%smeso.css">\n' "${root}" - printf '</head>\n' - printf '<body>\n' -} - -# Print top-level menu -print_menu1() -( - printf '<div id="menu">\n' - - _separator="" - strip_dummy < "${worktree}/menu.tsv" | while read -r _i; do - - # Retrieve the menu label and its associated directory - _label="$(echo "${_i}" | cut -d' ' -f1)" - _directory="$(echo "${_i}" | cut -d' ' -f2)" - - echo "${_separator}" && _separator=' &emsp13;|&emsp13;' - - if [ "${_directory}" = "${section}" ]; then - printf ' %s\n' "${_label}" - - else - # Get the default page of the section, i.e., the first entry in - # its index. The menu is a link to it. - _uri="$(indexed_content < "${worktree}/${_directory}/index.tsv" \ - | head -1 | cut -d' ' -f2)" - - printf ' <a href="%s%s/%s">%s</a>\n' \ - "${root}" "${_directory}" "${_uri}" "${_label}" - fi - done - - printf '</div>\n<hr>\n' -) - -# Print the list of translation choices -# Available langs are submitted on standard input -print_translations() # uri_template (i.e. URI generic to the lang) -( - _uri_template="$1" - - printf ' <span style="float: right;">\n' - - _separator="" - while read -r _lang; do - - _translation="$(echo "${_uri_template}" | sed "s/@LANG@/${_lang}/g")" - - echo "${_separator}" && _separator=' &emsp13;/&emsp13;' - - if [ "${content}" = "${_translation}" ]; then - printf ' <span class="cur">%s</span>\n' "${_lang}" - else - printf ' <a href="%s%s/%s">%s</a>\n' \ - "${root}" "${section}" "${_translation}" "${_lang}" - fi - done - - printf ' </span>\n' -) - -# Print second-level menu -print_menu2() -( - - printf '<div id="sub-menu">\n' - - _separator="" - strip_dummy < "${worktree}/${section}/index.tsv" | while read -r _i; do - - _label="$(echo "${_i}" | cut -d' ' -f1)" - _uri_template="$(echo "${_i}" | cut -d' ' -f2)" - _langs="$(echo "${_i}" | cut -d' ' -f3)" - _lang_default="$(echo "${_langs}" | cut -d ':' -f1)" - - _uri="$(echo "${_uri_template}" | sed "s/@LANG@/${lang}/g")" - - echo "${_separator}" && _separator=' &emsp13;.&emsp13;' - - if [ "${_uri}" = "${content}" ]; then - # This is the current web page - printf ' <span class="cur">%s</span>\n' "${_label}" - - # Print links to translations if available - if [ -n "${_langs}" ]; then - echo "${_langs}" \ - | sed 's/:/\n/g' \ - | print_translations "${_uri_template}" - fi - - elif echo "${_uri}" | grep -qe "^http[s]\{0,1\}://"; then - # The entry links to an http[s] URL - printf ' <a href="%s">%s</a>\n' "${_uri}" "${_label}" - - else - # The entry links to a local web page for the section - _uri="$(echo "${_uri_template}" | sed "s/@LANG@/${_lang_default}/g")" - printf ' <a href="%s%s/%s">%s</a>\n' \ - "${root}" "${section}" "${_uri}" "${_label}" - fi - done - - printf '</div>\n' -) - -######################################################################## -# The script -######################################################################## -if [ "$#" -lt 1 ]; then - >&2 printf 'usage: %s file\n' "${0##*/}" - exit 1 -fi - -# Define the absolute path of the working directory, i.e. the root -# directory of the site, and enter it. -worktree="$(absdir "$0")" -cd "${worktree}" - -# Define the section directory where the input file is located, i.e., the -# subdirectory in the working directory. -section="$(absdir "$1")" -section="$(printf '%s\n' "${section}" | sed "s;^${worktree}[/]\{0,\};;g")" -section="${section%%/*}" - -if [ -z "${section}" ]; then - >&2 printf \ - '%s: unable to extract the section directory from file %s\n' \ - "${0##*/}" "$1" - exit 1 -fi - -# Find the menu entry corresponding to the section directory -entry="$(strip_dummy < "${worktree}/menu.tsv" \ - | sed -n "/\t${section}/p")" - -if [ -z "${entry}" ]; then - >&2 printf \ -'%s: the %s directory of the %s file is not a valid menu entry '\ -'(see menu.tsv)\n' "${0##*/}" "${section}" "$1" - exit 1 -fi - -label="$(echo "${entry}" | cut -d' ' -f1)" - -if ! [ -e "${section}/index.tsv" ]; then - >&2 printf \ - '%s: unable to find the index.tsv file in the directory %s\n' \ - "${0##*/}" "${section}" - exit 1 -fi - -# Define whether the entry corresponds to a subsection index, i.e., -# whether it is the file to be displayed when entering the subsection. -content="$(basename "$1")" -subentry="$(indexed_content < "${worktree}/${section}/index.tsv" \ - | sed -n "/\t${content}/p")" - -if [ -n "${subentry}" ]; then - lang="$(echo "${subentry}" | cut -d' ' -f3 | cut -d':' -f1)" -fi - -lang="${lang:-en}" -root="$(relpath_to_worktree "$1")" - -print_head -print_menu1 -print_menu2 - -printf '<div id="content">\n' diff --git a/hooks.sh b/hooks.sh @@ -1,111 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -. "./meso-web.sh" - -set -e - - -# Print on standard output the Makefile targets used to automate hook -# management - -shtml="$(sh ./list.sh shtml)" -hook="$(sh ./list.sh hook)" - -sections | while read -r i; do - shtml_section="$(printf '%s\n' "${shtml}" \ - | sed -n "/^${i}\//p" | tr '\n' ' ')" - hook_section="$(printf '%s\n' "${hook}" \ - | sed -n "/^${i}\//p" | tr '\n' ' ' \ - | sed -e 's/\.sh[[:space:]]/.hook /g')" - - # Define Makefile target that makes section hooks prerequisites for - # the HTML content of the section. - # - # It is the files generated by each of the hooks that are - # prerequisites for the HTML files, not the scripts of the hooks - # themselves, because even if the scripts have not changed, their - # output may have been updated, which can impact the HTML content - # generated at build time. - printf '%s: %s\n' "${shtml_section}" "${hook_section}" -done - -printf '%s\n' "${hook}" | while read -r i; do - # Divide the path into two parts: - # - the top-level directory, i.e. the section - # - the shell script to be executed from the section directory - section="${i%%/*}" - hook="${i##"${section}"/}" - - # The hook is the first one in the current section: it has the highest - # priority and therefore has no prerequisites. - if [ "${section}" != "${prev_section}" ]; then - dep="" - fi - - # Define a name for the hook used as a prefix for Makefile targets in - # order to automate its execution and the management of the file it - # generates. To ensure that this name is unique, and thus avoid - # conflicts between different hooks, it is constructed from the names - # of the section and file corresponding to the hook. - file="$(basename "${hook}")" - prefix="${section}-${file%%.*}" - - # The hook name begins with 'xx-', meaning that it does not depend on - # any other hook in the section. - if echo "${file}" | grep -qe '^xx-.*'; then - dep="" - fi - - # Set the file in which the names of the files generated by the hook - # are stored as resources for the website, i.e., the files that must - # be deployed with the website. - tgt="${i%%.*}.hook" - - # Define the Makefile target that automate the hook executation. Its - # pre-requisites are the hook script and the output of the # previous - # hook in the section, i.e. with an higher priority. So that - # execution priority is ensured. - # - # Finally, make this target a prerequisite for building the website - # in order to enforce its execution during the build call. - printf '%s: %s %s\n' "${tgt}" "${i}" "${dep}" - printf " @( cd -- %s && \$(SHELL) %s ) > \$@\n" \ - "${section}" "${hook}" - - # Set the target for cleaning files generated by executing the hook. - # Run it on "distclean" and not on "clean", as their generation can be - # costly while effectively being files generated to "distribute" the - # website. - printf '%s-clean:\n' "${prefix}" - printf ' if [ -f %s ]; then cat %s | xargs rm -f; fi\n' \ - "${tgt}" "${tgt}" - printf ' rm -f %s\n' "${tgt}" - printf 'distclean__: %s-clean\n' "${prefix}" - - # Set the target that installs website resources generated by the hook - printf '%s-install: %s\n' "${prefix}" "${tgt}" - printf " @rsync --mkpath -avzrR --files-from=%s ./ \$(PREFIX)\n" \ - "${tgt}" - printf 'install__: %s-install\n' "${prefix}" - - # Ensure that the target of the hook is a prerequisite for the next - # hook in the section, so that the execution order follows their - # priority as defined by their file name. - dep="${tgt}" - prev_section="${section}" -done diff --git a/index.sh b/index.sh @@ -1,33 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -. "./meso-web.sh" - -set -e - -# Print to standard output the Makefile targets that make the section -# index file a prerequisite for the section's HTML content. - -html="$(sh ./list.sh html)" - -sections | while read -r i; do - html_section="$(printf '%s\n' "${html}" \ - | sed -n "/^${i}\//p" \ - | tr '\n' ' ')" - - printf '%s: %s/index.tsv\n' "${html_section}" "${i}" -done diff --git a/list.sh b/list.sh @@ -1,114 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -. "./meso-web.sh" - -set -e - -if [ "$#" -lt 1 ]; then - >&2 printf 'usage: %s <html|hook|shell|sig>\n' "${0##*/}" - exit 1 -fi - -######################################################################## -# Helper functions -######################################################################## -# List of HTML files to generate from Markdown files or shell scripts -# stored in each section -html() -{ - _find_args="$(\ - printf '%s\n' "${sections}" \ - | sed -e 's/^/! -path /' \ - | tr '\n' ' ')" - - eval "exec find ${search_dirs} ${_find_args} -type d -prune -o \ - \( \ - -name \"*.md\" \ - -o -name \"*.sh\" \ - \) -exec sh -c 'printf \"%s.html\n\" \"\${1%.*}\"' -- {} \; \ - | sort" -} - -# List of shell scripts that dynamically generate HTML content -shtml() -{ - _find_args="$(\ - printf '%s\n' "${sections}" \ - | sed -e 's/^/! -path /' \ - | tr '\n' ' ')" - - eval "exec find ${search_dirs} ${_find_args} -type d -prune -o \ - -name \"*.sh\" -print \ - | sort" -} - -# List of hooks, i.e. shell scripts to be run by section -hook() -{ - _find_args="$(\ - printf '%s\n' "${sections}" \ - | sed -e 's/^/-path "/;s/$/\/hooks\/*" -o/' \ - | tr '\n' ' ' \ - | sed 's/ -o $//')" - - eval "find ${search_dirs} \ - \( \( ${_find_args} \) -type f -name \"*.sh\" \) \ - | sort" -} - -# List the shell scripts relevant to the compilation system, i.e. the -# shell script at the root of the working tree and those in each section -# used to generate HTML pages. -shell() -{ - _find_args="$(\ - printf '%s\n' "${sections}" \ - | sed -e 's/^\(.\{0,\}\)$/! -path \1 ! -path \1\/hooks/' \ - | tr '\n' ' ')" - - eval "exec find . ${search_dirs} \ - ! -path . ${_find_args} -type d -prune -o -name \"*.sh\" -print \ - | sort" -} - -# List the relevent section subdirectories which are: -# - downloads -# - images -# - thumbs -subdir() -{ - downloads="-path \1/downloads" - images="-path \1/images -o -path \1/thumbs" - - _find_args="$(\ - printf '%s\n' "${sections}" \ - | sed "s;^\(.\{0,\}\)$;${downloads} -o ${images} -o;" \ - | tr '\n' ' ' \ - | sed 's/ -o $//')" - - eval "exec find ${search_dirs} ${_find_args} -type d | sort" -} - -######################################################################## -# Script -######################################################################## -# List of sections to be dealt with -sections="$(sections)" -search_dirs="$(printf '%s\n' "${sections}" | tr '\n' ' ')" - -"$@" diff --git a/schiff/hooks/01-generate-man.sh b/schiff/hooks/01-generate-man.sh @@ -32,8 +32,8 @@ man2html() # output_filename { { cd .. - sh ./generate_header.sh "${OLDPWD##*/}/$1" - sh ./convert_man.sh + sh ./scripts/generate_header.sh "${OLDPWD##*/}/$1" + sh ./scripts/convert_man.sh cat ./footer.html cd "${OLDPWD}" } > "$1" diff --git a/schiff/schiff-downloads.sh b/schiff/schiff-downloads.sh @@ -16,7 +16,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. . "./config.sh.in" -. "../meso-web.sh" +. "../scripts/meso-web.sh" set -e diff --git a/convert_man.sh b/scripts/convert_man.sh diff --git a/scripts/generate_header.sh b/scripts/generate_header.sh @@ -0,0 +1,256 @@ +#!/bin/sh + +# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -e + +. "./scripts/meso-web.sh" + +######################################################################## +# Helper functions +######################################################################## +# Print the absolute dir of the input file +absdir() # file +{ + cd -- "$(dirname "$1")" && pwd + cd "${OLDPWD}" +} + +# List the indexed content in TSV format. Each line contains the index +# label, followed by the indexed content, and possibly an indicator of +# the language used. +# +# The input data is the content of an index.tsv file, submitted on +# standard input. +indexed_content() +( + strip_dummy | while read -r _line; do + _langs="$(echo "${_line}" | cut -d' ' -f3)" + + if [ -z "${_langs}" ]; then + # There is no lang field defined: print the line as it + printf '%s\n' "${_line}" + + else + # The lang field is defined. Duplicate the line as many times as + # there are languages listed. Define the content URI by replacing + # the @LANG@ string with the language value. + echo "${_langs}" \ + | sed 's/:/\n/g' \ + | while read -r _translation; do + echo "${_line}" \ + | sed -e "s/\t[^\t]\{1,\}$/\t${_translation}/g" \ + -e "s/@LANG@/${_translation}/g" + done + fi + done +) + +# Print relative path from input file to worktree +relpath_to_worktree() # file +( + # Build directory from worktree to path + _dir="$(absdir "$1")" + _dir="$(printf '%s\n' "${_dir}" | sed "s;^${worktree}[/]\{0,\};;g")" + + # Ensure that the directory if a subpath of the worktree + if ! [ -d "${_dir}" ]; then + return 1 + fi + + echo "${_dir}" | sed 's/\//\n/g' | while read -r _i; do + printf "../" + done +) + +print_head() +{ + printf '<!DOCTYPE html>\n' + printf '<html lang="%s">\n' "${lang}" + printf '<head>\n' + printf ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n' + printf ' <meta name="viewport" content="width=device-width, initial-scale=1">\n' + printf ' <title>|M|S> %s</title>\n' "${label}" + printf ' <link rel="stylesheet" title="default" href="%smeso.css">\n' "${root}" + printf '</head>\n' + printf '<body>\n' +} + +# Print top-level menu +print_menu1() +( + printf '<div id="menu">\n' + + _separator="" + strip_dummy < "${worktree}/menu.tsv" | while read -r _i; do + + # Retrieve the menu label and its associated directory + _label="$(echo "${_i}" | cut -d' ' -f1)" + _directory="$(echo "${_i}" | cut -d' ' -f2)" + + echo "${_separator}" && _separator=' &emsp13;|&emsp13;' + + if [ "${_directory}" = "${section}" ]; then + printf ' %s\n' "${_label}" + + else + # Get the default page of the section, i.e., the first entry in + # its index. The menu is a link to it. + _uri="$(indexed_content < "${worktree}/${_directory}/index.tsv" \ + | head -1 | cut -d' ' -f2)" + + printf ' <a href="%s%s/%s">%s</a>\n' \ + "${root}" "${_directory}" "${_uri}" "${_label}" + fi + done + + printf '</div>\n<hr>\n' +) + +# Print the list of translation choices +# Available langs are submitted on standard input +print_translations() # uri_template (i.e. URI generic to the lang) +( + _uri_template="$1" + + printf ' <span style="float: right;">\n' + + _separator="" + while read -r _lang; do + + _translation="$(echo "${_uri_template}" | sed "s/@LANG@/${_lang}/g")" + + echo "${_separator}" && _separator=' &emsp13;/&emsp13;' + + if [ "${content}" = "${_translation}" ]; then + printf ' <span class="cur">%s</span>\n' "${_lang}" + else + printf ' <a href="%s%s/%s">%s</a>\n' \ + "${root}" "${section}" "${_translation}" "${_lang}" + fi + done + + printf ' </span>\n' +) + +# Print second-level menu +print_menu2() +( + + printf '<div id="sub-menu">\n' + + _separator="" + strip_dummy < "${worktree}/${section}/index.tsv" | while read -r _i; do + + _label="$(echo "${_i}" | cut -d' ' -f1)" + _uri_template="$(echo "${_i}" | cut -d' ' -f2)" + _langs="$(echo "${_i}" | cut -d' ' -f3)" + _lang_default="$(echo "${_langs}" | cut -d ':' -f1)" + + _uri="$(echo "${_uri_template}" | sed "s/@LANG@/${lang}/g")" + + echo "${_separator}" && _separator=' &emsp13;.&emsp13;' + + if [ "${_uri}" = "${content}" ]; then + # This is the current web page + printf ' <span class="cur">%s</span>\n' "${_label}" + + # Print links to translations if available + if [ -n "${_langs}" ]; then + echo "${_langs}" \ + | sed 's/:/\n/g' \ + | print_translations "${_uri_template}" + fi + + elif echo "${_uri}" | grep -qe "^http[s]\{0,1\}://"; then + # The entry links to an http[s] URL + printf ' <a href="%s">%s</a>\n' "${_uri}" "${_label}" + + else + # The entry links to a local web page for the section + _uri="$(echo "${_uri_template}" | sed "s/@LANG@/${_lang_default}/g")" + printf ' <a href="%s%s/%s">%s</a>\n' \ + "${root}" "${section}" "${_uri}" "${_label}" + fi + done + + printf '</div>\n' +) + +######################################################################## +# The script +######################################################################## +if [ "$#" -lt 1 ]; then + >&2 printf 'usage: %s file\n' "${0##*/}" + exit 1 +fi + +# Define the absolute path of the working directory, i.e. the root +# directory of the site, and enter it. +worktree="$(absdir "${0%%/*}")" +cd "${worktree}" + +# Define the section directory where the input file is located, i.e., the +# subdirectory in the working directory. +section="$(absdir "$1")" +section="$(printf '%s\n' "${section}" | sed "s;^${worktree}[/]\{0,\};;g")" +section="${section%%/*}" + +if [ -z "${section}" ]; then + >&2 printf \ + '%s: unable to extract the section directory from file %s\n' \ + "${0##*/}" "$1" + exit 1 +fi + +# Find the menu entry corresponding to the section directory +entry="$(strip_dummy < "${worktree}/menu.tsv" \ + | sed -n "/\t${section}/p")" + +if [ -z "${entry}" ]; then + >&2 printf \ +'%s: the %s directory of the %s file is not a valid menu entry '\ +'(see menu.tsv)\n' "${0##*/}" "${section}" "$1" + exit 1 +fi + +label="$(echo "${entry}" | cut -d' ' -f1)" + +if ! [ -e "${section}/index.tsv" ]; then + >&2 printf \ + '%s: unable to find the index.tsv file in the directory %s\n' \ + "${0##*/}" "${section}" + exit 1 +fi + +# Define whether the entry corresponds to a subsection index, i.e., +# whether it is the file to be displayed when entering the subsection. +content="$(basename "$1")" +subentry="$(indexed_content < "${worktree}/${section}/index.tsv" \ + | sed -n "/\t${content}/p")" + +if [ -n "${subentry}" ]; then + lang="$(echo "${subentry}" | cut -d' ' -f3 | cut -d':' -f1)" +fi + +lang="${lang:-en}" +root="$(relpath_to_worktree "$1")" + +print_head +print_menu1 +print_menu2 + +printf '<div id="content">\n' diff --git a/scripts/hooks.sh b/scripts/hooks.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. "scripts/meso-web.sh" + +set -e + + +# Print on standard output the Makefile targets used to automate hook +# management + +shtml="$(sh ./scripts/list.sh shtml)" +hook="$(sh ./scripts/list.sh hook)" + +sections | while read -r i; do + shtml_section="$(printf '%s\n' "${shtml}" \ + | sed -n "/^${i}\//p" | tr '\n' ' ')" + hook_section="$(printf '%s\n' "${hook}" \ + | sed -n "/^${i}\//p" | tr '\n' ' ' \ + | sed -e 's/\.sh[[:space:]]/.hook /g')" + + # Define Makefile target that makes section hooks prerequisites for + # the HTML content of the section. + # + # It is the files generated by each of the hooks that are + # prerequisites for the HTML files, not the scripts of the hooks + # themselves, because even if the scripts have not changed, their + # output may have been updated, which can impact the HTML content + # generated at build time. + printf '%s: %s\n' "${shtml_section}" "${hook_section}" +done + +printf '%s\n' "${hook}" | while read -r i; do + # Divide the path into two parts: + # - the top-level directory, i.e. the section + # - the shell script to be executed from the section directory + section="${i%%/*}" + hook="${i##"${section}"/}" + + # The hook is the first one in the current section: it has the highest + # priority and therefore has no prerequisites. + if [ "${section}" != "${prev_section}" ]; then + dep="" + fi + + # Define a name for the hook used as a prefix for Makefile targets in + # order to automate its execution and the management of the file it + # generates. To ensure that this name is unique, and thus avoid + # conflicts between different hooks, it is constructed from the names + # of the section and file corresponding to the hook. + file="$(basename "${hook}")" + prefix="${section}-${file%%.*}" + + # The hook name begins with 'xx-', meaning that it does not depend on + # any other hook in the section. + if echo "${file}" | grep -qe '^xx-.*'; then + dep="" + fi + + # Set the file in which the names of the files generated by the hook + # are stored as resources for the website, i.e., the files that must + # be deployed with the website. + tgt="${i%%.*}.hook" + + # Define the Makefile target that automate the hook executation. Its + # pre-requisites are the hook script and the output of the # previous + # hook in the section, i.e. with an higher priority. So that + # execution priority is ensured. + # + # Finally, make this target a prerequisite for building the website + # in order to enforce its execution during the build call. + printf '%s: %s %s\n' "${tgt}" "${i}" "${dep}" + printf " @( cd -- %s && \$(SHELL) %s ) > \$@\n" \ + "${section}" "${hook}" + + # Set the target for cleaning files generated by executing the hook. + # Run it on "distclean" and not on "clean", as their generation can be + # costly while effectively being files generated to "distribute" the + # website. + printf '%s-clean:\n' "${prefix}" + printf ' if [ -f %s ]; then cat %s | xargs rm -f; fi\n' \ + "${tgt}" "${tgt}" + printf ' rm -f %s\n' "${tgt}" + printf 'distclean__: %s-clean\n' "${prefix}" + + # Set the target that installs website resources generated by the hook + printf '%s-install: %s\n' "${prefix}" "${tgt}" + printf " @rsync --mkpath -avzrR --files-from=%s ./ \$(PREFIX)\n" \ + "${tgt}" + printf 'install__: %s-install\n' "${prefix}" + + # Ensure that the target of the hook is a prerequisite for the next + # hook in the section, so that the execution order follows their + # priority as defined by their file name. + dep="${tgt}" + prev_section="${section}" +done diff --git a/scripts/index.sh b/scripts/index.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. "./scripts/meso-web.sh" + +set -e + +# Print to standard output the Makefile targets that make the section +# index file a prerequisite for the section's HTML content. + +html="$(sh ./scripts/list.sh html)" + +sections | while read -r i; do + html_section="$(printf '%s\n' "${html}" \ + | sed -n "/^${i}\//p" \ + | tr '\n' ' ')" + + printf '%s: %s/index.tsv\n' "${html_section}" "${i}" +done diff --git a/scripts/list.sh b/scripts/list.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +# Copyright (C) 2017-2025 |Méso|Star> (contact@meso-star.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. "./scripts/meso-web.sh" + +set -e + +if [ "$#" -lt 1 ]; then + >&2 printf 'usage: %s <html|hook|shell|sig>\n' "${0##*/}" + exit 1 +fi + +######################################################################## +# Helper functions +######################################################################## +# List of HTML files to generate from Markdown files or shell scripts +# stored in each section +html() +{ + _find_args="$(\ + printf '%s\n' "${sections}" \ + | sed -e 's/^/! -path /' \ + | tr '\n' ' ')" + + eval "exec find ${search_dirs} ${_find_args} -type d -prune -o \ + \( \ + -name \"*.md\" \ + -o -name \"*.sh\" \ + \) -exec sh -c 'printf \"%s.html\n\" \"\${1%.*}\"' -- {} \; \ + | sort" +} + +# List of shell scripts that dynamically generate HTML content +shtml() +{ + _find_args="$(\ + printf '%s\n' "${sections}" \ + | sed -e 's/^/! -path /' \ + | tr '\n' ' ')" + + eval "exec find ${search_dirs} ${_find_args} -type d -prune -o \ + -name \"*.sh\" -print \ + | sort" +} + +# List of hooks, i.e. shell scripts to be run by section +hook() +{ + _find_args="$(\ + printf '%s\n' "${sections}" \ + | sed -e 's/^/-path "/;s/$/\/hooks\/*" -o/' \ + | tr '\n' ' ' \ + | sed 's/ -o $//')" + + eval "find ${search_dirs} \ + \( \( ${_find_args} \) -type f -name \"*.sh\" \) \ + | sort" +} + +# List the shell scripts relevant to the compilation system, i.e. the +# shell script at the root of the working tree and those in each section +# used to generate HTML pages. +shell() +{ + _find_args="$(\ + printf '%s\n' "${sections}" \ + | sed -e 's/^\(.\{0,\}\)$/! -path \1 ! -path \1\/hooks/' \ + | tr '\n' ' ')" + + eval "exec find scripts ${search_dirs} \ + ! -path scripts ${_find_args} -type d -prune -o -name \"*.sh\" -print \ + | sort" +} + +# List the relevent section subdirectories which are: +# - downloads +# - images +# - thumbs +subdir() +{ + downloads="-path \1/downloads" + images="-path \1/images -o -path \1/thumbs" + + _find_args="$(\ + printf '%s\n' "${sections}" \ + | sed "s;^\(.\{0,\}\)$;${downloads} -o ${images} -o;" \ + | tr '\n' ' ' \ + | sed 's/ -o $//')" + + eval "exec find ${search_dirs} ${_find_args} -type d | sort" +} + +######################################################################## +# Script +######################################################################## +# List of sections to be dealt with +sections="$(sections)" +search_dirs="$(printf '%s\n' "${sections}" | tr '\n' ' ')" + +"$@" diff --git a/meso-web.sh b/scripts/meso-web.sh diff --git a/solstice/hooks/01-generate-man.sh b/solstice/hooks/01-generate-man.sh @@ -32,8 +32,8 @@ man2html() # output_filename { { cd .. - sh ./generate_header.sh "${OLDPWD##*/}/$1" - sh ./convert_man.sh + sh ./scripts/generate_header.sh "${OLDPWD##*/}/$1" + sh ./scripts/convert_man.sh cat ./footer.html cd "${OLDPWD}" } > "$1" diff --git a/solstice/solstice-downloads.sh b/solstice/solstice-downloads.sh @@ -16,7 +16,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. . "./config.sh.in" -. "../meso-web.sh" +. "../scripts/meso-web.sh" set -e