anything-scripts

Disposable scripts to fix day to day problems.
Log | Files | Refs

commit 0792ed229c8082e27cc6290c853998acfa0c86d8
Author: Hugo Soucy <hugo@soucy.cc>
Date:   Sun,  7 Feb 2021 14:32:36 -0500

First commit for the self-hosted repo.

Diffstat:
A.gitignore | 1+
Aextract-hex-colors-from-css/.gitignore | 1+
Aextract-hex-colors-from-css/src/hexcolors-extractor.mustache | 17+++++++++++++++++
Aextract-hex-colors-from-css/src/hexcolors-extractor.sh | 29+++++++++++++++++++++++++++++
Aextract-hex-colors-from-css/src/hexcolors.data | 9+++++++++
Aextract-hex-colors-from-css/src/mo | 1046+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Affmpeg-mov-to-mp4 | 18++++++++++++++++++
Aget-svg-sizes-to-css-class | 26++++++++++++++++++++++++++
Ahttpd | 16++++++++++++++++
Amanuelfile | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anpm-scripts/README.md | 1+
Anpm-scripts/imgoptim.sh | 2++
Anpm-scripts/lint.sh | 2++
Anpm-scripts/prefix.sh | 2++
Anpm-scripts/scss.sh | 8++++++++
Anpm-scripts/svg/.svgdest | 0
Anpm-scripts/svg/.svgoconf.yml | 43+++++++++++++++++++++++++++++++++++++++++++
Anpm-scripts/svg/README.md | 1+
Anpm-scripts/svg/svg-optim.sh | 22++++++++++++++++++++++
Anpm-scripts/svg/svg-sprite.sh | 1+
Anpm-scripts/svg/svg.sh | 1+
Anpm-scripts/uglify.sh | 2++
Anpm-scripts/watch.sh | 2++
Aposse | 24++++++++++++++++++++++++
Apreprocess_css | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apreprocess_javascript | 22++++++++++++++++++++++
Areload-browser | 44++++++++++++++++++++++++++++++++++++++++++++
Ashortlinks | 19+++++++++++++++++++
Ashortlinks.db | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aupdate-web-projects | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30 files changed, 1686 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +/projectlist diff --git a/extract-hex-colors-from-css/.gitignore b/extract-hex-colors-from-css/.gitignore @@ -0,0 +1 @@ +hexcolors.html diff --git a/extract-hex-colors-from-css/src/hexcolors-extractor.mustache b/extract-hex-colors-from-css/src/hexcolors-extractor.mustache @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <title>{{ NAME }}</title> + </head> + <body> + <div> + {{# COLORS }} + <svg height="200" width="200" viewBox = "0 0 200 200" > + <rect x="0" y="15" width="150" height="150" fill="{{ . }}"/> + <text x="0" y="15">{{ . }}</text> + </svg> + {{/ COLORS }} + </div> + </body> +</html> diff --git a/extract-hex-colors-from-css/src/hexcolors-extractor.sh b/extract-hex-colors-from-css/src/hexcolors-extractor.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +. ./mo + +REPO_PATH="$1" +unset -v COLORS[*] +declare -a COLORS + +[ -f "hexcolors.html" ] && rm "hexcolors.html" + +for css in $(find "$REPO_PATH/" -type f \( -name "*.css" -o -name "*.scss" \)); do + #echo "$css" + + if [[ ! -a "$css" ]]; then + echo "File not found" + exit 1 + fi + + grep -o '\#[0-9a-fA-F]\{3,6\}' "$css" + +done | tr '[:upper:]' '[:lower:]' | sort -n | uniq > "hexcolors.data" + +while read -r line ; do + echo "Processing ${line}" + + COLORS+=("${line}") +done < "hexcolors.data" + +mo "hexcolors-extractor.mustache" > "hexcolors.html" diff --git a/extract-hex-colors-from-css/src/hexcolors.data b/extract-hex-colors-from-css/src/hexcolors.data @@ -0,0 +1,9 @@ +#000 +#0000ff +#111111 +#333333 +#c0c0c0 +#ccc +#cccccc +#f1f1f1 +#ff0 diff --git a/extract-hex-colors-from-css/src/mo b/extract-hex-colors-from-css/src/mo @@ -0,0 +1,1046 @@ +#!/usr/bin/env bash +# +#/ Mo is a mustache template rendering software written in bash. It inserts +#/ environment variables into templates. +#/ +#/ Simply put, mo will change {{VARIABLE}} into the value of that +#/ environment variable. You can use {{#VARIABLE}}content{{/VARIABLE}} to +#/ conditionally display content or iterate over the values of an array. +#/ +#/ Learn more about mustache templates at https://mustache.github.io/ +#/ +#/ Simple usage: +#/ +#/ mo [--false] [--help] [--source=FILE] filenames... +#/ +#/ --fail-not-set - Fail upon expansion of an unset variable. +#/ --false - Treat the string "false" as empty for conditionals. +#/ --help - This message. +#/ --source=FILE - Load FILE into the environment before processing templates. +# +# Mo is under a MIT style licence with an additional non-advertising clause. +# See LICENSE.md for the full text. +# +# This is open source! Please feel free to contribute. +# +# https://github.com/tests-always-included/mo + + +# Public: Template parser function. Writes templates to stdout. +# +# $0 - Name of the mo file, used for getting the help message. +# --allow-function-arguments +# - Permit functions in templates to be called with additional +# arguments. This puts template data directly in to the path +# of an eval statement. Use with caution. +# --fail-not-set - Fail upon expansion of an unset variable. Default behavior +# is to silently ignore and expand into empty string. +# --false - Treat "false" as an empty value. You may set the +# MO_FALSE_IS_EMPTY environment variable instead to a non-empty +# value to enable this behavior. +# --help - Display a help message. +# --source=FILE - Source a file into the environment before processint +# template files. +# -- - Used to indicate the end of options. You may optionally +# use this when filenames may start with two hyphens. +# $@ - Filenames to parse. +# +# Mo uses the following environment variables: +# +# MO_ALLOW_FUNCTION_ARGUMENTS +# - When set to a non-empty value, this allows functions +# referenced in templates to receive additional +# options and arguments. This puts the content from the +# template directly into an eval statement. Use with +# extreme care. +# MO_FAIL_ON_UNSET - When set to a non-empty value, expansion of an unset +# env variable will be aborted with an error. +# MO_FALSE_IS_EMPTY - When set to a non-empty value, the string "false" +# will be treated as an empty value for the purposes +# of conditionals. +# MO_ORIGINAL_COMMAND - Used to find the `mo` program in order to generate +# a help message. +# +# Returns nothing. +mo() ( + # This function executes in a subshell so IFS is reset. + # Namespace this variable so we don't conflict with desired values. + local moContent f2source files doubleHyphens + + IFS=$' \n\t' + files=() + doubleHyphens=false + + if [[ $# -gt 0 ]]; then + for arg in "$@"; do + if $doubleHyphens; then + # After we encounter two hyphens together, all the rest + # of the arguments are files. + files=("${files[@]}" "$arg") + else + case "$arg" in + -h|--h|--he|--hel|--help|-\?) + moUsage "$0" + exit 0 + ;; + + --allow-function-arguments) + # shellcheck disable=SC2030 + MO_ALLOW_FUNCTION_ARGUMENTS=true + ;; + + --fail-not-set) + # shellcheck disable=SC2030 + MO_FAIL_ON_UNSET=true + ;; + + --false) + # shellcheck disable=SC2030 + MO_FALSE_IS_EMPTY=true + ;; + + --source=*) + f2source="${arg#--source=}" + + if [[ -f "$f2source" ]]; then + # shellcheck disable=SC1090 + . "$f2source" + else + echo "No such file: $f2source" >&2 + exit 1 + fi + ;; + + --) + # Set a flag indicating we've encountered double hyphens + doubleHyphens=true + ;; + + *) + # Every arg that is not a flag or a option should be a file + files=(${files[@]+"${files[@]}"} "$arg") + ;; + esac + fi + done + fi + + moGetContent moContent "${files[@]}" || return 1 + moParse "$moContent" "" true +) + + +# Internal: Call a function. +# +# $1 - Function to call +# $2 - Content to pass +# $3 - Additional arguments as a single string +# +# This can be dangerous, especially if you are using tags like +# {{someFunction ; rm -rf / }} +# +# Returns nothing. +moCallFunction() { + local moArgs + + moArgs=() + + # shellcheck disable=SC2031 + if [[ -n "${MO_ALLOW_FUNCTION_ARGUMENTS-}" ]]; then + moArgs=$3 + fi + + echo -n "$2" | eval "$1" "$moArgs" +} + + +# Internal: Scan content until the right end tag is found. Creates an array +# with the following members: +# +# [0] = Content before end tag +# [1] = End tag (complete tag) +# [2] = Content after end tag +# +# Everything using this function uses the "standalone tags" logic. +# +# $1 - Name of variable for the array +# $2 - Content +# $3 - Name of end tag +# $4 - If -z, do standalone tag processing before finishing +# +# Returns nothing. +moFindEndTag() { + local content remaining scanned standaloneBytes tag + + #: Find open tags + scanned="" + moSplit content "$2" '{{' '}}' + + while [[ "${#content[@]}" -gt 1 ]]; do + moTrimWhitespace tag "${content[1]}" + + #: Restore content[1] before we start using it + content[1]='{{'"${content[1]}"'}}' + + case $tag in + '#'* | '^'*) + #: Start another block + scanned="${scanned}${content[0]}${content[1]}" + moTrimWhitespace tag "${tag:1}" + moFindEndTag content "${content[2]}" "$tag" "loop" + scanned="${scanned}${content[0]}${content[1]}" + remaining=${content[2]} + ;; + + '/'*) + #: End a block - could be ours + moTrimWhitespace tag "${tag:1}" + scanned="$scanned${content[0]}" + + if [[ "$tag" == "$3" ]]; then + #: Found our end tag + if [[ -z "${4-}" ]] && moIsStandalone standaloneBytes "$scanned" "${content[2]}" true; then + #: This is also a standalone tag - clean up whitespace + #: and move those whitespace bytes to the "tag" element + standaloneBytes=( $standaloneBytes ) + content[1]="${scanned:${standaloneBytes[0]}}${content[1]}${content[2]:0:${standaloneBytes[1]}}" + scanned="${scanned:0:${standaloneBytes[0]}}" + content[2]="${content[2]:${standaloneBytes[1]}}" + fi + + local "$1" && moIndirectArray "$1" "$scanned" "${content[1]}" "${content[2]}" + return 0 + fi + + scanned="$scanned${content[1]}" + remaining=${content[2]} + ;; + + *) + #: Ignore all other tags + scanned="${scanned}${content[0]}${content[1]}" + remaining=${content[2]} + ;; + esac + + moSplit content "$remaining" '{{' '}}' + done + + #: Did not find our closing tag + scanned="$scanned${content[0]}" + local "$1" && moIndirectArray "$1" "${scanned}" "" "" +} + + +# Internal: Find the first index of a substring. If not found, sets the +# index to -1. +# +# $1 - Destination variable for the index +# $2 - Haystack +# $3 - Needle +# +# Returns nothing. +moFindString() { + local pos string + + string=${2%%$3*} + [[ "$string" == "$2" ]] && pos=-1 || pos=${#string} + local "$1" && moIndirect "$1" "$pos" +} + + +# Internal: Generate a dotted name based on current context and target name. +# +# $1 - Target variable to store results +# $2 - Context name +# $3 - Desired variable name +# +# Returns nothing. +moFullTagName() { + if [[ -z "${2-}" ]] || [[ "$2" == *.* ]]; then + local "$1" && moIndirect "$1" "$3" + else + local "$1" && moIndirect "$1" "${2}.${3}" + fi +} + + +# Internal: Fetches the content to parse into a variable. Can be a list of +# partials for files or the content from stdin. +# +# $1 - Variable name to assign this content back as +# $2-@ - File names (optional) +# +# Returns nothing. +moGetContent() { + local content filename target + + target=$1 + shift + if [[ "${#@}" -gt 0 ]]; then + content="" + + for filename in "$@"; do + #: This is so relative paths work from inside template files + content="$content"'{{>'"$filename"'}}' + done + else + moLoadFile content /dev/stdin || return 1 + fi + + local "$target" && moIndirect "$target" "$content" +} + + +# Internal: Indent a string, placing the indent at the beginning of every +# line that has any content. +# +# $1 - Name of destination variable to get an array of lines +# $2 - The indent string +# $3 - The string to reindent +# +# Returns nothing. +moIndentLines() { + local content fragment len posN posR result trimmed + + result="" + + #: Remove the period from the end of the string. + len=$((${#3} - 1)) + content=${3:0:$len} + + if [[ -z "${2-}" ]]; then + local "$1" && moIndirect "$1" "$content" + + return 0 + fi + + moFindString posN "$content" $'\n' + moFindString posR "$content" $'\r' + + while [[ "$posN" -gt -1 ]] || [[ "$posR" -gt -1 ]]; do + if [[ "$posN" -gt -1 ]]; then + fragment="${content:0:$posN + 1}" + content=${content:$posN + 1} + else + fragment="${content:0:$posR + 1}" + content=${content:$posR + 1} + fi + + moTrimChars trimmed "$fragment" false true " " $'\t' $'\n' $'\r' + + if [[ -n "$trimmed" ]]; then + fragment="$2$fragment" + fi + + result="$result$fragment" + + moFindString posN "$content" $'\n' + moFindString posR "$content" $'\r' + + # If the content ends in a newline, do not indent. + if [[ "$posN" -eq ${#content} ]]; then + # Special clause for \r\n + if [[ "$posR" -eq "$((posN - 1))" ]]; then + posR=-1 + fi + + posN=-1 + fi + + if [[ "$posR" -eq ${#content} ]]; then + posR=-1 + fi + done + + moTrimChars trimmed "$content" false true " " $'\t' + + if [[ -n "$trimmed" ]]; then + content="$2$content" + fi + + result="$result$content" + + local "$1" && moIndirect "$1" "$result" +} + + +# Internal: Send a variable up to the parent of the caller of this function. +# +# $1 - Variable name +# $2 - Value +# +# Examples +# +# callFunc () { +# local "$1" && moIndirect "$1" "the value" +# } +# callFunc dest +# echo "$dest" # writes "the value" +# +# Returns nothing. +moIndirect() { + unset -v "$1" + printf -v "$1" '%s' "$2" +} + + +# Internal: Send an array as a variable up to caller of a function +# +# $1 - Variable name +# $2-@ - Array elements +# +# Examples +# +# callFunc () { +# local myArray=(one two three) +# local "$1" && moIndirectArray "$1" "${myArray[@]}" +# } +# callFunc dest +# echo "${dest[@]}" # writes "one two three" +# +# Returns nothing. +moIndirectArray() { + unset -v "$1" + + # IFS must be set to a string containing space or unset in order for + # the array slicing to work regardless of the current IFS setting on + # bash 3. This is detailed further at + # https://github.com/fidian/gg-core/pull/7 + eval "$(printf "IFS= %s=(\"\${@:2}\") IFS=%q" "$1" "$IFS")" +} + + +# Internal: Determine if a given environment variable exists and if it is +# an array. +# +# $1 - Name of environment variable +# +# Be extremely careful. Even if strict mode is enabled, it is not honored +# in newer versions of Bash. Any errors that crop up here will not be +# caught automatically. +# +# Examples +# +# var=(abc) +# if moIsArray var; then +# echo "This is an array" +# echo "Make sure you don't accidentally use \$var" +# fi +# +# Returns 0 if the name is not empty, 1 otherwise. +moIsArray() { + # Namespace this variable so we don't conflict with what we're testing. + local moTestResult + + moTestResult=$(declare -p "$1" 2>/dev/null) || return 1 + [[ "${moTestResult:0:10}" == "declare -a" ]] && return 0 + [[ "${moTestResult:0:10}" == "declare -A" ]] && return 0 + + return 1 +} + + +# Internal: Determine if the given name is a defined function. +# +# $1 - Function name to check +# +# Be extremely careful. Even if strict mode is enabled, it is not honored +# in newer versions of Bash. Any errors that crop up here will not be +# caught automatically. +# +# Examples +# +# moo () { +# echo "This is a function" +# } +# if moIsFunction moo; then +# echo "moo is a defined function" +# fi +# +# Returns 0 if the name is a function, 1 otherwise. +moIsFunction() { + local functionList functionName + + functionList=$(declare -F) + functionList=( ${functionList//declare -f /} ) + + for functionName in "${functionList[@]}"; do + if [[ "$functionName" == "$1" ]]; then + return 0 + fi + done + + return 1 +} + + +# Internal: Determine if the tag is a standalone tag based on whitespace +# before and after the tag. +# +# Passes back a string containing two numbers in the format "BEFORE AFTER" +# like "27 10". It indicates the number of bytes remaining in the "before" +# string (27) and the number of bytes to trim in the "after" string (10). +# Useful for string manipulation: +# +# $1 - Variable to set for passing data back +# $2 - Content before the tag +# $3 - Content after the tag +# $4 - true/false: is this the beginning of the content? +# +# Examples +# +# moIsStandalone RESULT "$before" "$after" false || return 0 +# RESULT_ARRAY=( $RESULT ) +# echo "${before:0:${RESULT_ARRAY[0]}}...${after:${RESULT_ARRAY[1]}}" +# +# Returns nothing. +moIsStandalone() { + local afterTrimmed beforeTrimmed char + + moTrimChars beforeTrimmed "$2" false true " " $'\t' + moTrimChars afterTrimmed "$3" true false " " $'\t' + char=$((${#beforeTrimmed} - 1)) + char=${beforeTrimmed:$char} + + # If the content before didn't end in a newline + if [[ "$char" != $'\n' ]] && [[ "$char" != $'\r' ]]; then + # and there was content or this didn't start the file + if [[ -n "$char" ]] || ! $4; then + # then this is not a standalone tag. + return 1 + fi + fi + + char=${afterTrimmed:0:1} + + # If the content after doesn't start with a newline and it is something + if [[ "$char" != $'\n' ]] && [[ "$char" != $'\r' ]] && [[ -n "$char" ]]; then + # then this is not a standalone tag. + return 2 + fi + + if [[ "$char" == $'\r' ]] && [[ "${afterTrimmed:1:1}" == $'\n' ]]; then + char="$char"$'\n' + fi + + local "$1" && moIndirect "$1" "$((${#beforeTrimmed})) $((${#3} + ${#char} - ${#afterTrimmed}))" +} + + +# Internal: Join / implode an array +# +# $1 - Variable name to receive the joined content +# $2 - Joiner +# $3-$* - Elements to join +# +# Returns nothing. +moJoin() { + local joiner part result target + + target=$1 + joiner=$2 + result=$3 + shift 3 + + for part in "$@"; do + result="$result$joiner$part" + done + + local "$target" && moIndirect "$target" "$result" +} + + +# Internal: Read a file into a variable. +# +# $1 - Variable name to receive the file's content +# $2 - Filename to load +# +# Returns nothing. +moLoadFile() { + local content len + + # The subshell removes any trailing newlines. We forcibly add + # a dot to the content to preserve all newlines. + # As a future optimization, it would be worth considering removing + # cat and replacing this with a read loop. + + content=$(cat -- "$2" && echo '.') || return 1 + len=$((${#content} - 1)) + content=${content:0:$len} # Remove last dot + + local "$1" && moIndirect "$1" "$content" +} + + +# Internal: Process a chunk of content some number of times. Writes output +# to stdout. +# +# $1 - Content to parse repeatedly +# $2 - Tag prefix (context name) +# $3-@ - Names to insert into the parsed content +# +# Returns nothing. +moLoop() { + local content context contextBase + + content=$1 + contextBase=$2 + shift 2 + + while [[ "${#@}" -gt 0 ]]; do + moFullTagName context "$contextBase" "$1" + moParse "$content" "$context" false + shift + done +} + + +# Internal: Parse a block of text, writing the result to stdout. +# +# $1 - Block of text to change +# $2 - Current name (the variable NAME for what {{.}} means) +# $3 - true when no content before this, false otherwise +# +# Returns nothing. +moParse() { + # Keep naming variables mo* here to not overwrite needed variables + # used in the string replacements + local moArgs moBlock moContent moCurrent moIsBeginning moNextIsBeginning moTag + + moCurrent=$2 + moIsBeginning=$3 + + # Find open tags + moSplit moContent "$1" '{{' '}}' + + while [[ "${#moContent[@]}" -gt 1 ]]; do + moTrimWhitespace moTag "${moContent[1]}" + moNextIsBeginning=false + + case $moTag in + '#'*) + # Loop, if/then, or pass content through function + # Sets context + moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" + moTrimWhitespace moTag "${moTag:1}" + + # Split arguments from the tag name. Arguments are passed to + # functions. + moArgs=$moTag + moTag=${moTag%% *} + moTag=${moTag%%$'\t'*} + moArgs=${moArgs:${#moTag}} + moFindEndTag moBlock "$moContent" "$moTag" + moFullTagName moTag "$moCurrent" "$moTag" + + if moTest "$moTag"; then + # Show / loop / pass through function + if moIsFunction "$moTag"; then + #: Consider piping the output to moGetContent + #: so the lambda does not execute in a subshell? + moContent=$(moCallFunction "$moTag" "${moBlock[0]}" "$moArgs") + moParse "$moContent" "$moCurrent" false + moContent="${moBlock[2]}" + elif moIsArray "$moTag"; then + eval "moLoop \"\${moBlock[0]}\" \"$moTag\" \"\${!${moTag}[@]}\"" + else + moParse "${moBlock[0]}" "$moCurrent" true + fi + fi + + moContent="${moBlock[2]}" + ;; + + '>'*) + # Load partial - get name of file relative to cwd + moPartial moContent "${moContent[@]}" "$moIsBeginning" "$moCurrent" + moNextIsBeginning=${moContent[1]} + moContent=${moContent[0]} + ;; + + '/'*) + # Closing tag - If hit in this loop, we simply ignore + # Matching tags are found in moFindEndTag + moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" + ;; + + '^'*) + # Display section if named thing does not exist + moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" + moTrimWhitespace moTag "${moTag:1}" + moFindEndTag moBlock "$moContent" "$moTag" + moFullTagName moTag "$moCurrent" "$moTag" + + if ! moTest "$moTag"; then + moParse "${moBlock[0]}" "$moCurrent" false "$moCurrent" + fi + + moContent="${moBlock[2]}" + ;; + + '!'*) + # Comment - ignore the tag content entirely + # Trim spaces/tabs before the comment + moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" + ;; + + .) + # Current content (environment variable or function) + moStandaloneDenied moContent "${moContent[@]}" + moShow "$moCurrent" "$moCurrent" + ;; + + '=') + # Change delimiters + # Any two non-whitespace sequences separated by whitespace. + # This tag is ignored. + moStandaloneAllowed moContent "${moContent[@]}" "$moIsBeginning" + ;; + + '{'*) + # Unescaped - split on }}} not }} + moStandaloneDenied moContent "${moContent[@]}" + moContent="${moTag:1}"'}}'"$moContent" + moSplit moContent "$moContent" '}}}' + moTrimWhitespace moTag "${moContent[0]}" + moArgs=$moTag + moTag=${moTag%% *} + moTag=${moTag%%$'\t'*} + moArgs=${moArgs:${#moTag}} + moFullTagName moTag "$moCurrent" "$moTag" + moContent=${moContent[1]} + + # Now show the value + # Quote moArgs here, do not quote it later. + moShow "$moTag" "$moCurrent" "$moArgs" + ;; + + '&'*) + # Unescaped + moStandaloneDenied moContent "${moContent[@]}" + moTrimWhitespace moTag "${moTag:1}" + moFullTagName moTag "$moCurrent" "$moTag" + moShow "$moTag" "$moCurrent" + ;; + + *) + # Normal environment variable or function call + moStandaloneDenied moContent "${moContent[@]}" + moArgs=$moTag + moTag=${moTag%% *} + moTag=${moTag%%$'\t'*} + moArgs=${moArgs:${#moTag}} + moFullTagName moTag "$moCurrent" "$moTag" + + # Quote moArgs here, do not quote it later. + moShow "$moTag" "$moCurrent" "$moArgs" + ;; + esac + + moIsBeginning=$moNextIsBeginning + moSplit moContent "$moContent" '{{' '}}' + done + + echo -n "${moContent[0]}" +} + + +# Internal: Process a partial. +# +# Indentation should be applied to the entire partial. +# +# This sends back the "is beginning" flag because the newline after a +# standalone partial is consumed. That newline is very important in the middle +# of content. We send back this flag to reset the processing loop's +# `moIsBeginning` variable, so the software thinks we are back at the +# beginning of a file and standalone processing continues to work. +# +# Prefix all variables. +# +# $1 - Name of destination variable. Element [0] is the content, [1] is the +# true/false flag indicating if we are at the beginning of content. +# $2 - Content before the tag that was not yet written +# $3 - Tag content +# $4 - Content after the tag +# $5 - true/false: is this the beginning of the content? +# $6 - Current context name +# +# Returns nothing. +moPartial() { + # Namespace variables here to prevent conflicts. + local moContent moFilename moIndent moIsBeginning moPartial moStandalone moUnindented + + if moIsStandalone moStandalone "$2" "$4" "$5"; then + moStandalone=( $moStandalone ) + echo -n "${2:0:${moStandalone[0]}}" + moIndent=${2:${moStandalone[0]}} + moContent=${4:${moStandalone[1]}} + moIsBeginning=true + else + moIndent="" + echo -n "$2" + moContent=$4 + moIsBeginning=$5 + fi + + moTrimWhitespace moFilename "${3:1}" + + # Execute in subshell to preserve current cwd and environment + ( + # It would be nice to remove `dirname` and use a function instead, + # but that's difficult when you're only given filenames. + cd "$(dirname -- "$moFilename")" || exit 1 + moUnindented="$( + moLoadFile moPartial "${moFilename##*/}" || exit 1 + moParse "${moPartial}" "$6" true + + # Fix bash handling of subshells and keep trailing whitespace. + # This is removed in moIndentLines. + echo -n "." + )" || exit 1 + moIndentLines moPartial "$moIndent" "$moUnindented" + echo -n "$moPartial" + ) || exit 1 + + # If this is a standalone tag, the trailing newline after the tag is + # removed and the contents of the partial are added, which typically + # contain a newline. We need to send a signal back to the processing + # loop that the moIsBeginning flag needs to be turned on again. + # + # [0] is the content, [1] is that flag. + local "$1" && moIndirectArray "$1" "$moContent" "$moIsBeginning" +} + + +# Internal: Show an environment variable or the output of a function to +# stdout. +# +# Limit/prefix any variables used. +# +# $1 - Name of environment variable or function +# $2 - Current context +# $3 - Arguments string if $1 is a function +# +# Returns nothing. +moShow() { + # Namespace these variables + local moJoined moNameParts + + if moIsFunction "$1"; then + CONTENT=$(moCallFunction "$1" "" "$3") + moParse "$CONTENT" "$2" false + return 0 + fi + + moSplit moNameParts "$1" "." + + if [[ -z "${moNameParts[1]-}" ]]; then + if moIsArray "$1"; then + eval moJoin moJoined "," "\${$1[@]}" + echo -n "$moJoined" + else + # shellcheck disable=SC2031 + if moTestVarSet "$1"; then + echo -n "${!1}" + elif [[ -n "${MO_FAIL_ON_UNSET-}" ]]; then + echo "Env variable not set: $1" >&2 + exit 1 + fi + fi + else + # Further subindexes are disallowed + eval "echo -n \"\${${moNameParts[0]}[${moNameParts[1]%%.*}]}\"" + fi +} + + +# Internal: Split a larger string into an array. +# +# $1 - Destination variable +# $2 - String to split +# $3 - Starting delimiter +# $4 - Ending delimiter (optional) +# +# Returns nothing. +moSplit() { + local pos result + + result=( "$2" ) + moFindString pos "${result[0]}" "$3" + + if [[ "$pos" -ne -1 ]]; then + # The first delimiter was found + result[1]=${result[0]:$pos + ${#3}} + result[0]=${result[0]:0:$pos} + + if [[ -n "${4-}" ]]; then + moFindString pos "${result[1]}" "$4" + + if [[ "$pos" -ne -1 ]]; then + # The second delimiter was found + result[2]="${result[1]:$pos + ${#4}}" + result[1]="${result[1]:0:$pos}" + fi + fi + fi + + local "$1" && moIndirectArray "$1" "${result[@]}" +} + + +# Internal: Handle the content for a standalone tag. This means removing +# whitespace (not newlines) before a tag and whitespace and a newline after +# a tag. That is, assuming, that the line is otherwise empty. +# +# $1 - Name of destination "content" variable. +# $2 - Content before the tag that was not yet written +# $3 - Tag content (not used) +# $4 - Content after the tag +# $5 - true/false: is this the beginning of the content? +# +# Returns nothing. +moStandaloneAllowed() { + local bytes + + if moIsStandalone bytes "$2" "$4" "$5"; then + bytes=( $bytes ) + echo -n "${2:0:${bytes[0]}}" + local "$1" && moIndirect "$1" "${4:${bytes[1]}}" + else + echo -n "$2" + local "$1" && moIndirect "$1" "$4" + fi +} + + +# Internal: Handle the content for a tag that is never "standalone". No +# adjustments are made for newlines and whitespace. +# +# $1 - Name of destination "content" variable. +# $2 - Content before the tag that was not yet written +# $3 - Tag content (not used) +# $4 - Content after the tag +# +# Returns nothing. +moStandaloneDenied() { + echo -n "$2" + local "$1" && moIndirect "$1" "$4" +} + + +# Internal: Determines if the named thing is a function or if it is a +# non-empty environment variable. When MO_FALSE_IS_EMPTY is set to a +# non-empty value, then "false" is also treated is an empty value. +# +# Do not use variables without prefixes here if possible as this needs to +# check if any name exists in the environment +# +# $1 - Name of environment variable or function +# $2 - Current value (our context) +# MO_FALSE_IS_EMPTY - When set to a non-empty value, this will say the +# string value "false" is empty. +# +# Returns 0 if the name is not empty, 1 otherwise. When MO_FALSE_IS_EMPTY +# is set, this returns 1 if the name is "false". +moTest() { + # Test for functions + moIsFunction "$1" && return 0 + + if moIsArray "$1"; then + # Arrays must have at least 1 element + eval "[[ \"\${#${1}[@]}\" -gt 0 ]]" && return 0 + else + # If MO_FALSE_IS_EMPTY is set, then return 1 if the value of + # the variable is "false". + # shellcheck disable=SC2031 + [[ -n "${MO_FALSE_IS_EMPTY-}" ]] && [[ "${!1-}" == "false" ]] && return 1 + + # Environment variables must not be empty + [[ -n "${!1-}" ]] && return 0 + fi + + return 1 +} + +# Internal: Determine if a variable is assigned, even if it is assigned an empty +# value. +# +# $1 - Variable name to check. +# +# Returns true (0) if the variable is set, 1 if the variable is unset. +moTestVarSet() { + [[ "${!1-a}" == "${!1-b}" ]] +} + + +# Internal: Trim the leading whitespace only. +# +# $1 - Name of destination variable +# $2 - The string +# $3 - true/false - trim front? +# $4 - true/false - trim end? +# $5-@ - Characters to trim +# +# Returns nothing. +moTrimChars() { + local back current front last target varName + + target=$1 + current=$2 + front=$3 + back=$4 + last="" + shift 4 # Remove target, string, trim front flag, trim end flag + + while [[ "$current" != "$last" ]]; do + last=$current + + for varName in "$@"; do + $front && current="${current/#$varName}" + $back && current="${current/%$varName}" + done + done + + local "$target" && moIndirect "$target" "$current" +} + + +# Internal: Trim leading and trailing whitespace from a string. +# +# $1 - Name of variable to store trimmed string +# $2 - The string +# +# Returns nothing. +moTrimWhitespace() { + local result + + moTrimChars result "$2" true true $'\r' $'\n' $'\t' " " + local "$1" && moIndirect "$1" "$result" +} + + +# Internal: Displays the usage for mo. Pulls this from the file that +# contained the `mo` function. Can only work when the right filename +# comes is the one argument, and that only happens when `mo` is called +# with `$0` set to this file. +# +# $1 - Filename that has the help message +# +# Returns nothing. +moUsage() { + grep '^#/' "${MO_ORIGINAL_COMMAND}" | cut -c 4- + echo "" + set | grep ^MO_VERSION= +} + + +# Save the original command's path for usage later +MO_ORIGINAL_COMMAND="$(cd "${BASH_SOURCE[0]%/*}" || exit 1; pwd)/${BASH_SOURCE[0]##*/}" +MO_VERSION="2.0.4" + +# If sourced, load all functions. +# If executed, perform the actions as expected. +if [[ "$0" == "${BASH_SOURCE[0]}" ]] || [[ -z "${BASH_SOURCE[0]}" ]]; then + mo "$@" +fi diff --git a/ffmpeg-mov-to-mp4 b/ffmpeg-mov-to-mp4 @@ -0,0 +1,18 @@ +#!/bin/bash + +inputMov=$1 + +if hash ffmpeg 2>/dev/null; then + # If there's no 2nd argument + # use the name of the input + if [ -z "$2" ]; then + outputMpeg="${inputMov%.*}.mp4" + else + outputMpeg=$2 + fi + + ffmpeg -i "$inputMov" -vcodec copy -acodec copy "$outputMpeg" +else + echo "- Sorry But You must Install *ffmpeg*." + echo "- Please Visit <https://ffmpeg.org/>." +fi diff --git a/get-svg-sizes-to-css-class b/get-svg-sizes-to-css-class @@ -0,0 +1,26 @@ +#!/bin/bash + +pth=$1 + +get_svg_sizes_to_css_class () { + svg_location="$pth" + css_file="$(basename $svg_location).css" + + touch "/tmp/$css_file" + + for svg in $(find "$svg_location" -type f \( -name "*.svg" \)); do + svg_width=$(cat "$svg" | ~/go/bin/pup "svg attr{width}") + svg_height=$(cat "$svg" | ~/go/bin/pup "svg attr{height}") + svg_name=$(basename "$svg") + svg_classname="${svg_name%.*}" + + echo ".$svg_classname {" + echo " height: calc-em($svg_height," '$base-size);' + echo " width: calc-em($svg_width," '$base-size);' + echo "}" + echo "" + + done > "/tmp/$css_file" +} + +get_svg_sizes_to_css_class diff --git a/httpd b/httpd @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Open the developpement URL in $BROWSER +# Start the developpement Web server + +# Dependency : +# - https://unix4lyfe.org/darkhttpd + +if hash darkhttpd 2>/dev/null; then + xdg-open "http://localhost:8181" && + + darkhttpd ./public_html --port 8181 +else + echo "- Sorry But You must Install *darkhttpd*." + echo "- Please Visit <https://unix4lyfe.org/darkhttpd/>." +fi diff --git a/manuelfile b/manuelfile @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +# Dependencies : +# - https://github.com/ShaneKilkelly/manuel +# - https://github.com/ShaneKilkelly/manuel-contrib-watch + +# $HOME/.manuel.d/plugins/manuel-contrib-watch +load_plugin manuel-contrib-watch + +# Paths vars +FERRON_PATH=/home/hs0ucy/_01_http/ferron + +SITE_PATH=/home/hs0ucy/_01_http/ferron/sites/hugo.soucy.cc +SITE_DOMAINNAME="hugo.soucy.cc" +SITE_PUBLIC_HTML=public_html +SITE_STATIC_DST=static/dst +SITE_STATIC_SRC=static/src +SITE_TEMPLATES=templates + +# Update partials/cv.mustache +function updatecv () { + # from git@github.com:hs0ucy/Curriculum-vitae.git repository + curl https://raw.githubusercontent.com/hs0ucy/Curriculum-vitae/master/curriculum-vitae.html > "$SITE_TEMPLATES/partials/cv.mustache" +} + +# Concatenate and minify assets +# Then build the static site +function build () { + updatecv && + + ./preprocess_css + ./preprocess_javascript + + case $1 in + -d|--dev) + cd "$FERRON_PATH" && + ./cornelius build --dev + ;; + *) + cd "$FERRON_PATH" && + ./cornelius build + ;; + esac + + echo "- $SITE_DOMAINNAME is builded!" +} + +# Build the static site +# Then deploy it to the web server +function deploy () { + build && + + cd $SITE_PATH + + ./deploy + + echo "- ... and deployed!" +} + +# Concatenate and minify stylesheets +# Then export with rsync +function update_css () { + ./preprocess_css && + + rsync -avmh "$SITE_STATIC_DST/css/" "$SITE_PUBLIC_HTML/css/" +} + +# Concatenate and minify scripts +# Then export with rsync +function update_js () { + ./preprocess_javascript && + + rsync -avmh "$SITE_STATIC_DST/js/" "$SITE_PUBLIC_HTML/js/" +} + +# Watch CSS and JS files +# Then update them +function watch_assets_change () { + + declare -A actions=( + ["*?css"]="update_css" + ["*?js"]="update_js" + ) + + manuel_watch "$SITE_STATIC_SRC/" +} diff --git a/npm-scripts/README.md b/npm-scripts/README.md @@ -0,0 +1 @@ +# Shell SCripts to pass tasks through npm-scripts diff --git a/npm-scripts/imgoptim.sh b/npm-scripts/imgoptim.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +# diff --git a/npm-scripts/lint.sh b/npm-scripts/lint.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +# diff --git a/npm-scripts/prefix.sh b/npm-scripts/prefix.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +# diff --git a/npm-scripts/scss.sh b/npm-scripts/scss.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +if hash sass 2>/dev/null; then + sass --help +else + echo "- Sorry But You must install *SASS* for NodeJs." + echo "- Please execute *sudo npm install -g sass*" +fi diff --git a/npm-scripts/svg/.svgdest b/npm-scripts/svg/.svgdest diff --git a/npm-scripts/svg/.svgoconf.yml b/npm-scripts/svg/.svgoconf.yml @@ -0,0 +1,43 @@ +plugins: + - addAttributesToSVGElement: false + - addClassesToSVGElement: false + - cleanupAttrs: true + - cleanupEnableBackground: true + - cleanupIDs: true + - cleanupListOfValues: true + - cleanupNumericValues: + floatPrecision: 2 + - collapseGroups: true + - convertColors: true + - convertPathData: true + - convertShapeToPath: true + - convertStyleToAttrs: true + - convertTransform: true + - mergePaths: true + - minifyStyles: true + - moveElemsAttrsToGroup: true + - moveGroupAttrsToElems: true + - removeAttrs: true + - removeComments: true + - removeDesc: true + - removeDimensions: true + - removeDoctype: true + - removeEditorsNSData: true + - removeElementsByAttr: true + - removeEmptyAttrs: true + - removeEmptyContainers: true + - removeEmptyText: true + - removeHiddenElems: true + - removeMetadata: true + - removeNonInheritableGroupAttrs: true + - removeRasterImages: true + - removeStyleElement: true + - removeTitle: true + - removeUnknownsAndDefaults: true + - removeUnusedNS: true + - removeUselessDefs: true + - removeUselessStrokeAndFill: true + - removeViewBox: true + - removeXMLNS: false + - removeXMLProcInst: true + - sortAttrs: true diff --git a/npm-scripts/svg/README.md b/npm-scripts/svg/README.md @@ -0,0 +1 @@ +# SVG Scripts for npm-script diff --git a/npm-scripts/svg/svg-optim.sh b/npm-scripts/svg/svg-optim.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Find SVGs then pipes to svgo +# find . -type f -name "*.svg" | svg-optim +# ls "*.svg" | svg-optim +# echo "ico.svg" | svg-optim + +if hash svgo 2>/dev/null; then + # Get the path to this script + thisDir="$(dirname "$(readlink -f "$0")")" + svgoconf="$thisDir/.svgoconf.yml" + + while read -r pathtosvg; do + # Test if mime type is SVG + if [[ $(file -b --mime-type "$pathtosvg") == "image/svg"* ]]; then + svgo "$pathtosvg" --config="$svgoconf" --output="${pathtosvg%.*}.optim.svg" + fi + done +else + echo "- Sorry, But You must Install *svgo*:" + echo "- 'sudo npm install -g svgo'" +fi diff --git a/npm-scripts/svg/svg-sprite.sh b/npm-scripts/svg/svg-sprite.sh @@ -0,0 +1 @@ +#!/usr/bin/env bash diff --git a/npm-scripts/svg/svg.sh b/npm-scripts/svg/svg.sh @@ -0,0 +1 @@ +#!/usr/bin/env bash diff --git a/npm-scripts/uglify.sh b/npm-scripts/uglify.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +# diff --git a/npm-scripts/watch.sh b/npm-scripts/watch.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +# diff --git a/posse b/posse @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# https://indieweb.org/POSSE + +# POSSE to Twitter via Bridgy +# <https://brid.gy/> +# with the Will Norris Webmention app +# <https://willnorris.com/go/webmention> + +unset -v first_db_line + +# Read the first line (last entry) of the fakestache.db +read -r first_db_line < fakestache.db + +# Extract the permalink +last_permalink=$(echo "$first_db_line" | cut -d "|" -f 3) + +# Then send it to the webmention-go app +if hash webmention 2>/dev/null; then + webmention "$last_permalink" +else + echo "- Sorry But You must Install *webmention*." + echo "- Please Visit <https://willnorris.com/go/webmention>." +fi diff --git a/preprocess_css b/preprocess_css @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# CSS Preprocessing Script + +# Include mustache for bash as library +. ~/bin/mo + +CSS_DST_PATH=static/dst/css +CSS_SRC_PATH=static/src/css + +# Convert pixels to EMs +px_to_em () { + pixel_size=$1 + pixel_context=16 + + if [ -n "$2" ]; then + pixel_context=$2 + fi + + echo "$(bc <<< "scale=4;$pixel_size/$pixel_context")em" +} + +# Associative array with breakpoints and sizes in EMs +declare -A BREAKPOINTS + +BREAKPOINTS=( + [xxs]=$(px_to_em 360) + [xs]=$(px_to_em 520) + [sm]=$(px_to_em 768) + [md]=$(px_to_em 992) + [lg]=$(px_to_em 1140) +) + +# You must install "Minify CLI" for running this script : +# <https://github.com/tdewolff/minify/tree/master/cmd/minify> +if hash minify 2>/dev/null; then + # CSS Concatenation + cat "$CSS_SRC_PATH/global/fonts.css" \ + "$CSS_SRC_PATH/global/normalize.css" \ + "$CSS_SRC_PATH/global/abstractions.css" \ + "$CSS_SRC_PATH/global/base.css" \ + "$CSS_SRC_PATH/global/helpers.css" \ + "$CSS_SRC_PATH/global/grid.css" \ + "$CSS_SRC_PATH/modules/"*.css \ + > "$CSS_DST_PATH/styles.tmp.css" + + # Replace mustache tags with associative array and co. + mo "$CSS_DST_PATH"/styles.tmp.css > "$CSS_DST_PATH"/styles.css + + # Remove the temporary stylesheet + rm "$CSS_DST_PATH"/styles.tmp.css + + # CSS Minification + minify -v --mime=text/css < "$CSS_DST_PATH"/styles.css > "$CSS_DST_PATH"/styles.min.css +else + echo "- You must install Minify CLI for running this script" + echo "- <https://github.com/tdewolff/minify/tree/master/cmd/minify>" +fi diff --git a/preprocess_javascript b/preprocess_javascript @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# JavaScript Preprocessing Script + +JS_SRC_PATH=static/src/js +JS_DST_PATH=static/dst/js + +# You must install "Minify CLI" for running this script : +# <https://github.com/tdewolff/minify/tree/master/cmd/minify> +if hash minify 2>/dev/null; then + # JavaScript Concatenation + cat "$JS_SRC_PATH/vendor/dom-utilities/dom-utilities.js" \ + "$JS_SRC_PATH/custom/init.js" \ + > "$JS_DST_PATH/script.js" + + # JavaScript Minification + minify -v --mime=text/javascript < "$JS_DST_PATH"/script.js > "$JS_DST_PATH"/script.min.js + +else + echo "- You must install Minify CLI for running this script" + echo "- <https://github.com/tdewolff/minify/tree/master/cmd/minify>" +fi diff --git a/reload-browser b/reload-browser @@ -0,0 +1,44 @@ +#!/bin/sh +# reload-browser - A cross-platform wrapper for reloading the current +# browser tab +# Eric Radman, 2014 +# http://eradman.com/entrproject/scripts/ + +usage() { + case `uname` in + Darwin) + # applescript needs the exact title + echo "Usage: $(basename $0) Firefox [Safari \"Google Chrome\" ...]" + ;; + *) + # xdotool uses regular expressions + echo "Usage: $(basename $0) Firefox [Chrome ...]" + ;; + esac + exit 1 +} +[ $# -lt 1 ] && usage + +for app in "$@" +do + case `uname` in + Darwin) + /usr/bin/osascript <<-APPLESCRIPT + set prev to (path to frontmost application as text) + tell application "$app" + activate + end tell + delay 0.5 + tell application "System Events" to keystroke "r" using {command down} + delay 0.5 + activate application prev + APPLESCRIPT + ;; + *) + xdotool search --onlyvisible --class "$app" windowfocus key \ + --window %@ 'ctrl+r' || { + 1>&2 echo "unable to signal an application named \"$app\"" + } + ;; + esac +done diff --git a/shortlinks b/shortlinks @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Dependency +# <https://github.com/ericchiang/pup> + +# Short URL command example +# curl -v "http://x.soucy.cc/?save=y&url=https://words.werd.io/tear-down-the-new-institutions-91516b868a2c" + +# curl -s "http://x.soucy.cc/?save=y&url=https://words.werd.io/tear-down-the-new-institutions-91516b868a2c" | pup '[name="tighturl"] attr{value}' + +while read -r db_entry; do + field_permalink=$(echo $db_entry | cut -d "|" -f 3) + + field_shortlink=$(curl -s "http://x.soucy.cc/?save=y&url=$field_permalink" | pup '[name="tighturl"] attr{value}') + + echo "$field_permalink|$field_shortlink" + +done < fakestache.db > shortlinks.db + diff --git a/shortlinks.db b/shortlinks.db @@ -0,0 +1,99 @@ +http://hugo.soucy.cc/note/2017/10/setup-a-desktop-environment-under-openbsd-with-xfce.html|http://x.soucy.cc/dh +http://hugo.soucy.cc/ce-site-web-explique-markdown.html|http://x.soucy.cc/di +http://hugo.soucy.cc/note/2017/10/test-de-repost-en-posse-3.html|http://x.soucy.cc/dj +http://hugo.soucy.cc/note/2017/10/reply-to-saralfddin93-for-status-914965952898457600.html|http://x.soucy.cc/dk +http://hugo.soucy.cc/note/2017/10/openbsd-6.2-sen-vient-a-la-mi-octobre.html|http://x.soucy.cc/dl +http://hugo.soucy.cc/note/2017/10/ghandi-je-suis-pret-a-mourir-pour-plusieurs-causes-a-tuer-pour-aucune.html|http://x.soucy.cc/dm +http://hugo.soucy.cc/note/2017/10/why-we-sleep.html|http://x.soucy.cc/dn +http://hugo.soucy.cc/note/2017/09/le-poil-de-la-bete.html|http://x.soucy.cc/do +http://hugo.soucy.cc/note/2017/09/lesbricodeurs-replyto-status-909427743573577728.html|http://x.soucy.cc/dp +http://hugo.soucy.cc/note/2017/09/lesbricodeurs-jaime-votre-nom.html|http://x.soucy.cc/dq +http://hugo.soucy.cc/note/2017/09/barbares-se-substitus-aux-piliers.html|http://x.soucy.cc/dr +http://hugo.soucy.cc/note/2017/09/bacteries-communiqueraient-avec-des-decharges-electriques.html|http://x.soucy.cc/ds +http://hugo.soucy.cc/note/2017/07/why-the-indie-web-movement-is-so-important.html|http://x.soucy.cc/dt +http://hugo.soucy.cc/note/2017/06/100-millions-de-certificats-pour-lets-encrypt.html|http://x.soucy.cc/du +http://hugo.soucy.cc/note/2017/06/using-css-variables-correctly.html|http://x.soucy.cc/dv +http://hugo.soucy.cc/note/2017/06/sesame-street-lgbt-pride.html|http://x.soucy.cc/dw +http://hugo.soucy.cc/note/2017/06/petite-contribution-bash-au-task-runner-manuel.html|http://x.soucy.cc/dx +http://hugo.soucy.cc/note/2017/06/politique-numerique-que-jaimerais.html|http://x.soucy.cc/dy +http://hugo.soucy.cc/note/2017/06/le-velo-cest-dangereux.html|http://x.soucy.cc/dz +http://hugo.soucy.cc/note/2017/05/twitter-partage-vos-donnees-personnelles.html|http://x.soucy.cc/e0 +http://hugo.soucy.cc/note/2017/05/utilisation-des-variables-css.html|http://x.soucy.cc/e1 +http://hugo.soucy.cc/note/2017/05/retirer-la-couche-pandoc-de-fakestache-ssg.html|http://x.soucy.cc/e2 +http://hugo.soucy.cc/note/2017/05/pandoc-for-openbsd.html|http://x.soucy.cc/e3 +http://hugo.soucy.cc/note/2017/05/mg-is-micro-gnu-emacs.html|http://x.soucy.cc/e4 +http://hugo.soucy.cc/note/2017/05/fai-associatifs-au-canada.html|http://x.soucy.cc/e5 +http://hugo.soucy.cc/note/2017/05/why-i-love-openbsd.html|http://x.soucy.cc/e6 +http://hugo.soucy.cc/note/2017/05/switching-to-openbsd.html|http://x.soucy.cc/e7 +http://hugo.soucy.cc/note/2017/04/duckduckgo-hacks-for-developers.html|http://x.soucy.cc/e8 +http://hugo.soucy.cc/note/2017/04/updating-all-packages-in-go.html|http://x.soucy.cc/e9 +http://hugo.soucy.cc/note/2017/04/fait-le-respirer-un-peu-ton-code.html|http://x.soucy.cc/ea +http://hugo.soucy.cc/albums-preferes.html|http://x.soucy.cc/eb +http://hugo.soucy.cc/note/2017/03/animista-css-animations-on-demand.html|http://x.soucy.cc/ec +http://hugo.soucy.cc/note/2017/03/moi-jaime-pas-les-courriels-juste-en-html.html|http://x.soucy.cc/ed +http://hugo.soucy.cc/a-propos.html|http://x.soucy.cc/ee +http://hugo.soucy.cc/note/2017/03/github-and-copyleft.html|http://x.soucy.cc/ef +http://hugo.soucy.cc/note/2017/03/appnet-is-another-silo-who-is-shutting-down.html|http://x.soucy.cc/eg +http://hugo.soucy.cc/note/2017/03/vider-le-filelist-dun-input-type-file.html|http://x.soucy.cc/eh +http://hugo.soucy.cc/note/2017/03/why-apple-avoid-the-gpl-3.html|http://x.soucy.cc/ei +http://hugo.soucy.cc/note/2017/03/presentation-de-manuel-un-task-runner-bash.html|http://x.soucy.cc/ej +http://hugo.soucy.cc/txt/bash/2017/03/manuel-taskrunner.html|http://x.soucy.cc/ek +http://hugo.soucy.cc/note/2017/03/vuejs-templates-a-maintenant-son-mode-dans-emacs.html|http://x.soucy.cc/el +http://hugo.soucy.cc/note/2017/03/si-les-etats-unis-envahissaient-le-canada.html|http://x.soucy.cc/em +http://hugo.soucy.cc/note/2017/03/poutine-et-bal-masque.html|http://x.soucy.cc/en +http://hugo.soucy.cc/note/2017/03/revanche-des-librairies-independantes.html|http://x.soucy.cc/eo +http://hugo.soucy.cc/note/2017/01/how-machines-learned-to-speak-human-language.html|http://x.soucy.cc/ep +http://hugo.soucy.cc/note/2017/01/3-500-proces-au-cours-des-30-dernieres-annees.html|http://x.soucy.cc/eq +http://hugo.soucy.cc/note/2017/01/est-ce-une-fausse-nouvelle-car-trop-beau-pour-etre-vrai.html|http://x.soucy.cc/er +http://hugo.soucy.cc/note/2017/01/because-protest-is-an-industry.html|http://x.soucy.cc/es +http://hugo.soucy.cc/note/2017/01/lemprise-de-wallstreet-sur-trump.html|http://x.soucy.cc/et +http://hugo.soucy.cc/note/2017/01/la-ville-facteur-majeur-d-evolution-des-especes.html|http://x.soucy.cc/eu +http://hugo.soucy.cc/note/2016/12/michel-chartrand-aurait-eu-cent-ans-hier.html|http://x.soucy.cc/ev +http://hugo.soucy.cc/note/2016/12/le-peuple-nest-pas-juridiquement-souverain.html|http://x.soucy.cc/ew +http://hugo.soucy.cc/note/2016/12/le-travail-aujourdhui-est-en-voie-de-disparition.html|http://x.soucy.cc/ex +http://hugo.soucy.cc/note/2016/12/larnaque-de-la-dictature-bancaire-continue.html|http://x.soucy.cc/ey +http://hugo.soucy.cc/note/2016/11/would-the-web-s-inventor-give-up-on-free-standards.html|http://x.soucy.cc/ez +http://hugo.soucy.cc/note/2016/11/the-average-american-now-downloads-zero-apps-per-month.html|http://x.soucy.cc/f0 +http://hugo.soucy.cc/note/2016/11/browsers-not-apps-are-the-future-of-mobile.html|http://x.soucy.cc/f1 +http://hugo.soucy.cc/note/2016/11/indieweb-make-your-social-media-posts-open-first.html|http://x.soucy.cc/f2 +http://hugo.soucy.cc/note/2016/10/how-can-i-handle-command-line-arguments-options-to-my-script-easily.html|http://x.soucy.cc/f3 +http://hugo.soucy.cc/note/2016/10/linux-foundation-takes-javascript-under-its-wings.html|http://x.soucy.cc/f4 +http://hugo.soucy.cc/note/2016/10/who-pays-for-the-decentralized-web.html|http://x.soucy.cc/f5 +http://hugo.soucy.cc/note/2016/09/ma-vie-obeit-a-l-attraction-des-livres-nikolski-nicolas-dickner.html|http://x.soucy.cc/f6 +http://hugo.soucy.cc/note/2016/09/why-we-use-progressive-enhancement-to-build-gov-uk.html|http://x.soucy.cc/f7 +http://hugo.soucy.cc/note/2016/09/internet-3-0-peut-on-reprendre-le-controle-des-geants.html|http://x.soucy.cc/f8 +http://hugo.soucy.cc/note/2016/09/ce-que-le-quebec-gagnerait-a-nationaliser-internet.html|http://x.soucy.cc/f9 +http://hugo.soucy.cc/note/2016/09/radio-canada-publicitaire-pour-apple.html|http://x.soucy.cc/fa +http://hugo.soucy.cc/note/2016/08/quoi-ce-n-est-pas-des-femmes-grenouilles.html|http://x.soucy.cc/fb +http://hugo.soucy.cc/note/2016/08/add-key-bindings-to-moving-faster-between-emacs-windows.html|http://x.soucy.cc/fc +http://hugo.soucy.cc/note/2016/08/openbsd-pour-tous.html|http://x.soucy.cc/fd +http://hugo.soucy.cc/note/2016/08/pokemon-go-et-societe-de-surveillance.html|http://x.soucy.cc/fe +http://hugo.soucy.cc/note/2016/08/snowden-pardon-petition-on-facebook.html|http://x.soucy.cc/ff +http://hugo.soucy.cc/note/2016/08/ssh-chat-server-written-ingo.html|http://x.soucy.cc/fg +http://hugo.soucy.cc/note/2016/08/nathalie-normandeau-et-la-radio-de-quebec.html|http://x.soucy.cc/fh +http://hugo.soucy.cc/note/2016/08/vimgifs-et-emacs_gifs.html|http://x.soucy.cc/fi +http://hugo.soucy.cc/note/2016/08/programming-languages-hyperpolyglot.html|http://x.soucy.cc/fj +http://hugo.soucy.cc/note/2016/08/everybody-should-be-twitter-verified.html|http://x.soucy.cc/fk +http://hugo.soucy.cc/note/2016/08/shipping-is-a-feature.html|http://x.soucy.cc/fl +http://hugo.soucy.cc/note/2016/08/matane-budget-participatif.html|http://x.soucy.cc/fm +http://hugo.soucy.cc/note/2016/08/m4-as-css-pre-processor.html|http://x.soucy.cc/fn +http://hugo.soucy.cc/note/2016/08/txti.html|http://x.soucy.cc/fo +http://hugo.soucy.cc/note/2016/07/emacs-sort-delete-matching-duplicate-lines.html|http://x.soucy.cc/fp +http://hugo.soucy.cc/note/2016/06/nous-sommes-eduques-a-croire.html|http://x.soucy.cc/fq +http://hugo.soucy.cc/note/2016/05/firefox-print-background-color.html|http://x.soucy.cc/fr +http://hugo.soucy.cc/note/2016/05/justin-jackson-is-a-fucking-webmaster.html|http://x.soucy.cc/fs +http://hugo.soucy.cc/note/2016/05/jeunes-liberaux-ringards.html|http://x.soucy.cc/ft +http://hugo.soucy.cc/note/2016/05/indieweb-in-a-nutshellown-your-identity-domain-website-content-uiux.html|http://x.soucy.cc/fu +http://hugo.soucy.cc/note/2016/04/tiens-tiens-tiens-le-projet-gnu-revamp-la-page-web.html|http://x.soucy.cc/fv +http://hugo.soucy.cc/note/2016/04/encore-une-fois-je-viens-de-supprimer-mon-compte-facebook.html|http://x.soucy.cc/fw +http://hugo.soucy.cc/note/2016/03/javascript-vanille-underscorejs-font-selon-moi-une-excellente-quipe-youmightnotneedjquery-webdev.html|http://x.soucy.cc/fx +http://hugo.soucy.cc/note/2016/02/encryption-is-the-nsas-friend-20160127nsa_loves_it_when_you_use_pgp.html|http://x.soucy.cc/fy +http://hugo.soucy.cc/note/2016/02/what-is-it-about-society-that-disappoints-you-so-much.html|http://x.soucy.cc/fz +http://hugo.soucy.cc/note/2016/01/tiens-un-article-sur-le-darknet-que-plusieurs-devraient-lire.html|http://x.soucy.cc/g0 +http://hugo.soucy.cc/txt/emacs/2015/06/emacs-101-la-configuration.html|http://x.soucy.cc/d3 +http://hugo.soucy.cc/txt/emacs/2015/06/emacs-101-l-introduction.html|http://x.soucy.cc/g1 +http://hugo.soucy.cc/txt/2014/09/mes-logiciels-libres-preferes.html|http://x.soucy.cc/g2 +http://hugo.soucy.cc/txt/2014/04/bronto-politiciens-de-silos.html|http://x.soucy.cc/g3 +http://hugo.soucy.cc/txt/2014/02/les-partis-politiques-nuisent-ils-a-la-democratie.html|http://x.soucy.cc/g4 +http://hugo.soucy.cc/file/pgp.html|http://x.soucy.cc/g5 +http://hugo.soucy.cc/file/curriculum-vitae.html|http://x.soucy.cc/g6 diff --git a/update-web-projects b/update-web-projects @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Script to do all the steps for upgrade a list of web projects +# Why? Laziness! +# You MUST have Bash 4 or Up + +echo "¤¤ NOT-TO-DO SOMETHING IS DOING SOMETHING ... ¤¤" && sleep 2 + +# The project list is a file with the path of each project per line +# Passes in first argument: +# Ex.: ./update-web-projects myprojectlistfile +# Paths must be relative to the $HOME directory. +# Ex.: my/project/relative/path + +PROJECTLIST="$1" + +# Projects path in a Array +unset -v "PROJECTS[*]" +declare -a PROJECTS + +while read -r line ; do + echo "Processing ${line}" + + PROJECTS+=("${line}") +done < "$PROJECTLIST" + +# Do all these steps below for each project in projectListFile +for project in "${PROJECTS[@]}"; do + # Check if the current path point to a directory + [ ! -d "$HOME/$project" ] && echo "$HOME/$project is not a valid directory" && exit 1 + + echo "¤¤¤¤¤¤¤ $(basename "$HOME/$project") ¤¤¤¤¤¤¤" + + # Go to the project directory + echo "Going to $(pwd)" + cd "$HOME/$project" || exit + + # If there's a .git/ folder do a `pull origin` and a fetch + if [ -d "$HOME/$project/.git" ]; then + echo "¤ GIT artefacts found ¤" + git pull origin "$(git rev-parse --abbrev-ref HEAD)" && git fetch + fi + + # If there's a composer.json do the `composer install` command + if [ -f "$HOME/$project/composer.json" ]; then + echo "¤ COMPOSER artefacts found ¤" + composer install + fi + + # If there's a node_modules folder do a `rm -R node_modules` + if [ -d "$HOME/$project/node_modules" ]; then + echo "¤ NODE_MODULES artefacts found ¤" + rm -Rf node_modules/ + echo "¤ ./node_modules removed ¤" + fi + + # If there's a yarn.lock do tne `yarn` command + # Or no yarn.lock but a package.json + if [ -f "$HOME/$project/yarn.lock" ]; then + echo "¤ YARN artefacts found ¤" + yarn + + if [ -f "$HOME/$project/scripts/build.sh" ]; then + yarn build + fi + elif [ ! -f "$HOME/$project/yarn.lock" ] && [ -f "$HOME/$project/package.json" ]; then + echo "¤ NPM artefacts found ¤" + npm install + fi + + # If there's a bower.json do tne `bower install` command + if [ -f "$HOME/$project/bower.json" ]; then + echo "¤ BOWER artefacts found ¤" + bower install + fi + + # If there's a Gruntfile.js do tne `grunt build-dev` command + if [ -f "$HOME/$project/Gruntfile.js" ] && cat -u "$HOME/$project/Gruntfile.js" | grep -q 'build-dev'; then + echo "¤ Grunt artefacts found ¤" + grunt build-dev + fi + + echo "¤¤ Done, $(basename "$HOME/$project") is updated ¤¤" +done