cookutils rev 891

web/*: update look&feel
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Mar 17 01:20:30 2017 +0200 (2017-03-17)
parents 2cb347d1b668
children 34b05a9e92c7
files web/cooker.cgi web/prism.css web/prism.js web/style.css
line diff
     1.1 --- a/web/cooker.cgi	Fri Mar 17 00:44:10 2017 +0200
     1.2 +++ b/web/cooker.cgi	Fri Mar 17 01:20:30 2017 +0200
     1.3 @@ -23,60 +23,87 @@
     1.4  cooktime="$CACHE/cooktime"
     1.5  wokrev="$CACHE/wokrev"
     1.6  
     1.7 +# Path to sundown (markdown to html convertor)
     1.8 +if [ -n "$(which sundown 2>/dev/null)" ]; then
     1.9 +	SUNDOWN=$(which sundown)
    1.10 +elif [ -x "./sundown" ]; then
    1.11 +	SUNDOWN="./sundown"
    1.12 +fi
    1.13 +
    1.14  # We're not logged and want time zone to display correct server date.
    1.15  export TZ=$(cat /etc/TZ)
    1.16  
    1.17  case "$QUERY_STRING" in
    1.18 -recook=*)
    1.19 -	case "$HTTP_USER_AGENT" in
    1.20 -	*SliTaz*)
    1.21 -		grep -qs "^${QUERY_STRING#recook=}$" $CACHE/recook-packages ||
    1.22 -		echo ${QUERY_STRING#recook=} >> $CACHE/recook-packages
    1.23 -	esac
    1.24 -	cat <<EOT
    1.25 +	recook=*)
    1.26 +		case "$HTTP_USER_AGENT" in
    1.27 +			*SliTaz*)
    1.28 +				grep -qs "^${QUERY_STRING#recook=}$" $CACHE/recook-packages ||
    1.29 +				echo ${QUERY_STRING#recook=} >> $CACHE/recook-packages
    1.30 +		esac
    1.31 +		cat <<EOT
    1.32  Location: ${HTTP_REFERER:-${REQUEST_URI%\?*}}
    1.33  
    1.34  EOT
    1.35 -	exit ;;
    1.36 -poke)
    1.37 -	touch $CACHE/cooker-request
    1.38 -	cat <<EOT
    1.39 +		exit
    1.40 +		;;
    1.41 +
    1.42 +	poke)
    1.43 +		touch $CACHE/cooker-request
    1.44 +		cat <<EOT
    1.45  Location: ${HTTP_REFERER:-${REQUEST_URI%\?*}}
    1.46  
    1.47  EOT
    1.48 -	exit ;;
    1.49 -src*)
    1.50 -	file=$(busybox httpd -d "$SRC/${QUERY_STRING#*=}")
    1.51 -	cat <<EOT
    1.52 +		exit
    1.53 +		;;
    1.54 +
    1.55 +	src*)
    1.56 +		file=$(busybox httpd -d "$SRC/${QUERY_STRING#*=}")
    1.57 +		cat <<EOT
    1.58  Content-Type: application/octet-stream
    1.59  Content-Length: $(stat -c %s "$file")
    1.60  Content-Disposition: attachment; filename="$(basename "$file")"
    1.61  
    1.62  EOT
    1.63 -	cat "$file"
    1.64 -	exit ;;
    1.65 -download*)
    1.66 -	file=$(busybox httpd -d "$PKGS/${QUERY_STRING#*=}")
    1.67 -	cat <<EOT
    1.68 -Content-Type: application/octet-stream
    1.69 -Content-Length: $(stat -c %s "$file")
    1.70 -Content-Disposition: attachment; filename="$(basename "$file")"
    1.71 +		cat "$file"
    1.72 +		exit
    1.73 +		;;
    1.74  
    1.75 -EOT
    1.76 -	cat "$file"
    1.77 -	exit ;;
    1.78 -rss)
    1.79 -	cat <<EOT
    1.80 -Content-Type: application/rss+xml
    1.81 +	download*)
    1.82 +		file=$(busybox httpd -d "$PKGS/${QUERY_STRING#*=}")
    1.83 +		content_type='application/octet-stream'
    1.84 +		case $file in
    1.85 +			*.txt|*.conf|*/README|*/receipt)
    1.86 +			              content_type='text/plain; charset=UTF-8' ;;
    1.87 +			*.css)        content_type='text/css; charset=UTF-8' ;;
    1.88 +			*.htm|*.html) content_type='text/html; charset=UTF-8' ;;
    1.89 +			*.js)         content_type='application/javascript; charset=UTF-8' ;;
    1.90 +			*.desktop)    content_type='application/x-desktop; charset=UTF-8' ;;
    1.91 +			*.png)        content_type='image/png' ;;
    1.92 +			*.svg)        content_type='image/svg+xml' ;;
    1.93 +			*.jpg|*.jpeg) content_type='image/jpeg' ;;
    1.94 +			*.sh|*.cgi)   content_type='application/x-shellscript' ;;
    1.95 +			*.gz)         content_type='application/gzip' ;;
    1.96 +			*.ico)        content_type='image/vnd.microsoft.icon' ;;
    1.97 +		esac
    1.98 +		echo "Content-Type: $content_type"
    1.99 +		echo "Content-Length: $(stat -c %s "$file")"
   1.100 +		[ "$content_type" == 'application/octet-stream' ] &&
   1.101 +		echo "Content-Disposition: attachment; filename=\"$(basename "$file")\""
   1.102  
   1.103 -EOT
   1.104 -	;;
   1.105 -*)
   1.106 -	cat <<EOT
   1.107 -Content-Type: text/html; charset=utf-8
   1.108 +		echo
   1.109  
   1.110 -EOT
   1.111 -	;;
   1.112 +		cat "$file"
   1.113 +		exit
   1.114 +		;;
   1.115 +
   1.116 +	rss)
   1.117 +		echo -e 'Content-Type: application/rss+xml\n'
   1.118 +		;;
   1.119 +
   1.120 +	*)
   1.121 +		echo -e 'Content-Type: text/html; charset=UTF-8\n'
   1.122 +		;;
   1.123 +
   1.124  esac
   1.125  
   1.126  
   1.127 @@ -139,10 +166,14 @@
   1.128  		-e '/INFO-DIR/,/^END-INFO-DIR/d' \
   1.129  		-e "s|https*://[^>),'\"\` ]*|<a href=\"&\">&</a>|g" \
   1.130  		-e "s|ftp://[^>),\"\` ]*|<a href=\"&\">&</a>|g" \
   1.131 -		-e "s|^|</pre><pre>|"
   1.132 +		-e "s|^|</pre><pre class='info'>|"
   1.133  }
   1.134  
   1.135  
   1.136 +htmlize() {
   1.137 +	sed -e 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g'
   1.138 +}
   1.139 +
   1.140  # Put some colors in log and DB files.
   1.141  
   1.142  syntax_highlighter() {
   1.143 @@ -201,23 +232,38 @@
   1.144  					s|\[93m|<span style='color: #FF0'>|;
   1.145  					s|\[94m|<span style='color: #00F'>|;
   1.146  					s|\[95m|<span style='color: #808'>|;
   1.147 -					s|\[96m|<span style='color: #0CC'>|;
   1.148 +					s|\[96m|<span style='color: #088'>|;
   1.149  					s|\[39m|</span>|;"
   1.150 -				;;
   1.151 +			;;
   1.152 +
   1.153 +		files)
   1.154 +			sed \
   1.155 +				-e "s|\[[01];31m|<span style='color: #F00'>|g;
   1.156 +					s|\[[01];32m|<span style='color: #080'>|g;
   1.157 +					s|\[[01];33m|<span style='color: #FF0'>|g;
   1.158 +					s|\[[01];34m|<span style='color: #00F'>|g;
   1.159 +					s|\[[01];35m|<span style='color: #808'>|g;
   1.160 +					s|\[[01];36m|<span style='color: #088'>|g;
   1.161 +					s|\[[01];0m|<span style='color: #333'>|g;
   1.162 +					s|\[0m|</span>|g;"
   1.163 +			;;
   1.164  
   1.165  		receipt)
   1.166  			sed	-e s'|&|\&amp;|g' -e 's|<|\&lt;|g' -e 's|>|\&gt;|'g \
   1.167  				-e s"#^\#\([^']*\)#<span class='sh-comment'>\0</span>#"g \
   1.168 -				-e s"#\"\([^']*\)\"#<span class='sh-val'>\0</span>#"g ;;
   1.169 +				-e s"#\"\([^']*\)\"#<span class='sh-val'>\0</span>#"g
   1.170 +			;;
   1.171  
   1.172  		diff)
   1.173  			sed -e 's|&|\&amp;|g' -e 's|<|\&lt;|g' -e 's|>|\&gt;|g' \
   1.174  				-e s"#^-\([^']*\).#<span class='span-red'>\0</span>#"g \
   1.175  				-e s"#^+\([^']*\).#<span class='span-ok'>\0</span>#"g \
   1.176 -				-e s"#@@\([^']*\)@@#<span class='span-sky'>@@\1@@</span>#"g ;;
   1.177 +				-e s"#@@\([^']*\)@@#<span class='span-sky'>@@\1@@</span>#"g
   1.178 +			;;
   1.179  
   1.180  		activity)
   1.181 -			sed s"#^\([^']* : \)#<span class='log-date'>\0</span>#"g ;;
   1.182 +			sed s"#^\([^']* : \)#<span class='log-date'>\0</span>#"g
   1.183 +			;;
   1.184  	esac
   1.185  }
   1.186  
   1.187 @@ -228,7 +274,7 @@
   1.188  	cd $PKGS
   1.189  	ls -1t *.tazpkg | head -n 20 | \
   1.190  	while read file; do
   1.191 -		echo -n $(TZ=UTC stat -c '%y' $PKGS/$file | cut -d . -f 1 | sed s/:[0-9]*$//)
   1.192 +		echo -n $(TZ=UTC stat -c '%y' $PKGS/$file | cut -d. -f1 | sed s/:[0-9]*$//)
   1.193  		echo " : $file"
   1.194  	done
   1.195  }
   1.196 @@ -237,23 +283,19 @@
   1.197  # Optional full list button
   1.198  
   1.199  more_button() {
   1.200 -	[ $(wc -l < ${3:-$CACHE/$1}) -gt ${4:-12} ] && cat <<EOT
   1.201 -<div style="float: right;">
   1.202 -	<a class="button" href="?file=$1">$2</a>
   1.203 -</div>
   1.204 -EOT
   1.205 +	[ $(wc -l < ${3:-$CACHE/$1}) -gt ${4:-12} ] &&
   1.206 +	echo "<a class='button r' href='?file=$1'>$2</a>"
   1.207  }
   1.208  
   1.209  
   1.210  # Show the running command and its progression
   1.211  
   1.212 -running_command()
   1.213 -{
   1.214 +running_command() {
   1.215  	local state="Not running"
   1.216  	if [ -s "$command" ]; then
   1.217  		state="$(cat $command)"
   1.218  		set -- $(grep "^$state" $cooktime)
   1.219 -		if [ -n "$1" -a $2 -ne 0 ]; then
   1.220 +		if [ -n "$1" ]; then
   1.221  			state="$state $((($(date +%s)-$3)*100/$2))%"
   1.222  			[ $2 -gt 300 ] && state="$state (should end $(date -u -d @$(($2+$3))))"
   1.223  		fi
   1.224 @@ -262,6 +304,128 @@
   1.225  }
   1.226  
   1.227  
   1.228 +datalist() {
   1.229 +	(
   1.230 +		cd $wok
   1.231 +
   1.232 +		ls | awk '
   1.233 +		BEGIN{printf("<datalist id=\"packages\">")}
   1.234 +		     {printf("<option>%s</option>",$1)}
   1.235 +		END  {printf("</datalist>")}
   1.236 +		'
   1.237 +	)
   1.238 +}
   1.239 +
   1.240 +
   1.241 +summary() {
   1.242 +	log="$1"
   1.243 +	pkg="$(basename ${log%%.log*})"
   1.244 +	if [ -f "$log" ]; then
   1.245 +		if grep -q "cook:$pkg$" $command; then
   1.246 +			echo "<pre>The Cooker is currently building: $pkg</pre>"
   1.247 +		fi
   1.248 +		if fgrep -q "Summary for:" $log; then
   1.249 +			echo "<pre>"
   1.250 +			sed '/^Summary for:/,$!d' $log | sed /^$/d | syntax_highlighter log
   1.251 +			echo "</pre>"
   1.252 +		fi
   1.253 +
   1.254 +		if fgrep -q "Debug information" $log; then
   1.255 +			echo '<pre>'
   1.256 +			sed '/^Debug information/,$!d' $log | sed /^$/d | \
   1.257 +			if [ -n "$2" ]; then
   1.258 +				syntax_highlighter log | \
   1.259 +				sed 's|\([0-9][0-9]*\):|<a href="#n\1">\1</a>:|'
   1.260 +			else
   1.261 +				sed 's|^[0-9][0-9]*:||' | syntax_highlighter log
   1.262 +			fi
   1.263 +			echo '</pre>'
   1.264 +		fi
   1.265 +	else
   1.266 +		[ -n "$pkg" -a -d "$wok/$pkg" ] && echo "<pre>No log for $pkg</pre>"
   1.267 +	fi
   1.268 +}
   1.269 +
   1.270 +
   1.271 +pkg_info() {
   1.272 +	local log cmd active bpkg
   1.273 +	log=$LOGS/$pkg.log
   1.274 +	cmd=${QUERY_STRING%%=*}
   1.275 +	echo '<div id="info">'
   1.276 +	active=''; [ "$cmd" == 'receipt' -o "$cmd" == 'stuff' ] && active=' active'
   1.277 +	echo "<a class='button green$active' href='?receipt=$pkg'>receipt &amp; stuff</a>"
   1.278 +
   1.279 +	unset WEB_SITE WANTED
   1.280 +	bpkg=$pkg
   1.281 +	. $wok/$pkg/receipt
   1.282 +
   1.283 +	[ -n "$WANTED" ] && bpkg="${WANTED%% *}" # see locale-* with multiple WANTED
   1.284 +
   1.285 +	[ -n "$WEB_SITE" ] &&
   1.286 +	echo "<a class='button sky' href='$WEB_SITE'>web site</a>"
   1.287 +
   1.288 +	if [ -f "$wok/$pkg/taz/$PACKAGE-$VERSION/receipt" ]; then
   1.289 +		active=''; [ "$cmd" == 'files' ] && active=' active'
   1.290 +		echo "<a class='button khaki$active' href='?files=$pkg'>files</a>"
   1.291 +
   1.292 +		unset EXTRAVERSION
   1.293 +		. $wok/$pkg/taz/$PACKAGE-$VERSION/receipt
   1.294 +
   1.295 +		if [ -f $wok/$pkg/taz/$PACKAGE-$VERSION/description.txt ]; then
   1.296 +			active=''; [ "$cmd" == 'description' ] && active=' active'
   1.297 +			echo "<a class='button brown$active' href='?description=$pkg'>description</a>"
   1.298 +		fi
   1.299 +
   1.300 +		if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg ]; then
   1.301 +			echo "<a class='button gold' href='?download=$PACKAGE-$VERSION$EXTRAVERSION.tazpkg'>download</a>"
   1.302 +		fi
   1.303 +
   1.304 +		if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg ]; then
   1.305 +			echo "<a class='button gold' href='?download=$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg'>download</a>"
   1.306 +		fi
   1.307 +	fi
   1.308 +
   1.309 +	[ -n "$TARBALL" ] && [ -s "$SRC/$TARBALL" ] &&
   1.310 +	echo "<a class='button yellow' href='?src=$TARBALL'>source</a>"
   1.311 +
   1.312 +	[ -x ./man2html ] &&
   1.313 +	if [ -d $wok/$bpkg/install/usr/man ] ||
   1.314 +	   [ -d $wok/$bpkg/install/usr/share/man ] ||
   1.315 +	   [ -d $wok/$bpkg/taz/*/fs/usr/man ] ||
   1.316 +	   [ -d $wok/$bpkg/taz/*/fs/usr/share/man ]; then
   1.317 +		active=''; [ "$cmd" == 'man' ] && active=' active'
   1.318 +		echo "<a class='button plum$active' href='?man=$bpkg'>man</a>"
   1.319 +	fi
   1.320 +
   1.321 +	if [ -d $wok/$bpkg/install/usr/doc ] ||
   1.322 +	   [ -d $wok/$bpkg/install/usr/share/doc ] ||
   1.323 +	   [ -d $wok/$bpkg/taz/*/fs/usr/doc ] ||
   1.324 +	   [ -d $wok/$bpkg/taz/*/fs/usr/share/doc ]; then
   1.325 +		active=''; [ "$cmd" == 'doc' ] && active=' active'
   1.326 +		echo "<a class='button plum$active' href='?doc=$bpkg'>doc</a>"
   1.327 +	fi
   1.328 +
   1.329 +	if [ -d $wok/$bpkg/install/usr/info ] ||
   1.330 +	   [ -d $wok/$bpkg/install/usr/share/info ] ||
   1.331 +	   [ -d $wok/$bpkg/taz/*/fs/usr/info ] ||
   1.332 +	   [ -d $wok/$bpkg/taz/*/fs/usr/share/info ]; then
   1.333 +		active=''; [ "$cmd" == 'info' ] && active=' active'
   1.334 +		echo "<a class='button plum$active' href='?info=$bpkg'>info</a>"
   1.335 +	fi
   1.336 +
   1.337 +	[ -n "$(echo $REQUEST_URI | sed 's|/[^/]*?pkg.*||')" ] ||
   1.338 +	echo "<a class='button' href='ftp://${HTTP_HOST%:*}/$pkg/'>browse</a>"
   1.339 +
   1.340 +	if [ -s "$log" ]; then
   1.341 +		active=''; [ "$cmd" == 'log' ] && active=' active'
   1.342 +		echo "<a class='button gray$active' href='?log=$pkg.log'>logs</a>"
   1.343 +	fi
   1.344 +
   1.345 +	echo '</div>'
   1.346 +}
   1.347 +
   1.348 +
   1.349 +
   1.350  # xHTML header. Pages can be customized with a separated html.header file.
   1.351  
   1.352  if [ -f "header.html" ]; then
   1.353 @@ -272,9 +436,13 @@
   1.354  <html lang="en">
   1.355  <head>
   1.356  	<meta charset="UTF-8">
   1.357 +	<meta name="viewport" content="width=device-width, initial-scale=1.0">
   1.358  	<title>SliTaz Cooker</title>
   1.359  	<link rel="shortcut icon" href="favicon.ico">
   1.360  	<link rel="stylesheet" href="style.css">
   1.361 +	<script src="prism.js"></script>
   1.362 +	<link rel="stylesheet" href="prism.css">
   1.363 +	<link rel="alternate" type="application/rss+xml" title="Cooker Feed" href="?rss">
   1.364  	<meta name="robots" content="nofollow">
   1.365  </head>
   1.366  <body>
   1.367 @@ -283,9 +451,6 @@
   1.368  	<div id="logo"></div>
   1.369  	<h1><a href="cooker.cgi">SliTaz Cooker</a></h1>
   1.370  </div>
   1.371 -
   1.372 -<!-- Content -->
   1.373 -<div id="content">
   1.374  EOT
   1.375  fi
   1.376  
   1.377 @@ -298,6 +463,7 @@
   1.378  	pkg=*)
   1.379  		pkg=${QUERY_STRING#pkg=}
   1.380  		log=$LOGS/$pkg.log
   1.381 +		echo "<div id='content'>"
   1.382  		echo "<h2>Package: $pkg</h2>"
   1.383  
   1.384  		# Define cook variables for syntax highlighter
   1.385 @@ -311,59 +477,14 @@
   1.386  		fi
   1.387  
   1.388  		# Package info.
   1.389 -		echo '<div id="info">'
   1.390  		if [ -f "$wok/$pkg/receipt" ]; then
   1.391 -			echo "<a href='?receipt=$pkg'>receipt</a>"
   1.392 -			unset WEB_SITE
   1.393 -			unset WANTED
   1.394 -			bpkg=$pkg
   1.395 -			. $wok/$pkg/receipt
   1.396 -
   1.397 -			[ -n "$WANTED" ] && bpkg="${WANTED%% *}" # see locale-* with multiple WANTED
   1.398 -			[ -n "$WEB_SITE" ] && # busybox wget -s $WEB_SITE &&
   1.399 -			echo "<a href='$WEB_SITE'>home</a>"
   1.400 -
   1.401 -			if [ -f "$wok/$pkg/taz/$PACKAGE-$VERSION/receipt" ]; then
   1.402 -				echo "<a href='?files=$pkg'>files</a>"
   1.403 -				unset EXTRAVERSION
   1.404 -				. $wok/$pkg/taz/$PACKAGE-$VERSION/receipt
   1.405 -				if [ -f $wok/$pkg/taz/$PACKAGE-$VERSION/description.txt ]; then
   1.406 -					echo "<a href='?description=$pkg'>description</a>"
   1.407 -				fi
   1.408 -				if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg ]; then
   1.409 -					echo "<a href='?download=$PACKAGE-$VERSION$EXTRAVERSION.tazpkg'>download</a>"
   1.410 -				fi
   1.411 -				if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg ]; then
   1.412 -					echo "<a href='?download=$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg'>download</a>"
   1.413 -				fi
   1.414 -			fi
   1.415 -			[ -x ./man2html ] &&
   1.416 -			if [ -d $wok/$bpkg/install/usr/man ] ||
   1.417 -			   [ -d $wok/$bpkg/install/usr/share/man ] ||
   1.418 -			   [ -d $wok/$bpkg/taz/*/fs/usr/man ] ||
   1.419 -			   [ -d $wok/$bpkg/taz/*/fs/usr/share/man ]; then
   1.420 -				echo "<a href='?man=$bpkg'>man</a>"
   1.421 -			fi
   1.422 -			if [ -d $wok/$bpkg/install/usr/doc ] ||
   1.423 -			   [ -d $wok/$bpkg/install/usr/share/doc ] ||
   1.424 -			   [ -d $wok/$bpkg/taz/*/fs/usr/doc ] ||
   1.425 -			   [ -d $wok/$bpkg/taz/*/fs/usr/share/doc ]; then
   1.426 -				echo "<a href='?doc=$bpkg'>doc</a>"
   1.427 -			fi
   1.428 -			if [ -d $wok/$bpkg/install/usr/info ] ||
   1.429 -			   [ -d $wok/$bpkg/install/usr/share/info ] ||
   1.430 -			   [ -d $wok/$bpkg/taz/*/fs/usr/info ] ||
   1.431 -			   [ -d $wok/$bpkg/taz/*/fs/usr/share/info ]; then
   1.432 -				echo "<a href='?info=$bpkg'>info</a>"
   1.433 -			fi
   1.434 -			[ -n "$(echo $REQUEST_URI | sed 's|/[^/]*?pkg.*||')" ] ||
   1.435 -			echo "<a href='ftp://${HTTP_HOST%:*}/$pkg/'>browse</a>"
   1.436 +			pkg_info
   1.437  		else
   1.438  			if [ $(ls $wok/*$pkg*/receipt 2>/dev/null | wc -l) -eq 0 ]; then
   1.439  				echo "No package named: $pkg"
   1.440  			else
   1.441  				ls $wok/$pkg/receipt >/dev/null 2>&1 || pkg="*$pkg*"
   1.442 -				echo '<table style="width:100%">'
   1.443 +				echo '<table class="zebra" style="width:100%">'
   1.444  				for i in $(cd $wok ; ls $pkg/receipt); do
   1.445  					pkg=$(dirname $i)
   1.446  					unset SHORT_DESC CATEGORY
   1.447 @@ -380,78 +501,75 @@
   1.448  				unset pkg
   1.449  			fi
   1.450  		fi
   1.451 -		echo '</div>'
   1.452  
   1.453  		# Check for a log file and display summary if it exists.
   1.454 +		summary "$log"
   1.455  		if [ -f "$log" ]; then
   1.456 -			if grep -q "cook:$pkg$" $command; then
   1.457 -				echo "<pre>The Cooker is currently building: $pkg</pre>"
   1.458 -			fi
   1.459 -			if fgrep -q "Summary for:" $LOGS/$pkg.log; then
   1.460 -				echo '<h3>Cook summary</h3>'
   1.461 -				echo '<pre>'
   1.462 -				grep -A 12 "^Summary for:" $LOGS/$pkg.log | sed /^$/d | \
   1.463 -					syntax_highlighter log
   1.464 -				echo '</pre>'
   1.465 -			fi
   1.466 -			if fgrep -q "Debug information" $LOGS/$pkg.log; then
   1.467 -				echo '<h3>Cook failed</h3>'
   1.468 -				echo '<pre>'
   1.469 -				grep -A 8 "^Debug information" $LOGS/$pkg.log | sed /^$/d | \
   1.470 -						syntax_highlighter log
   1.471 -				echo '</pre>'
   1.472 -			fi
   1.473 -			echo "<h3>Cook log $(stat -c %y $log | sed 's/:..\..*//')</h3>"
   1.474 -			for i in $(ls -t $log.*); do
   1.475 -				echo -n "<a href=\"?log=$(basename $i)\">"
   1.476 -				echo "$(stat -c %y $i | sed 's/ .*//')</a>"
   1.477 -			done
   1.478 -			echo '<pre>'
   1.479 -			cat $log | syntax_highlighter log
   1.480 -			echo '</pre>'
   1.481  			case "$HTTP_USER_AGENT" in
   1.482 -			*SliTaz*)
   1.483 -				[ -f $CACHE/cooker-request ] && [ -n "$HTTP_REFERER" ] &&
   1.484 -				echo "<a class=\"button\" href=\"?recook=$pkg\">Recook $pkg</a>"
   1.485 +				*SliTaz*)
   1.486 +					[ -f $CACHE/cooker-request ] && [ -n "$HTTP_REFERER" ] &&
   1.487 +					echo "<a class=\"button\" href=\"?recook=$pkg\">Recook $pkg</a>"
   1.488 +					;;
   1.489  			esac
   1.490 -		else
   1.491 -			[ "$pkg" ] && echo "<pre>No log: $pkg</pre>"
   1.492 -		fi ;;
   1.493 +		fi
   1.494 +		;;
   1.495  
   1.496  	log=*)
   1.497 -		log=$LOGS/${QUERY_STRING#log=}
   1.498 -		if [ -s $log ]; then
   1.499 -			echo "<h3>Cook log $(stat -c %y $log | sed 's/:..\..*//')</h3>"
   1.500 -			if fgrep -q "Summary" $log; then
   1.501 -				echo '<pre>'
   1.502 -				grep -A 20 "^Summary" $log | sed /^$/d | \
   1.503 -					syntax_highlighter log
   1.504 -				echo '</pre>'
   1.505 -			fi
   1.506 -			echo '<pre>'
   1.507 -			cat $log | syntax_highlighter log
   1.508 -			echo '</pre>'
   1.509 +		log=${QUERY_STRING#log=}
   1.510 +		logfile=$LOGS/$log
   1.511 +		pkg=${log%.log*}
   1.512 +		if [ -s "$logfile" ]; then
   1.513 +			echo "<div id='content'>"
   1.514 +
   1.515 +			echo "<h2>Cook log $(stat -c %y $logfile | sed 's/:..\..*//')</h2>"
   1.516 +			pkg_info
   1.517 +
   1.518 +			case $log in
   1.519 +				*.log) baselog=$logfile ;;
   1.520 +				*)     baselog=${logfile%.*} ;;
   1.521 +			esac
   1.522 +			for i in $(ls -t $baselog $baselog.* 2>/dev/null); do
   1.523 +				class=''; [ $i == $logfile ] && class=' gray'
   1.524 +				echo -n "<a class='button$class' href=\"?log=$(basename $i)\">"
   1.525 +				echo "$(stat -c %y $i | cut -d: -f1,2)</a>"
   1.526 +			done
   1.527 +
   1.528 +			summary "$logfile" links
   1.529 +
   1.530 +			cat $logfile | syntax_highlighter log | awk '
   1.531 +			BEGIN { print "<pre class=\"log\">"; }
   1.532 +			      { printf("<a name=\"l%d\" href=\"#l%d\">%5d</a>  %s\n", NR, NR, NR, $0); }
   1.533 +			END   { print "</pre>"; }
   1.534 +			'
   1.535  		fi
   1.536  		;;
   1.537 +
   1.538  	file=*)
   1.539 +		echo "<div id='content'>"
   1.540  		# Don't allow all files on the system for security reasons.
   1.541  		file=${QUERY_STRING#file=}
   1.542  		case "$file" in
   1.543  			activity|cooknotes|cooklist)
   1.544  				[ "$file" == "cooklist" ] && \
   1.545  					nb="- Packages: $(cat $cooklist | wc -l)"
   1.546 +				echo '<div id="content2">'
   1.547  				echo "<h2>DB: $file $nb</h2>"
   1.548 -				echo '<pre>'
   1.549 -				tac $CACHE/$file | syntax_highlighter activity
   1.550 -				echo '</pre>' ;;
   1.551 +				echo '<ul class="activity">'
   1.552 +				tac $CACHE/$file | syntax_highlighter activity | \
   1.553 +				sed 's|^|<li>|; s|$|</li>|'
   1.554 +				echo '</ul></div>'
   1.555 +				;;
   1.556  
   1.557  			broken)
   1.558 -				nb=$(cat $broken | wc -l)
   1.559 +				nb=$(wc -l < $broken)
   1.560 +				echo '<div id="content2">'
   1.561  				echo "<h2>DB: broken - Packages: $nb</h2>"
   1.562 -				echo '<pre>'
   1.563 +				echo '<ul class="activity">'
   1.564  				cat $CACHE/$file | sort | \
   1.565 -					sed s"#^[^']*#<a href='?pkg=\0'>\0</a>#"g
   1.566 -				echo '</pre>' ;;
   1.567 +					sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" | \
   1.568 +					sed 's|^|<li>|; s|$|</li>|'
   1.569 +				echo '</ul></div>'
   1.570 +				;;
   1.571  
   1.572  			*.diff)
   1.573  				diff=$CACHE/$file
   1.574 @@ -461,7 +579,8 @@
   1.575  					and installed build dependencies to cook.</p>"
   1.576  				echo '<pre>'
   1.577  				cat $diff | syntax_highlighter diff
   1.578 -				echo '</pre>' ;;
   1.579 +				echo '</pre>'
   1.580 +				;;
   1.581  
   1.582  			*.log)
   1.583  				log=$LOGS/$file
   1.584 @@ -479,105 +598,250 @@
   1.585  					echo '</pre>'
   1.586  				else
   1.587  					echo "<pre>No log file: $log</pre>"
   1.588 -				fi ;;
   1.589 -		esac ;;
   1.590 +				fi
   1.591 +				;;
   1.592 +		esac
   1.593 +		;;
   1.594  
   1.595  	stuff=*)
   1.596 +		echo "<div id='content'>"
   1.597  		file=${QUERY_STRING#stuff=}
   1.598 -		echo "<h2>$file</h2>"
   1.599 -		echo '<pre>'
   1.600 -		cat $wok/$file | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
   1.601 -		echo '</pre>' ;;
   1.602 +		pkg=${file%%/*}
   1.603 +		if [ -f "$wok/$file" ]; then
   1.604 +			echo "<h2>$file</h2>"
   1.605 +			pkg_info
   1.606 +			echo "<a class='button' href='?receipt=$pkg'>receipt</a>"
   1.607 +
   1.608 +			( cd $wok/$pkg ; find stuff -type f 2> /dev/null ) | sort | \
   1.609 +			while read i ; do
   1.610 +				class=''; [ "$pkg/$i" == "$file" ] && class=" green"
   1.611 +				echo "<a class='button$class' href='?stuff=$pkg/$i'>$i</a>"
   1.612 +			done
   1.613 +
   1.614 +			case $file in
   1.615 +				*.desktop|*.theme) class="ini" ;;
   1.616 +				*.patch|*.diff|*.u)  class="diff" ;;
   1.617 +				*.sh)         class="bash" ;;
   1.618 +				*.conf*)
   1.619 +					class="bash"
   1.620 +					[ -n "$(cut -c1 < $wok/$file | fgrep '[')" ] && class="ini"
   1.621 +					;;
   1.622 +				*.pl)           class="perl" ;;
   1.623 +				*.c|*.h|*.awk)  class="clike" ;;
   1.624 +				*.svg)          class="svg" ;;
   1.625 +				*Makefile*)     class="makefile" ;;
   1.626 +				*.po|*.pot)     class="bash" ;;
   1.627 +				*.css)          class="css" ;;
   1.628 +				*.htm|*.html)   class="html" ;;
   1.629 +				*.js)           class="js" ;;
   1.630 +				*.txt)          class="asciidoc" ;;
   1.631 +				*)
   1.632 +					case $(head -n1 $wok/$file) in
   1.633 +						*!/bin/sh*|*!/bin/bash*) class="bash" ;;
   1.634 +					esac
   1.635 +					if [ -z "$class" -a "$(head -n1 $wok/$file | cut -b1)" == '#' ]; then
   1.636 +						class="bash"
   1.637 +					fi
   1.638 +					if [ -z "$class" ]; then
   1.639 +						# Follow Busybox restrictions. Search for non-printable chars
   1.640 +						if [ $(tr -d '[:alnum:][:punct:][:blank:][:cntrl:]' < "$wok/$file" | wc -c) -gt 0 ]; then
   1.641 +							raw="true"
   1.642 +						fi
   1.643 +					fi
   1.644 +					;;
   1.645 +			esac
   1.646 +
   1.647 +			# Display image
   1.648 +			case $file in
   1.649 +				*.png|*.svg|*.jpg|*.jpeg|*.ico)
   1.650 +					echo "<img src='?download=../wok/$file' style='display: block; max-width: 100%; margin: auto'/>"
   1.651 +					;;
   1.652 +			esac
   1.653 +
   1.654 +			# Display colored listing (also for *.svg)
   1.655 +			case $file in
   1.656 +				*.png|*.jpg|*.jpeg|*.ico) ;;
   1.657 +				*)
   1.658 +					if [ -z "$raw" ]; then
   1.659 +						echo -n "<pre><code class='language-$class'>"
   1.660 +						cat $wok/$file | sed 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g'
   1.661 +						echo '</code></pre>'
   1.662 +					fi
   1.663 +					;;
   1.664 +			esac
   1.665 +
   1.666 +			# Display hex dump for binary files
   1.667 +			if [ -n "$raw" ]; then
   1.668 +				echo -n "<pre><code class='language-$class'>"
   1.669 +				hexdump -C $wok/$file | sed 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g'
   1.670 +				echo '</code></pre>'
   1.671 +			fi
   1.672 +		else
   1.673 +			echo "<pre>File '$file' absent!</pre>"
   1.674 +		fi
   1.675 +		;;
   1.676  
   1.677  	receipt=*)
   1.678 +		echo "<div id='content'>"
   1.679  		pkg=${QUERY_STRING#receipt=}
   1.680 -		echo "<h2>Receipt for: $pkg</h2>"
   1.681  		if [ -f "$wok/$pkg/receipt" ]; then
   1.682 +			echo "<h2>Receipt for: $pkg</h2>"
   1.683 +			pkg_info
   1.684 +			echo "<a class='button green' href='?receipt=$pkg'>receipt</a>"
   1.685  			. $wok/$pkg/receipt
   1.686 -			[ -n "$TARBALL" ] && [ -s "$SRC/$TARBALL" ] &&
   1.687 -			echo "<a href='?src=$TARBALL'>source</a>"
   1.688  
   1.689 -			( cd $wok/$pkg ; find stuff -type f 2> /dev/null ) | \
   1.690 -			while read file ; do
   1.691 -				echo "<a href=\"?stuff=$pkg/$file\">$file</a>"
   1.692 +			( cd $wok/$pkg; find stuff -type f 2> /dev/null ) | sort | \
   1.693 +			while read file; do
   1.694 +				echo "<a class='button' href='?stuff=$pkg/$file'>$file</a>"
   1.695  			done | sort
   1.696 -			echo '<pre>'
   1.697 -			cat $wok/$pkg/receipt | \
   1.698 -				syntax_highlighter receipt
   1.699 +			echo -n '<pre><code class="language-bash">'
   1.700 +			cat $wok/$pkg/receipt | htmlize
   1.701 +			echo '</code></pre>'
   1.702 +		else
   1.703 +			echo "<pre>No receipt for: $pkg</pre>"
   1.704 +		fi
   1.705 +		;;
   1.706 +
   1.707 +	files=*)
   1.708 +		echo "<div id='content'>"
   1.709 +		pkg=${QUERY_STRING#files=}
   1.710 +		dir=$(ls -d $WOK/$pkg/taz/$pkg-* 2>/dev/null)
   1.711 +		if [ -d "$dir/fs" ]; then
   1.712 +			size=$(du -hs $dir/fs | awk '{ print $1 }')
   1.713 +			echo "<h2>Files installed by the package \"$pkg\" ($size)</h2>"
   1.714 +			pkg_info
   1.715 +			#echo "<a class='button gray' href='?pkg=$pkg'>‹ back</a>"
   1.716 +
   1.717 +			echo '<pre class="files">'
   1.718 +
   1.719 +			find $dir/fs -not -type d -print0 | \
   1.720 +			xargs -0 ls -ld --color=always | \
   1.721 +			syntax_highlighter files | \
   1.722 +			sed "s|\([^/]*\)/.*\(${dir#*wok}/fs\)\([^<]*\)\(<.*\)$|\1<a href=\"?download=../wok\2\3\">\3</a>\4|"
   1.723 +
   1.724  			echo '</pre>'
   1.725  		else
   1.726 -			echo "<pre>No receipt for: $pkg</pre>"
   1.727 -		fi ;;
   1.728 -
   1.729 -	files=*)
   1.730 -		pkg=${QUERY_STRING#files=}
   1.731 -		dir=$(ls -d $WOK/$pkg/taz/$pkg-*)
   1.732 -		if [ -d "$dir/fs" ]; then
   1.733 -			echo "<h2>Installed files by: $pkg ($(du -hs $dir/fs | awk '{ print $1 }'))</h2>"
   1.734 -			echo '<pre>'
   1.735 -			find $dir/fs -not -type d -print0 | xargs -0 ls -ld | \
   1.736 -				sed "s|\(.*\) /.*\(${dir#*wok}/fs\)\(.*\)|\1 <a href=\"?download=../wok\2\3\">\3</a>|;s|^\([^-].*\)\(<a.*\)\">\(.*\)</a>|\1\3|"
   1.737 -			echo '</pre>'
   1.738 -		else
   1.739 -			echo "<pre>No files list for: $pkg</pre>"
   1.740 -		fi ;;
   1.741 +			echo "<h2>No files list for \"$pkg\"</h2>"
   1.742 +			echo "<a class='button gray' href='?pkg=$pkg'>‹ back</a>"
   1.743 +		fi
   1.744 +		;;
   1.745  
   1.746  	description=*)
   1.747 +		echo "<div id='content'>"
   1.748  		pkg=${QUERY_STRING#description=}
   1.749 -		echo "<h2>Description of $pkg</h2>"
   1.750 -		dir=$(ls -d $WOK/$pkg/taz/$pkg-*)
   1.751 +		dir=$(ls -d $WOK/$pkg/taz/$pkg-* 2>/dev/null)
   1.752  		if [ -s "$dir/description.txt" ]; then
   1.753 -			echo '<pre>'
   1.754 -			cat $dir/description.txt | \
   1.755 -				sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
   1.756 -			echo '</pre>'
   1.757 +			echo "<h2>Description of $pkg</h2>"
   1.758 +			pkg_info
   1.759 +			if [ -x "$SUNDOWN" ]; then
   1.760 +				echo '<div id="content2">'
   1.761 +				$SUNDOWN $dir/description.txt
   1.762 +				echo '</div>'
   1.763 +			else
   1.764 +				echo '<pre><code class="language-markdown">'
   1.765 +				cat $dir/description.txt | \
   1.766 +					sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
   1.767 +				echo '</code></pre>'
   1.768 +			fi
   1.769  		else
   1.770  			echo "<pre>No description for: $pkg</pre>"
   1.771 -		fi ;;
   1.772 +		fi
   1.773 +		;;
   1.774  
   1.775  	man=*|doc=*|info=*)
   1.776 +		echo '<div id="content">'
   1.777  		type=${QUERY_STRING%%=*}
   1.778  		pkg=$(GET $type)
   1.779 -		dir=$WOK/$pkg/install/usr/share/$type
   1.780 -		[ -d $dir ] || dir=$WOK/$pkg/install/usr/$type
   1.781 -		[ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/share/$type)
   1.782 -		[ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/$type)
   1.783 -		page=$(GET file)
   1.784 -		if [ -z "$page" ]; then
   1.785 -			page=$(find $dir -type f | sed q)
   1.786 -			page=${page#$dir/}
   1.787 +		if [ -d "$wok/$pkg" ]; then
   1.788 +			dir=$WOK/$pkg/install/usr/share/$type
   1.789 +			[ -d $dir ] || dir=$WOK/$pkg/install/usr/$type
   1.790 +			[ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/share/$type)
   1.791 +			[ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/$type)
   1.792 +			page=$(GET file)
   1.793 +			if [ -z "$page" ]; then
   1.794 +				page=$(find $dir -type f | sed q)
   1.795 +				page=${page#$dir/}
   1.796 +			fi
   1.797 +
   1.798 +			echo "<h2>$(basename $page)</h2>"
   1.799 +
   1.800 +			pkg_info
   1.801 +			echo '<div style="max-height: 5em; overflow: auto">'
   1.802 +			find $dir -type f | sort | while read i ; do
   1.803 +				[ -s $i ] || continue
   1.804 +				case "$i" in
   1.805 +					*.jp*g|*.png|*.gif|*.svg) continue
   1.806 +				esac
   1.807 +				i=${i#$dir/}
   1.808 +				class=''; [ "$page" == "$i" ] && class=" plum"
   1.809 +				echo "<a class='button$class' href='?$type=$pkg&amp;file=$i'>$(basename $i .gz)</a>"
   1.810 +			done | sort -t \> -k 2
   1.811 +			echo '</div>'
   1.812 +
   1.813 +			if [ -f "$dir/$page" ]; then
   1.814 +				tmp="$(mktemp)"
   1.815 +				docat "$dir/$page" > $tmp
   1.816 +				[ -s "$tmp" ] &&
   1.817 +				case "$type" in
   1.818 +					info)
   1.819 +						echo '<div id="content2">'
   1.820 +						echo '<pre class="info">'
   1.821 +						info2html < "$tmp"
   1.822 +						echo '</pre></div>'
   1.823 +						;;
   1.824 +					doc)
   1.825 +						case "$page" in
   1.826 +							*.sgml) class='xml';;
   1.827 +							*)      class='asciidoc';;
   1.828 +						esac
   1.829 +						case "$page" in
   1.830 +							*.htm*)
   1.831 +								echo '<div id="content2">'
   1.832 +								cat
   1.833 +								echo '</div>'
   1.834 +								;;
   1.835 +							*)
   1.836 +								echo "<pre><code class=\"language-$class\">"
   1.837 +								sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
   1.838 +								echo '</code></pre>'
   1.839 +								;;
   1.840 +						esac < "$tmp"
   1.841 +						;;
   1.842 +					man)
   1.843 +						export TEXTDOMAIN='man2html'
   1.844 +						echo "<div id='content2'>"
   1.845 +
   1.846 +						html=$(./man2html "$tmp" | sed -e '1,/<header>/d' \
   1.847 +						-e 's|<a href="file:///[^>]*>\([^<]*\)</a>|\1|g' \
   1.848 +						-e 's|<a href="?[1-9]\+[^>]*>\([^<]*\)</a>|\1|g')
   1.849 +
   1.850 +						if [ -n "$(echo "$html" | fgrep 'The requested file /tmp/tmp.')" ]; then
   1.851 +							# Process the pre-formatted man-cat page
   1.852 +							echo '<pre>'
   1.853 +							sed '
   1.854 +								s|M-bM-^@M-^S|—|g;
   1.855 +								s|M-bM-^@M-^\\|<b>|g;
   1.856 +								s|M-bM-^@M-^]|</b>|g
   1.857 +								s|M-bM-^@M-^X|<u>|g;
   1.858 +								s|M-bM-^@M-^Y|</u>|g;
   1.859 +								s|M-BM-||g;
   1.860 +								' "$tmp"
   1.861 +							echo '</pre>'
   1.862 +						else
   1.863 +							echo "$html"
   1.864 +						fi
   1.865 +						echo "</div>"
   1.866 +						;;
   1.867 +				esac
   1.868 +				rm -f $tmp
   1.869 +			else
   1.870 +				echo "<pre>File '$page' not exists!</pre>"
   1.871 +			fi
   1.872 +		else
   1.873 +			echo "<pre>Package '$pkg' not exists!</pre>"
   1.874  		fi
   1.875 -		find $dir -type f | while read file ; do
   1.876 -			[ -s $file ] || continue
   1.877 -			case "$file" in
   1.878 -			*.jp*g|*.png|*.gif|*.svg) continue
   1.879 -			esac
   1.880 -			file=${file#$dir/}
   1.881 -			echo "<a href='?$type=$pkg&amp;file=$file'>$(basename $file)</a>"
   1.882 -		done | sort -t \> -k 2
   1.883 -		echo "<h2>$(basename $page)</h2>"
   1.884 -		tmp="$(mktemp)"
   1.885 -		docat "$dir/$page" > $tmp
   1.886 -		[ -s "$tmp" ] && case "$type" in
   1.887 -		info)
   1.888 -			echo '<pre>'
   1.889 -			info2html < "$tmp"
   1.890 -			echo '</pre>' ;;
   1.891 -		doc)
   1.892 -			echo '<pre>'
   1.893 -			case "$page" in
   1.894 -			*.htm*)	cat ;;
   1.895 -			*)	sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
   1.896 -			esac < "$tmp"
   1.897 -			echo '</pre>' ;;
   1.898 -		man)
   1.899 -			export TEXTDOMAIN='man2html'
   1.900 -			./man2html "$tmp" | sed -e '1,/<header>/d' \
   1.901 -			-e 's|<a href="file:///[^>]*>\([^<]*\)</a>|\1|g' \
   1.902 -			-e 's|<a href="?[1-9]\+[^>]*>\([^<]*\)</a>|\1|g' ;;
   1.903 -		esac
   1.904 -		rm -f $tmp
   1.905  		;;
   1.906 +
   1.907  	*)
   1.908  		# We may have a toolchain.cgi script for cross cooker's
   1.909  		if [ -f "toolchain.cgi" ]; then
   1.910 @@ -593,56 +857,57 @@
   1.911  		pct=0
   1.912  		[ $inwok -gt 0 ] && pct=$(( ($cooked * 100) / $inwok ))
   1.913  		cat <<EOT
   1.914 -<div style="float: right;">
   1.915 -	<form method="get" action="$SCRIPT_NAME">
   1.916 -		Package:
   1.917 -		<input type="text" name="pkg" />
   1.918 -	</form>
   1.919 -</div>
   1.920 +<div id="content2">
   1.921 +
   1.922 +<form method="get" action="" class="r">
   1.923 +	<input type="search" name="pkg" placeholder="Package" list="packages" autocorrect="off" autocapitalize="off"/>
   1.924 +</form>
   1.925  
   1.926  <h2>Summary</h2>
   1.927  
   1.928 -<pre>
   1.929 -Running command  : $(running_command)
   1.930 -Wok revision     : <a href="$WOK_URL">$(cat $wokrev)</a>
   1.931 -Commits to cook  : $(cat $commits | wc -l)
   1.932 -Current cooklist : $(cat $cooklist | wc -l)
   1.933 -Broken packages  : $(cat $broken | wc -l)
   1.934 -Blocked packages : $(cat $blocked | wc -l)
   1.935 -</pre>
   1.936 +<table>
   1.937 +<tr><td>Running command</td><td>: $(running_command)</td></tr>
   1.938 +<tr><td>Wok revision</td><td>: <a href="$WOK_URL">$(cat $wokrev)</a></td></tr>
   1.939 +<tr><td>Commits to cook</td><td>: $(wc -l < $commits)</td></tr>
   1.940 +<tr><td>Current cooklist</td><td>: $(wc -l < $cooklist)</td></tr>
   1.941 +<tr><td>Broken packages</td><td>: $(wc -l < $broken)</td></tr>
   1.942 +<tr><td>Blocked packages</td><td>: $(wc -l < $blocked)</td></tr>
   1.943 +<tr><td>Architecture</td><td>: $ARCH, <a href="$toolchain">toolchain</a></td></tr>
   1.944 +<tr><td>Server date</td><td>: $(date -u '+%F %R %Z')</td></tr>
   1.945 +
   1.946 +</table>
   1.947  EOT
   1.948 +
   1.949  		[ -e $CACHE/cooker-request ] &&
   1.950 -		[ $CACHE/activity -nt $CACHE/cooker-request ] && cat <<EOT
   1.951 -<div style="float: right;">
   1.952 -	<a class="button" href="?poke">Poke cooker</a>
   1.953 -</div>
   1.954 -EOT
   1.955 +		[ $CACHE/activity -nt $CACHE/cooker-request ] &&
   1.956 +		echo '<a class="button r" href="?poke">Poke cooker</a>'
   1.957 +
   1.958  		cat <<EOT
   1.959 -<p class="info">
   1.960 -	Packages: $inwok in the wok | $cooked cooked | $unbuilt unbuilt |
   1.961 -	Server date: $(date -u '+%F %R %Z')
   1.962 -</p>
   1.963 +<p class="info">Packages: $inwok in the wok · $cooked cooked · $unbuilt unbuilt</p>
   1.964 +
   1.965  <div class="pctbar">
   1.966  	<div class="pct" style="width: ${pct}%;">${pct}%</div>
   1.967  </div>
   1.968  
   1.969  <p>
   1.970 -	Latest:
   1.971 -	<a href="?file=cookorder.log">cookorder.log</a>
   1.972 -	<a href="?file=commits.log">commits.log</a>
   1.973 -	<a href="?file=pkgdb.log">pkgdb.log</a>
   1.974 -	<a href="?file=installed.diff">installed.diff</a>
   1.975 -	- Architecture $ARCH:
   1.976 -	<a href="$toolchain">toolchain</a>
   1.977 +	Service logs:
   1.978 +	<a href="?file=cookorder.log">cookorder</a> ·
   1.979 +	<a href="?file=commits.log">commits</a> ·
   1.980 +	<a href="?file=pkgdb.log">pkgdb</a><!-- ·
   1.981 +	<a href="?file=installed.diff">installed.diff</a> -->
   1.982  </p>
   1.983  
   1.984  $(more_button activity "More activity" $CACHE/activity 12)
   1.985  <h2 id="activity">Activity</h2>
   1.986 -<pre>
   1.987 -$(tac $CACHE/activity | head -n 12 | syntax_highlighter activity)
   1.988 -</pre>
   1.989 +
   1.990 +<ul class="activity">
   1.991  EOT
   1.992  
   1.993 +		tac $CACHE/activity | head -n 12 | syntax_highlighter activity | \
   1.994 +		sed 's|cooker.cgi||; s|^|<li>|; s|$|</li>|'
   1.995 +
   1.996 +		echo '</ul>'
   1.997 +
   1.998  		[ -s $cooknotes ] && cat <<EOT
   1.999  $(more_button cooknotes "More notes" $cooknotes 12)
  1.1000  <h2 id="cooknotes">Cooknotes</h2>
  1.1001 @@ -653,40 +918,42 @@
  1.1002  
  1.1003  		[ -s $commits ] && cat <<EOT
  1.1004  <h2 id="commits">Commits</h2>
  1.1005 -<pre>
  1.1006 -$(cat $commits)
  1.1007 -</pre>
  1.1008 +<ul class="activity">
  1.1009 +$(sed 's|^|<li>|; s|$|</li>|' $commits)
  1.1010 +</ul>
  1.1011  EOT
  1.1012  
  1.1013  		[ -s $cooklist ] && cat <<EOT
  1.1014  $(more_button cooklist "Full cooklist" $cooklist 20)
  1.1015  <h2 id="cooklist">Cooklist</h2>
  1.1016 -<pre>
  1.1017 -$(cat $cooklist | head -n 20)
  1.1018 -</pre>
  1.1019 +<ul class="activity">
  1.1020 +$(head -n 20 $cooklist | sed 's|^|<li>|; s|$|</li>|')
  1.1021 +</ul>
  1.1022  EOT
  1.1023  
  1.1024  		[ -s $broken ] && cat <<EOT
  1.1025  $(more_button broken "All broken packages" $broken 20)
  1.1026  <h2 id="broken">Broken</h2>
  1.1027 -<pre>
  1.1028 -$(cat $broken | head -n 20 | sed s"#^[^']*#<a href='?pkg=\0'>\0</a>#"g)
  1.1029 -</pre>
  1.1030 +<ul class="activity">
  1.1031 +$(head -n 20 $broken | sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" | sed 's|^|<li>|; s|$|</li>|')
  1.1032 +</ul>
  1.1033  EOT
  1.1034  
  1.1035  		[ -s $blocked ] && cat <<EOT
  1.1036  <h2 id="blocked">Blocked</h2>
  1.1037 -<pre>
  1.1038 -$(cat $blocked | sed s"#^[^']*#<a href='?pkg=\0'>\0</a>#"g)
  1.1039 -</pre>
  1.1040 +<ul class="activity">
  1.1041 +$(sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" $blocked | sed 's|^|<li>|; s|$|</li>|')
  1.1042 +</ul>
  1.1043  EOT
  1.1044  
  1.1045  		cat <<EOT
  1.1046  <h2 id="lastcook">Latest cook</h2>
  1.1047 -<pre>
  1.1048 -$(list_packages | sed s"#^\([^']*\).* : #<span class='log-date'>\0</span>#"g)
  1.1049 -</pre>
  1.1050 +<ul class="activity">
  1.1051 +$(list_packages | sed "s|^.* :|<span class='log-date'>\0</span> <span style='white-space:nowrap'>|g; s|^|<li>|; s|$|</span></li>|")
  1.1052 +</ul>
  1.1053 +
  1.1054  EOT
  1.1055 +		datalist
  1.1056  	;;
  1.1057  esac
  1.1058  
  1.1059 @@ -699,7 +966,7 @@
  1.1060  <div id="footer">
  1.1061  	<a href="http://www.slitaz.org/">SliTaz Website</a>
  1.1062  	<a href="cooker.cgi">Cooker</a>
  1.1063 -	<a href="doc/cookutils/cookutils.en.html">Documentation</a>
  1.1064 +	<a href="doc/cookutils/cookutils.html">Documentation</a>
  1.1065  </div>
  1.1066  
  1.1067  </body>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/web/prism.css	Fri Mar 17 01:20:30 2017 +0200
     2.3 @@ -0,0 +1,123 @@
     2.4 +/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+asciidoc+bash+c+css-extras+diff+ini+markdown+perl+python */
     2.5 +/**
     2.6 + * okaidia theme for JavaScript, CSS and HTML
     2.7 + * Loosely based on Monokai textmate theme by http://www.monokai.nl/
     2.8 + * @author ocodia
     2.9 + */
    2.10 +
    2.11 +code[class*="language-"],
    2.12 +pre[class*="language-"] {
    2.13 +	color: #f8f8f2;
    2.14 +	background: none;
    2.15 +	text-shadow: 0 1px rgba(0, 0, 0, 0.3);
    2.16 +	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
    2.17 +	text-align: left;
    2.18 +	white-space: pre;
    2.19 +	word-spacing: normal;
    2.20 +	word-break: normal;
    2.21 +	word-wrap: normal;
    2.22 +	line-height: 1.5;
    2.23 +
    2.24 +	-moz-tab-size: 4;
    2.25 +	-o-tab-size: 4;
    2.26 +	tab-size: 4;
    2.27 +
    2.28 +	-webkit-hyphens: none;
    2.29 +	-moz-hyphens: none;
    2.30 +	-ms-hyphens: none;
    2.31 +	hyphens: none;
    2.32 +}
    2.33 +
    2.34 +/* Code blocks */
    2.35 +pre[class*="language-"] {
    2.36 +	padding: 1em;
    2.37 +	margin: .5em 0;
    2.38 +	overflow: auto;
    2.39 +	border-radius: 0.3em;
    2.40 +}
    2.41 +
    2.42 +:not(pre) > code[class*="language-"],
    2.43 +pre[class*="language-"] {
    2.44 +	background: #272822;
    2.45 +}
    2.46 +
    2.47 +/* Inline code */
    2.48 +:not(pre) > code[class*="language-"] {
    2.49 +	padding: .1em;
    2.50 +	border-radius: .3em;
    2.51 +	white-space: normal;
    2.52 +}
    2.53 +
    2.54 +.token.comment,
    2.55 +.token.prolog,
    2.56 +.token.doctype,
    2.57 +.token.cdata {
    2.58 +	color: slategray;
    2.59 +}
    2.60 +
    2.61 +.token.punctuation {
    2.62 +	color: #f8f8f2;
    2.63 +}
    2.64 +
    2.65 +.namespace {
    2.66 +	opacity: .7;
    2.67 +}
    2.68 +
    2.69 +.token.property,
    2.70 +.token.tag,
    2.71 +.token.constant,
    2.72 +.token.symbol,
    2.73 +.token.deleted {
    2.74 +	color: #f92672;
    2.75 +}
    2.76 +
    2.77 +.token.boolean,
    2.78 +.token.number {
    2.79 +	color: #ae81ff;
    2.80 +}
    2.81 +
    2.82 +.token.selector,
    2.83 +.token.attr-name,
    2.84 +.token.string,
    2.85 +.token.char,
    2.86 +.token.builtin,
    2.87 +.token.inserted {
    2.88 +	color: #a6e22e;
    2.89 +}
    2.90 +
    2.91 +.token.operator,
    2.92 +.token.entity,
    2.93 +.token.url,
    2.94 +.language-css .token.string,
    2.95 +.style .token.string,
    2.96 +.token.variable {
    2.97 +	color: #f8f8f2;
    2.98 +}
    2.99 +
   2.100 +.token.atrule,
   2.101 +.token.attr-value,
   2.102 +.token.function {
   2.103 +	color: #e6db74;
   2.104 +}
   2.105 +
   2.106 +.token.keyword {
   2.107 +	color: #66d9ef;
   2.108 +}
   2.109 +
   2.110 +.token.regex,
   2.111 +.token.important {
   2.112 +	color: #fd971f;
   2.113 +}
   2.114 +
   2.115 +.token.important,
   2.116 +.token.bold {
   2.117 +	font-weight: bold;
   2.118 +}
   2.119 +.token.italic {
   2.120 +	font-style: italic;
   2.121 +}
   2.122 +
   2.123 +.token.entity {
   2.124 +	cursor: help;
   2.125 +}
   2.126 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/web/prism.js	Fri Mar 17 01:20:30 2017 +0200
     3.3 @@ -0,0 +1,16 @@
     3.4 +/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+asciidoc+bash+c+css-extras+diff+ini+makefile+markdown+perl+python */
     3.5 +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function(e){var t=n.util.type(e);switch(t){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=n.util.clone(e[r]));return a;case"Array":return e.map&&e.map(function(e){return n.util.clone(e)})}return e}},languages:{extend:function(e,t){var a=n.util.clone(n.languages[e]);for(var r in t)a[r]=t[r];return a},insertBefore:function(e,t,a,r){r=r||n.languages;var l=r[e];if(2==arguments.length){a=arguments[1];for(var i in a)a.hasOwnProperty(i)&&(l[i]=a[i]);return l}var o={};for(var s in l)if(l.hasOwnProperty(s)){if(s==t)for(var i in a)a.hasOwnProperty(i)&&(o[i]=a[i]);o[s]=l[s]}return n.languages.DFS(n.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=o)}),r[e]=o},DFS:function(e,t,a,r){r=r||{};for(var l in e)e.hasOwnProperty(l)&&(t.call(e,l,e[l],a||l),"Object"!==n.util.type(e[l])||r[n.util.objId(e[l])]?"Array"!==n.util.type(e[l])||r[n.util.objId(e[l])]||(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,l,r)):(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,null,r)))}},plugins:{},highlightAll:function(e,t){var a={callback:t,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};n.hooks.run("before-highlightall",a);for(var r,l=a.elements||document.querySelectorAll(a.selector),i=0;r=l[i++];)n.highlightElement(r,e===!0,a.callback)},highlightElement:function(t,a,r){for(var l,i,o=t;o&&!e.test(o.className);)o=o.parentNode;o&&(l=(o.className.match(e)||[,""])[1].toLowerCase(),i=n.languages[l]),t.className=t.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=t.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var s=t.textContent,u={element:t,language:l,grammar:i,code:s};if(n.hooks.run("before-sanity-check",u),!u.code||!u.grammar)return u.code&&(u.element.textContent=u.code),n.hooks.run("complete",u),void 0;if(n.hooks.run("before-highlight",u),a&&_self.Worker){var g=new Worker(n.filename);g.onmessage=function(e){u.highlightedCode=e.data,n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(u.element),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},g.postMessage(JSON.stringify({language:u.language,code:u.code,immediateClose:!0}))}else u.highlightedCode=n.highlight(u.code,u.grammar,u.language),n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(t),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},highlight:function(e,t,r){var l=n.tokenize(e,t);return a.stringify(n.util.encode(l),r)},tokenize:function(e,t){var a=n.Token,r=[e],l=t.rest;if(l){for(var i in l)t[i]=l[i];delete t.rest}e:for(var i in t)if(t.hasOwnProperty(i)&&t[i]){var o=t[i];o="Array"===n.util.type(o)?o:[o];for(var s=0;s<o.length;++s){var u=o[s],g=u.inside,c=!!u.lookbehind,h=!!u.greedy,f=0,d=u.alias;if(h&&!u.pattern.global){var p=u.pattern.toString().match(/[imuy]*$/)[0];u.pattern=RegExp(u.pattern.source,p+"g")}u=u.pattern||u;for(var m=0,y=0;m<r.length;y+=r[m].length,++m){var v=r[m];if(r.length>e.length)break e;if(!(v instanceof a)){u.lastIndex=0;var b=u.exec(v),k=1;if(!b&&h&&m!=r.length-1){if(u.lastIndex=y,b=u.exec(e),!b)break;for(var w=b.index+(c?b[1].length:0),_=b.index+b[0].length,P=m,A=y,j=r.length;j>P&&_>A;++P)A+=r[P].length,w>=A&&(++m,y=A);if(r[m]instanceof a||r[P-1].greedy)continue;k=P-m,v=e.slice(y,A),b.index-=y}if(b){c&&(f=b[1].length);var w=b.index+f,b=b[0].slice(f),_=w+b.length,x=v.slice(0,w),O=v.slice(_),S=[m,k];x&&S.push(x);var N=new a(i,g?n.tokenize(b,g):b,d,b,h);S.push(N),O&&S.push(O),Array.prototype.splice.apply(r,S)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==l.type&&(l.attributes.spellcheck="true"),e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,"&quot;")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+"</"+l.tag+">"},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,!document.addEventListener||n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
     3.6 +Prism.languages.markup={comment:/<!--[\w\W]*?-->/,prolog:/<\?[\w\W]+?\?>/,doctype:/<!DOCTYPE[\w\W]+?>/i,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&amp;/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup;
     3.7 +Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));
     3.8 +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/};
     3.9 +Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript;
    3.10 +!function(a){var i={pattern:/(^[ \t]*)\[(?!\[)(?:(["'$`])(?:(?!\2)[^\\]|\\.)*\2|\[(?:[^\]\\]|\\.)*\]|[^\]\\]|\\.)*\]/m,lookbehind:!0,inside:{quoted:{pattern:/([$`])(?:(?!\1)[^\\]|\\.)*\1/,inside:{punctuation:/^[$`]|[$`]$/}},interpreted:{pattern:/'(?:[^'\\]|\\.)*'/,inside:{punctuation:/^'|'$/}},string:/"(?:[^"\\]|\\.)*"/,variable:/\w+(?==)/,punctuation:/^\[|\]$|,/,operator:/=/,"attr-value":/(?!^\s+$).+/}};a.languages.asciidoc={"comment-block":{pattern:/^(\/{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1/m,alias:"comment"},table:{pattern:/^\|={3,}(?:(?:\r?\n|\r).*)*?(?:\r?\n|\r)\|={3,}$/m,inside:{specifiers:{pattern:/(?!\|)(?:(?:(?:\d+(?:\.\d+)?|\.\d+)[+*])?(?:[<^>](?:\.[<^>])?|\.[<^>])?[a-z]*)(?=\|)/,alias:"attr-value"},punctuation:{pattern:/(^|[^\\])[|!]=*/,lookbehind:!0}}},"passthrough-block":{pattern:/^(\+{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^\++|\++$/}},"literal-block":{pattern:/^(-{4,}|\.{4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\.+)|(?:-+|\.+)$/}},"other-block":{pattern:/^(--|\*{4,}|_{4,}|={4,})(?:\r?\n|\r)(?:[\s\S]*(?:\r?\n|\r))??\1$/m,inside:{punctuation:/^(?:-+|\*+|_+|=+)|(?:-+|\*+|_+|=+)$/}},"list-punctuation":{pattern:/(^[ \t]*)(?:-|\*{1,5}|\.{1,5}|(?:[a-z]|\d+)\.|[xvi]+\))(?= )/im,lookbehind:!0,alias:"punctuation"},"list-label":{pattern:/(^[ \t]*)[a-z\d].+(?::{2,4}|;;)(?=\s)/im,lookbehind:!0,alias:"symbol"},"indented-block":{pattern:/((\r?\n|\r)\2)([ \t]+)\S.*(?:(?:\r?\n|\r)\3.+)*(?=\2{2}|$)/,lookbehind:!0},comment:/^\/\/.*/m,title:{pattern:/^.+(?:\r?\n|\r)(?:={3,}|-{3,}|~{3,}|\^{3,}|\+{3,})$|^={1,5} +.+|^\.(?![\s.]).*/m,alias:"important",inside:{punctuation:/^(?:\.|=+)|(?:=+|-+|~+|\^+|\++)$/}},"attribute-entry":{pattern:/^:[^:\r\n]+:(?: .*?(?: \+(?:\r?\n|\r).*?)*)?$/m,alias:"tag"},attributes:i,hr:{pattern:/^'{3,}$/m,alias:"punctuation"},"page-break":{pattern:/^<{3,}$/m,alias:"punctuation"},admonition:{pattern:/^(?:TIP|NOTE|IMPORTANT|WARNING|CAUTION):/m,alias:"keyword"},callout:[{pattern:/(^[ \t]*)<?\d*>/m,lookbehind:!0,alias:"symbol"},{pattern:/<\d+>/,alias:"symbol"}],macro:{pattern:/\b[a-z\d][a-z\d-]*::?(?:(?:\S+)??\[(?:[^\]\\"]|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:{"function":/^[a-z\d-]+(?=:)/,punctuation:/^::?/,attributes:{pattern:/(?:\[(?:[^\]\\"]|(["'])(?:(?!\1)[^\\]|\\.)*\1|\\.)*\])/,inside:i.inside}}},inline:{pattern:/(^|[^\\])(?:(?:\B\[(?:[^\]\\"]|(["'])(?:(?!\2)[^\\]|\\.)*\2|\\.)*\])?(?:\b_(?!\s)(?: _|[^_\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: _|[^_\\\r\n]|\\.)+)*_\b|\B``(?!\s).+?(?:(?:\r?\n|\r).+?)*''\B|\B`(?!\s)(?: ['`]|.)+?(?:(?:\r?\n|\r)(?: ['`]|.)+?)*['`]\B|\B(['*+#])(?!\s)(?: \3|(?!\3)[^\\\r\n]|\\.)+(?:(?:\r?\n|\r)(?: \3|(?!\3)[^\\\r\n]|\\.)+)*\3\B)|(?:\[(?:[^\]\\"]|(["'])(?:(?!\4)[^\\]|\\.)*\4|\\.)*\])?(?:(__|\*\*|\+\+\+?|##|\$\$|[~^]).+?(?:(?:\r?\n|\r).+?)*\5|\{[^}\r\n]+\}|\[\[\[?.+?(?:(?:\r?\n|\r).+?)*\]?\]\]|<<.+?(?:(?:\r?\n|\r).+?)*>>|\(\(\(?.+?(?:(?:\r?\n|\r).+?)*\)?\)\)))/m,lookbehind:!0,inside:{attributes:i,url:{pattern:/^(?:\[\[\[?.+?\]?\]\]|<<.+?>>)$/,inside:{punctuation:/^(?:\[\[\[?|<<)|(?:\]\]\]?|>>)$/}},"attribute-ref":{pattern:/^\{.+\}$/,inside:{variable:{pattern:/(^\{)[a-z\d,+_-]+/,lookbehind:!0},operator:/^[=?!#%@$]|!(?=[:}])/,punctuation:/^\{|\}$|::?/}},italic:{pattern:/^(['_])[\s\S]+\1$/,inside:{punctuation:/^(?:''?|__?)|(?:''?|__?)$/}},bold:{pattern:/^\*[\s\S]+\*$/,inside:{punctuation:/^\*\*?|\*\*?$/}},punctuation:/^(?:``?|\+{1,3}|##?|\$\$|[~^]|\(\(\(?)|(?:''?|\+{1,3}|##?|\$\$|[~^`]|\)?\)\))$/}},replacement:{pattern:/\((?:C|TM|R)\)/,alias:"builtin"},entity:/&#?[\da-z]{1,8};/i,"line-continuation":{pattern:/(^| )\+$/m,lookbehind:!0,alias:"punctuation"}},i.inside.interpreted.inside.rest={macro:a.languages.asciidoc.macro,inline:a.languages.asciidoc.inline,replacement:a.languages.asciidoc.replacement,entity:a.languages.asciidoc.entity},a.languages.asciidoc["passthrough-block"].inside.rest={macro:a.languages.asciidoc.macro},a.languages.asciidoc["literal-block"].inside.rest={callout:a.languages.asciidoc.callout},a.languages.asciidoc.table.inside.rest={"comment-block":a.languages.asciidoc["comment-block"],"passthrough-block":a.languages.asciidoc["passthrough-block"],"literal-block":a.languages.asciidoc["literal-block"],"other-block":a.languages.asciidoc["other-block"],"list-punctuation":a.languages.asciidoc["list-punctuation"],"indented-block":a.languages.asciidoc["indented-block"],comment:a.languages.asciidoc.comment,title:a.languages.asciidoc.title,"attribute-entry":a.languages.asciidoc["attribute-entry"],attributes:a.languages.asciidoc.attributes,hr:a.languages.asciidoc.hr,"page-break":a.languages.asciidoc["page-break"],admonition:a.languages.asciidoc.admonition,"list-label":a.languages.asciidoc["list-label"],callout:a.languages.asciidoc.callout,macro:a.languages.asciidoc.macro,inline:a.languages.asciidoc.inline,replacement:a.languages.asciidoc.replacement,entity:a.languages.asciidoc.entity,"line-continuation":a.languages.asciidoc["line-continuation"]},a.languages.asciidoc["other-block"].inside.rest={table:a.languages.asciidoc.table,"list-punctuation":a.languages.asciidoc["list-punctuation"],"indented-block":a.languages.asciidoc["indented-block"],comment:a.languages.asciidoc.comment,"attribute-entry":a.languages.asciidoc["attribute-entry"],attributes:a.languages.asciidoc.attributes,hr:a.languages.asciidoc.hr,"page-break":a.languages.asciidoc["page-break"],admonition:a.languages.asciidoc.admonition,"list-label":a.languages.asciidoc["list-label"],macro:a.languages.asciidoc.macro,inline:a.languages.asciidoc.inline,replacement:a.languages.asciidoc.replacement,entity:a.languages.asciidoc.entity,"line-continuation":a.languages.asciidoc["line-continuation"]},a.languages.asciidoc.title.inside.rest={macro:a.languages.asciidoc.macro,inline:a.languages.asciidoc.inline,replacement:a.languages.asciidoc.replacement,entity:a.languages.asciidoc.entity},a.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&amp;/,"&"))})}(Prism);
    3.11 +!function(e){var t={variable:[{pattern:/\$?\(\([\w\W]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\w\W]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},"boolean":{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<<?|>>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism);
    3.12 +Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(define|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"];
    3.13 +Prism.languages.css.selector={pattern:/[^\{\}\s][^\{\}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:\.\w]+/,id:/#[-:\.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,6}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%\.]+/});
    3.14 +Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}};
    3.15 +Prism.languages.ini={comment:/^[ \t]*;.*$/m,selector:/^[ \t]*\[.*?\]/m,constant:/^[ \t]*[^\s=]+?(?=[ \t]*=)/m,"attr-value":{pattern:/=.*/,inside:{punctuation:/^[=]/}}};
    3.16 +Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|.)*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^[^:=\r\n]+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/};
    3.17 +Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold);
    3.18 +Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:[^\\]|\\.)*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?((::)*'?(?!\d)[\w$]+)+(::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(\.\d+)*|\d+(\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b-?(0x[\dA-Fa-f](_?[\dA-Fa-f])*|0b[01](_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/};
    3.19 +Prism.languages.python={"triple-quoted-string":{pattern:/"""[\s\S]+?"""|'''[\s\S]+?'''/,alias:"string"},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/("|')(?:\\\\|\\?[^\\\r\n])*?\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,"boolean":/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/};
     4.1 --- a/web/style.css	Fri Mar 17 00:44:10 2017 +0200
     4.2 +++ b/web/style.css	Fri Mar 17 01:20:30 2017 +0200
     4.3 @@ -1,46 +1,67 @@
     4.4  /* CSS style for SliTaz Cooker */
     4.5  
     4.6 -html { min-height: 102%; }
     4.7 -body { font: 13px sans-serif, vernada, arial; margin: 0; }
     4.8 -h1 { margin: 0; padding: 8px; color: #fff; font-size: 20px; }
     4.9 -h1 a { color: #fff; text-decoration: none; }
    4.10 -h2 { color: #444; }
    4.11 +body {
    4.12 +	font-family: sans-serif;
    4.13 +	font-size: 13px;
    4.14 +	margin: 0;
    4.15 +	min-height: 100%;
    4.16 +/*	position: absolute;*/
    4.17 +	left: 0;
    4.18 +	right: 0;
    4.19 +}
    4.20 +#content2 h2 {
    4.21 +	color: #444;
    4.22 +	border-bottom: 2px solid #CCC;
    4.23 +	height: 100%;
    4.24 +}
    4.25  h3 { color: #666; font-size: 140%; }
    4.26 -a { text-decoration: underline; color: #215090; }
    4.27 -a:hover { text-decoration: none; }
    4.28 -hr { margin: 0; border: 1px solid #cfcfcf; }
    4.29 +a { text-decoration: none; color: #215090; }
    4.30 +a:hover { text-decoration: underline; }
    4.31 +.files a { text-decoration: none; color: inherit; }
    4.32 +.files a:hover { text-decoration: underline; }
    4.33 +hr { margin: 0; border: 1px solid #CFCFCF; }
    4.34  pre {
    4.35 -	background-color: #f8f8f8;
    4.36 -	border: 1px solid #ddd;
    4.37 -	padding: 10px;
    4.38 +	background-color: #F8F8F8;
    4.39 +	border: 1px solid #DDD;
    4.40 +	padding: 8px;
    4.41  	overflow: auto;
    4.42 -	font-size: 96%;
    4.43  }
    4.44  
    4.45  /* Header */
    4.46  
    4.47  #header {
    4.48 -	color: #fff;
    4.49 +	color: #FFF;
    4.50  	background: #222;
    4.51  	height: 40px;
    4.52 -	border-bottom: 4px solid #afafaf;
    4.53 +	border-bottom: 3px solid #AAA;
    4.54  }
    4.55  
    4.56  #header h1 {
    4.57  	margin: 0;
    4.58 -	/* padding: 8px 0 0 42px; */
    4.59 +	padding: 8px 0 0 42px;
    4.60 +	color: #FFF;
    4.61 +	font-size: 20px;
    4.62  	width: 250px;
    4.63  }
    4.64 +#logo {
    4.65 +	background: url(/images/logo.png) no-repeat left;
    4.66 +	position: absolute;
    4.67 +	float: left;
    4.68 +	left: 0px;
    4.69 +	top: 0px;
    4.70 +	width: 40px;
    4.71 +	height: 40px;
    4.72 +}
    4.73  
    4.74  #header h1 a {
    4.75 -	color: #fff;
    4.76 +	color: #FFF;
    4.77  	text-decoration: none;
    4.78  	font-size: 20px;
    4.79  	font-style: italic;
    4.80  }
    4.81  
    4.82  #header h1 a:hover, #network a:hover {
    4.83 -	color: #afafaf;
    4.84 +	color: #AFAFAF;
    4.85  }
    4.86  
    4.87  /* Header links */
    4.88 @@ -53,7 +74,7 @@
    4.89  
    4.90  #network a {
    4.91  	padding: 0 4px;
    4.92 -	color: #fff;
    4.93 +	color: #FFF;
    4.94  	font-weight: bold;
    4.95  	text-decoration: none;
    4.96  }
    4.97 @@ -61,26 +82,33 @@
    4.98  /* Content */
    4.99  
   4.100  #content {
   4.101 -	margin: 40px 80px;
   4.102 -	text-align: justify;
   4.103 +	margin: auto;
   4.104 +	padding: 0.5em;
   4.105 +}
   4.106 +#content2 {
   4.107 +	width: 100%;
   4.108 +	max-width: 700px;
   4.109 +	margin: auto;
   4.110 +	padding: 0.5em;
   4.111  }
   4.112  
   4.113 -.span-ok    { color: #0a0; }
   4.114 +
   4.115 +.span-ok    { color: #0A0; }
   4.116  .span-red   { color: red; }
   4.117  .span-sky   { color: blue; }
   4.118 -.span-no    { color: #d90; }
   4.119 +.span-no    { color: #D90; }
   4.120  .span-line  { color: #888; }
   4.121  .log-date   { color: #666; font-size: 95%; }
   4.122 -.sh-comment { color: #a00; }
   4.123 -.sh-val     { color: #e50; font-weight: bold; }
   4.124 -.var        { color: #05a; }
   4.125 +.sh-comment { color: #A00; }
   4.126 +.sh-val     { color: #E50; font-weight: bold; }
   4.127 +.var        { color: #05A; }
   4.128  
   4.129  /* Buttons */
   4.130  
   4.131  .button {
   4.132 -	cursor: pointer;
   4.133 +	display: inline-block;
   4.134  	padding: 4px;
   4.135 -	margin: 4px 0px;
   4.136 +	margin: 2px 0;
   4.137  }
   4.138  
   4.139  a.button, .pctbar  {
   4.140 @@ -88,39 +116,81 @@
   4.141  	color: #666;
   4.142  }
   4.143  
   4.144 +.pct {
   4.145 +	background: #9DFF4A;
   4.146 +	background-image: -webkit-linear-gradient(#CDFFA3, #9DFF4A 40%, #87DB40);
   4.147 +	background-image:    -moz-linear-gradient(#CDFFA3, #9DFF4A 40%, #87DB40);
   4.148 +	padding: 2px 4px;
   4.149 +}
   4.150 +.pctbar { overflow: hidden; }
   4.151 +
   4.152 +.button {
   4.153 +	text-decoration: none;
   4.154 +	color: #444;
   4.155 +	border: 1px solid #666;
   4.156 +	font-size: 14px;
   4.157 +	line-height: 1.2em;
   4.158 +}
   4.159  .button:hover {
   4.160 -	border: 1px solid #999;
   4.161 +	color: #000;
   4.162 +	border-color: #000;
   4.163 +}
   4.164 +.button.active {
   4.165 +	/*outline: 1px solid #999;
   4.166 +	outline-offset: 1px;*/
   4.167 +	color: #000;
   4.168 +	border-color: #000;
   4.169  }
   4.170  
   4.171 -.pct { background: #9dff4a; padding: 2px 4px; }
   4.172 -.pctbar { overflow: hidden; }
   4.173 -
   4.174 -.button, .pctbar {
   4.175 -	border: 1px solid #cccccc;
   4.176 +.pctbar {
   4.177 +	border: 1px solid #AAA;
   4.178  	font-size: 14px;
   4.179  	line-height: 1.2em;
   4.180 -	background-image: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);
   4.181 -	background-image: -moz-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);
   4.182 -	-webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
   4.183 -	-moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
   4.184 -	box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
   4.185 +	background-image: -webkit-linear-gradient(#E5E5E5, #F4F4F4 40%, #FAFAFA);
   4.186 +	background-image: -moz-linear-gradient(#E5E5E5, #F4F4F4 40%, #FAFAFA);
   4.187  }
   4.188 -
   4.189  /* Round corner */
   4.190  
   4.191  pre, .button, .pctbar {
   4.192 -	-moz-border-radius: 4px;
   4.193 -	-webkit-border-radius: 4px;
   4.194 -	border-radius: 4px;
   4.195 +	border-radius: 2px;
   4.196  }
   4.197  
   4.198  /* Footer */
   4.199  
   4.200  #footer {
   4.201  	text-align: center;
   4.202 -	padding: 20px;
   4.203 -	border-top: 1px solid #ddd;
   4.204 +	padding: 20px 0;
   4.205 +	border-top: 1px solid #DDD;
   4.206  	font-size: 90%;
   4.207 +/*	position: absolute;*/
   4.208 +	bottom: 0;
   4.209 +	left: 0;
   4.210 +	right: 0;
   4.211  }
   4.212  
   4.213  #footer a { padding: 0 2px; }
   4.214 +
   4.215 +.log a { text-decoration: none; color: #666; }
   4.216 +.log a:hover { color: #000; }
   4.217 +
   4.218 +.activity { padding-left: 0.5em; }
   4.219 +.activity li { list-style-type: none; }
   4.220 +.activity li::before { color: #666; content: "•"; padding-right: 0.5em; }
   4.221 +
   4.222 +.r { float: right; }
   4.223 +
   4.224 +.zebra tr:nth-child(odd)  { background-color: #FFFFFF; }
   4.225 +.zebra tr:nth-child(even) { background-color: #ECECEC; }
   4.226 +
   4.227 +.gray   { background-color: lightgray; }
   4.228 +.gold   { background-color: gold; }
   4.229 +.green  { background-color: greenyellow; }
   4.230 +.sky    { background-color: skyblue; }
   4.231 +.plum   { background-color: plum; }
   4.232 +.yellow { background-color: yellow; }
   4.233 +.khaki  { background-color: khaki; }
   4.234 +.brown  { background-color: sandybrown; }
   4.235 +
   4.236 +a:target {background-color: yellow; }
   4.237 +
   4.238 +pre.info { color: #FFF; background-color: #272822; }