addpage 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #!/bin/bash
  2. #
  3. # addpage
  4. #
  5. # Page addition helper for the Dragora GNU/Linux-Libre website
  6. # (https://www.dragora.org)
  7. #
  8. #
  9. # Copyright (C) 2021 Michael Siegel
  10. #
  11. # Licensed under the Apache License, Version 2.0 (the "License");
  12. # you may not use this file except in compliance with the License.
  13. # You may obtain a copy of the License at
  14. #
  15. # http://www.apache.org/licenses/LICENSE-2.0
  16. #
  17. # Unless required by applicable law or agreed to in writing, software
  18. # distributed under the License is distributed on an "AS IS" BASIS,
  19. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. # See the License for the specific language governing permissions and
  21. # limitations under the License.
  22. #### INCLUDES ####
  23. . include/constants || exit 1
  24. . include/subroutines || exit 1
  25. #### CONSTANTS ####
  26. #### GLOBAL PARAMETERS ####
  27. pg_basedir=
  28. pg_dir=
  29. pg_prefixdir=
  30. pg_title=
  31. in_nav=
  32. nav_slot=
  33. nav_direction=
  34. #### FUNCTIONS ####
  35. ## Retrievers
  36. _show_navtree() {
  37. local -r index_start=0
  38. local indent=
  39. local item=
  40. local line_mark=
  41. local prefix="${1}/"
  42. local -r index_end="$(("${#navtree[@]}" - 1))"
  43. local -r index_width="${#index_end}"
  44. _get_tree_flow "${navtree[@]}" # _mk_tree_item_indent needs this
  45. local i=
  46. for ((i="$index_start"; i<="$index_end"; ++i))
  47. do
  48. if [[ "$i" -eq 0 ]] # Beware that this requires the start page to always
  49. # be the first in the site navigation.
  50. then
  51. item='[home page]'
  52. else
  53. item="${navtree[i]}"
  54. fi
  55. indent="$(_mk_tree_item_indent "$item" "$i")"
  56. if [[ "$item" = "$prefix" ]]
  57. then
  58. line_mark='* '
  59. else
  60. line_mark=' '
  61. fi
  62. item="${item%/}"
  63. printf "%s%${index_width}s %s%s%s\n" "$line_mark" "$i" "$indent" \
  64. "${item##*/}"
  65. done
  66. unset i
  67. }
  68. ## User queries and input parsers
  69. _prompt_basedir() {
  70. local input=
  71. while true
  72. do
  73. if [[ -z "$input" ]]
  74. then
  75. printf '%s\n' 'Please provide a directory name for the new page to add.'
  76. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  77. fi
  78. read -rp "$PROMPT" input
  79. if [[ -z "$input" ]]
  80. then
  81. continue
  82. elif [[ "$input" = "$HELP_COMMAND" ]]
  83. then
  84. _show_help "$FUNCNAME"
  85. elif [[ ! "$input" =~ ^[abcdefghijklmnopqrstuvwxyz0123456789_]+$ ]]
  86. then
  87. _perr "invalid directory name -- '$input'"
  88. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  89. else
  90. break
  91. fi
  92. done
  93. pg_basedir="$input"
  94. }
  95. _prompt_title() {
  96. local input=
  97. while true
  98. do
  99. if [[ -z "$input" ]]
  100. then
  101. printf '%s\n' 'Please provide a title for the new page.'
  102. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  103. fi
  104. read -rp "$PROMPT" input
  105. if [[ -z "$input" ]]
  106. then
  107. continue
  108. elif [[ "$input" = "$HELP_COMMAND" ]]
  109. then
  110. _show_help "$FUNCNAME"
  111. else
  112. break
  113. fi
  114. done
  115. # Currently, $pg_title may contain anything but a newline.
  116. # Apply further restrictions: The only whitespace character allowed shall be
  117. # space.
  118. pg_title="$input"
  119. }
  120. _prompt_prefixdir() {
  121. local input=
  122. while true
  123. do
  124. if [[ -z "$input" ]]
  125. then
  126. printf '%s\n' 'Please select where you want the new page to be placed:'
  127. _show_pagetree -add
  128. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  129. fi
  130. read -rp "$PROMPT" input
  131. if [[ -z "$input" ]]
  132. then
  133. continue
  134. elif [[ "$input" = "$HELP_COMMAND" ]]
  135. then
  136. _show_help "$FUNCNAME"
  137. elif [[ ! "$input" =~ ^[0123456789]+$ ]]
  138. then
  139. _perr "invalid selection -- '$input'"
  140. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  141. else
  142. if [[ ! "$input" -lt "${#pagetree[@]}" ]]
  143. then
  144. _perr "invalid selection -- '$input'"
  145. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  146. else
  147. break
  148. fi
  149. fi
  150. done
  151. [[ "$input" -ne 0 ]] && pg_prefixdir="${pagetree["$input"]%/}"
  152. }
  153. _prompt_putnav() {
  154. local input=
  155. while true
  156. do
  157. if [[ -z "$input" ]]
  158. then
  159. printf '%s\n' \
  160. 'Do you want the new page to appear in the site navigation? [y/n]'
  161. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  162. fi
  163. read -rp "$PROMPT" input
  164. if [[ -z "$input" ]]
  165. then
  166. continue
  167. elif [[ "$input" = "$HELP_COMMAND" ]]
  168. then
  169. _show_help "$FUNCNAME"
  170. elif [[ ! "$input" =~ ^y|n$ ]]
  171. then
  172. _perr "invalid input -- '$input'"
  173. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  174. else
  175. break
  176. fi
  177. done
  178. case "$input" in
  179. y)
  180. in_nav=1
  181. ;;
  182. n)
  183. in_nav=0
  184. ;;
  185. esac
  186. }
  187. _prompt_navplace() {
  188. local input=
  189. while true
  190. do
  191. if [[ -z "$input" ]]
  192. then
  193. printf '%s\n' \
  194. 'Where in the site navigation do you want the new page to appear?'
  195. _show_navtree "$pg_prefixdir"
  196. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  197. fi
  198. read -rp "$PROMPT" input
  199. if [[ -z "$input" ]]
  200. then
  201. continue
  202. elif [[ "$input" = "$HELP_COMMAND" ]]
  203. then
  204. _show_help "$FUNCNAME"
  205. elif [[ "${#input}" -lt 2 || ! "$input" =~ ^b|a[0-9]+$ ]]
  206. then
  207. _perr "invalid selection -- '$input'"
  208. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  209. elif [[ ! "${input:1}" -lt "${#navtree[@]}" ]]
  210. then
  211. _perr "invalid selection -- '$input'"
  212. printf '%s\n' "$HELP_TIP_INTERACTIVE"
  213. else
  214. break
  215. fi
  216. done
  217. nav_slot="${input:1}" # just the number
  218. nav_direction="${input:0:1}" # just the letter
  219. }
  220. _set_pagedir() {
  221. if [[ -z "$pg_prefixdir" ]]
  222. then
  223. pg_dir="$pg_basedir"
  224. else
  225. pg_dir="$pg_prefixdir/$pg_basedir"
  226. fi
  227. }
  228. ## Checks
  229. _probe_pagedir() {
  230. if [[ -e "$PAGES_DIR_MASTER/$pg_dir" ]]
  231. then
  232. _perr "Page directory '$pg_dir' already exists."
  233. return 1
  234. fi
  235. }
  236. ## Actions
  237. _add_page() {
  238. local pg_dir_full=
  239. local pg_file="$SOURCE_PAGE_FILENAME"
  240. local lang_dir=
  241. for lang_dir in $(_get_lang_dirs)
  242. do
  243. pg_dir_full="$PAGES_DIR/$lang_dir/$pg_dir"
  244. mkdir -p -- "$pg_dir_full" || return 1
  245. printf '%s\n\n%s' \
  246. "<!--PAGETITLE:${pg_title}-->" "<h2>$pg_title</h2>" \
  247. > "$pg_dir_full/$pg_file" || return 1
  248. printf '%s\n' "Added page '$pg_dir_full/$pg_file'."
  249. unset pg_dir_full
  250. done
  251. unset lang_dir
  252. }
  253. _add_page_nav() {
  254. local nav_slot_lnum=0
  255. local prefix=
  256. [[ -z "$nav_direction" ]] && nav_direction=a
  257. if [[ -z "$nav_slot" ]]
  258. then
  259. prefix="${pg_prefixdir}/"
  260. else
  261. prefix="${navtree[$nav_slot]}"
  262. fi
  263. local line=
  264. # Find the line number of "$prefix" in $NAVTREE_FILE
  265. while read -r line
  266. do
  267. [[ "$line" = "$prefix" ]] && break
  268. ((++nav_slot_lnum))
  269. done < "$NAVTREE_FILE"
  270. unset line
  271. cp -a -- "$NAVTREE_FILE" "${NAVTREE_FILE}.old"
  272. case "$nav_direction" in
  273. b)
  274. sed -- "$nav_slot_lnum a\\$pg_dir/" "$NAVTREE_FILE" \
  275. > "$TMP_DIR/navtree"
  276. ;;
  277. a)
  278. ((++nav_slot_lnum))
  279. sed -- "$nav_slot_lnum a\\$pg_dir/" "$NAVTREE_FILE" \
  280. > "$TMP_DIR/navtree"
  281. ;;
  282. esac
  283. mv -- "$TMP_DIR/navtree" "$NAVTREE_FILE"
  284. printf '%s\n' "Added '$pg_dir' to site navigation."
  285. }
  286. _show_help() {
  287. case "$1" in
  288. _prompt_basedir)
  289. cat <<'EOF'
  290. Page directory names may only contain lowercase ASCII letters (a-z), ASCII
  291. digits (0-9), and the underscore (_).
  292. EOF
  293. ;;
  294. _prompt_prefixdir)
  295. cat <<'EOF'
  296. Simply enter the number corresponding to the path into which you want the new
  297. page to be placed, or `0` to create a new top-level page.
  298. EOF
  299. ;;
  300. # _prompt_putnav)
  301. # :
  302. # ;;
  303. _prompt_navplace)
  304. cat <<'EOF'
  305. Please select the desired slot number and indicate whether the new page shall
  306. be inserted before or after the chosen slot, by putting either `b` (before) or
  307. `a` (after) infront of the slot number -- e.g., `a2`, to insert after the
  308. second slot.
  309. EOF
  310. ;;
  311. global)
  312. cat <<'EOF'
  313. Add a page interactively
  314. Usage:
  315. addpage
  316. Options:
  317. --help
  318. Show this help text and exit
  319. EOF
  320. ;;
  321. *)
  322. printf '%s\n' "Sorry, no help text available."
  323. ;;
  324. esac
  325. }
  326. #### MAIN ####
  327. if [[ "$1" = '--help' ]]
  328. then
  329. _show_help global
  330. exit
  331. fi
  332. ## Environment checks
  333. _env_checks || _abort
  334. ## Action
  335. _get_pagetree
  336. _get_navtree
  337. _prompt_prefixdir
  338. while true
  339. do
  340. _prompt_basedir
  341. _set_pagedir
  342. _probe_pagedir && break
  343. done
  344. _prompt_title
  345. _prompt_putnav
  346. if [[ "$in_nav" -eq 1 ]] && \
  347. [[ "$(find "${PAGES_DIR_MASTER}/$pg_prefixdir" -type d | wc -l)" -gt 1 ]]
  348. then
  349. _prompt_navplace
  350. fi
  351. _add_page || _abort
  352. [[ "$in_nav" -eq 1 ]] && _add_page_nav