Last active
June 3, 2024 02:36
-
-
Save allex/ab874c487178eade932d220cb079470a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# vim: set ft=sh fdm=marker ts=2 sw=2 sts=2 tw=85 et: | |
# extract and convert scss to css3 variables, output type support json,text,css | |
# by @allex_wang | |
# | |
# Install: | |
# curl -sfkL -o ./convert-scss-var.sh https://gist.githubusercontent.com/allex/ab874c487178eade932d220cb079470a/raw/convert-scss-var.sh && chmod +x ./convert-scss-var.sh | |
# | |
# GistID: ab874c487178eade932d220cb079470a | |
# GistURL: https://gist.github.com/ab874c487178eade932d220cb079470a | |
set -euEo pipefail | |
PROG=$(basename "$0") | |
SH_DIR="$(cd -P -- "$(dirname -- "$(readlink -f "$0")")" && pwd -P)" | |
WORKDIR="$(umask 0077; mktemp -d)" | |
DEBUG= | |
# input (scss variable file) | |
scss_file= | |
# output file | |
output_file= | |
# output filetype: json, css, txt | |
output_format= | |
### Helpers {{{ | |
BOLD="$(tput bold 2>/dev/null || echo '')" | |
GREY="$(tput setaf 0 2>/dev/null || echo '')" | |
UNDERLINE="$(tput smul 2>/dev/null || echo '')" | |
RED="$(tput setaf 1 2>/dev/null || echo '')" | |
GREEN="$(tput setaf 2 2>/dev/null || echo '')" | |
YELLOW="$(tput setaf 3 2>/dev/null || echo '')" | |
BLUE="$(tput setaf 4 2>/dev/null || echo '')" | |
MAGENTA="$(tput setaf 5 2>/dev/null || echo '')" | |
CYAN="$(tput setaf 6 2>/dev/null || echo '')" | |
NO_COLOR="$(tput sgr0 2>/dev/null || echo '')" | |
info() { printf "${BOLD}${GREY}>${NO_COLOR} %s\n" "$*"; } | |
warn() { printf "${YELLOW}! %s${NO_COLOR}\n" "$*" >&2; } | |
error() { printf "${RED}x %s${NO_COLOR}\n" "$*" >&2; } | |
complete() { printf "${GREEN}✓${NO_COLOR} %s\n" "$*"; } | |
die() { [ "${1-}" ] && error "fatal: ${1}"; exit "${2-1}"; } | |
assert() { [ -n "$1" ] || die "${2?assert message required}"; } | |
has() { type "${1:?command required}" >/dev/null 2>&1; } | |
### }}} | |
show_usage() { | |
cat <<-HELP | |
Usage: ${PROG} [options] <scss_file> <output_file> | |
Options: | |
--output-format <json|txt|css> | |
Specifies the desired output format. The output format defines how the extracted | |
and converted SCSS variables are represented in the output file. Supported output | |
formats are: json, txt, and css. | |
Note: if this option is not specified, the output format defaults to "raw" CSS. | |
--debug | |
Enables debug mode. When debug mode is enabled, additional debugging information will | |
be displayed, which can be useful for troubleshooting. | |
-h, --help | |
Shows this help information. | |
Arguments: | |
<scss_file> | |
The path for the input SCSS file. This contains the SCSS variables that will be | |
extracted and converted by the script | |
<output_file> | |
The path to the output file. This file will contain the extracted and converted | |
SCSS variables, formatted according to either the --output-format parameter or | |
the "raw" CSS default. | |
Example: | |
${PROG} --output-format=json input.scss output.json | |
This command extracts and converts SCSS variables from "input.scss", formats | |
the output as JSON, and writes the results to "output.json" | |
Note: | |
The script needs either sass or node-sass to be installed on the system. | |
HELP | |
exit 1 | |
} | |
### ARGS {{{ | |
handle_exit() { | |
local ec="$?" | |
# declare -F on_exit, not avaiable in alipine/sh | |
if type on_exit >/dev/null 2>&1; then on_exit; fi | |
local tmpDir=${TMP:-${TMPDIR:-/tmp/}} | |
if [ "${WORKDIR##${tmpDir%%/}/*}" != "${WORKDIR}" ]; then | |
rm -rf "${WORKDIR--}" | |
else | |
warn "For security, The \$WORKDIR:${WORKDIR} not allot at system tmpdir, will not be cleanup" | |
fi | |
trap - INT TERM EXIT | |
exit $ec | |
} | |
trap handle_exit 0 1 2 3 6 15 | |
args=() | |
while [ $# -gt 0 ]; do | |
OPT=$1 | |
[ "$OPT" = "--" ] && break | |
[ "$OPT" = "${OPT#-*}" ] && { | |
args+=("$OPT") | |
shift | |
continue | |
} | |
if [ "${OPT%=*}" = "$OPT" ]; then | |
OPTARG="${2-}" | |
if [ "${OPTARG##-*}" = "${OPTARG}" ]; then | |
shift | |
else | |
OPTARG= | |
fi | |
else | |
OPT=$(echo "$1" | awk -F= '{print $1}') | |
OPTARG=$(echo "$1" | awk -F= '{print $2}') | |
fi | |
case $OPT in | |
--debug) | |
DEBUG=1 | |
;; | |
--output-format) | |
output_format=$OPTARG | |
;; | |
-h | --help) | |
show_usage | |
;; | |
-*) | |
error "Unknown parameter \"$OPT\"" | |
args+=("$OPT") | |
[ "$OPTARG" ] && args+=("\"$OPTARG\"") | |
;; | |
esac | |
[ $# -gt 0 ] && shift | |
done | |
[ "$DEBUG" == "1" ] && set -x; | |
[ ${#args[@]} -gt 0 ] && eval set -- "${args[@]}" | |
### }}} | |
scss_file="${1:-}" | |
output_file="${2:-}" | |
if [ -z "$scss_file" ]; then | |
show_usage | |
fi | |
awkfile="$WORKDIR/a.awk" | |
cat <<'EOF' > "$awkfile" | |
BEGIN { | |
FS=":" | |
var_prefix="--v-" | |
} | |
/^\$/{ | |
arr[substr($1,4)]=$1 | |
} | |
END { | |
print "@import '" scss_file "';"; | |
print "$variables: ("; | |
l = length(arr); | |
asorti(arr, sorted_keys) | |
for (i in sorted_keys) { | |
k = sorted_keys[i] | |
l--; | |
printf " %s%s: %s", var_prefix, k, arr[k]; | |
print(l != 0 ? "," : ""); | |
} | |
print ");"; | |
print "\ | |
:root {\n\ | |
@each $key, $value in $variables {\n\ | |
@if type-of($value) != map {\n\ | |
#{$key}: #{$value};\n\ | |
}\n\ | |
}\n\ | |
}"; | |
} | |
EOF | |
eval_sass () { | |
if has node-sass; then | |
node-sass --output-style expanded | |
elif has sass; then | |
sass --stdin --no-source-map --style=expanded | |
else | |
die "both sass and node-sass are not found" | |
fi | |
} | |
# output the css variables with different format (txt, json, raw) | |
output () { | |
out=${output_file:-/dev/stdout} | |
case "${output_format}" in | |
json) | |
awk ' | |
/^ *--/ { match($0, /^ *([^:]+): *(.*);/, a); arr[a[1]] = a[2]; } | |
END { | |
print "{"; | |
l = length(arr) | |
asorti(arr, sorted_keys) | |
for (i in sorted_keys) { | |
k = sorted_keys[i] | |
printf(" \"%s\": \"%s\"", k, arr[k]); | |
print(--l != 0 ? "," : ""); | |
} | |
print "}"; | |
} | |
' > "$out" | |
;; | |
txt) | |
awk '/^ *--/ { match($0, /^ *([^:]+): *(.*);/, arr); printf("%s: %s;\n", arr[1], arr[2]); }' > "$out" | |
;; | |
*) | |
cat > "$out" | |
;; | |
esac | |
} | |
awk -v "scss_file=$scss_file" -f "$awkfile" "$scss_file" \ | |
| eval_sass \ | |
| sed -e '/\/\*/,/\*\//d' \ | |
| output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment