diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/assets/nuweb/mdlio-app.css b/assets/nuweb/mdlio-app.css new file mode 100755 index 0000000..8e25c0a --- /dev/null +++ b/assets/nuweb/mdlio-app.css @@ -0,0 +1,332 @@ +@font-face { + font-family: "Material Design Icons"; + src: url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.eot?v=1.9.32"); + src: url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.eot?#iefix&v=1.9.32") format("embedded-opentype"), url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.woff2?v=1.9.32") format("woff2"), url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.woff?v=1.9.32") format("woff"), url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.ttf?v=1.9.32") format("truetype"), url("https://cdn.materialdesignicons.com/1.9.32/fonts/materialdesignicons-webfont.svg?v=1.9.32#materialdesigniconsregular") format("svg"); + font-weight: normal; + font-style: normal; +} + +.item .mdl-card_title { + padding: 8px; + width: calc( 100% - 16px ); +} +.item .mdl-card__title-text { + text-decoration:none; + font-family: "Roboto","Helvetica","Arial",sans-serif +} + + +.item.type-image.thumb .card-no-media { + display:none; +} + +.item.type-image.thumb:hover .card-no-media { + display:block; +} + +.item.type-person.thumb .card-title-wrapper { + height:0px; + position:relative; + overflow:visible; +} + + +.item .card-title-body { + width: 100%; + + +} + +.item.type-person.thumb .card-title-body, +.item.type-image.thumb .card-title-body { + background: rgba(0,0,0,0.25); + color: #fff; + text-shadow: 0px 0px 7px rgba(0, 0, 0, 1); + bottom: 0px; + position: absolute; +} + +.item.type-image.thumb .card-title-body { + display:none; +} + +.item.type-person:hover .card-title-body, +.item.type-image:hover .card-title-body { + display: block; +} + +input.material-icons[type="submit"] { + font-family: "Material Icons"; +} + +.file .mdl-card_title-text { + word-break:break-all; +} + + +.file .title:before { + font-family: "Material Design Icons"; + margin-right:8px; + content: "\f214"; +} + +.file.type-directory .title:before { + content: "\f24b"; +} + +.file.type-person .title:before { + content: "\f004"; +} + +.file.type-image .title:before { + + content: "\f21f"; +} + +.file.type-video .title:before { + content: "\f22b"; +} + +.file[data-mime="application/pdf"] .title:before { + content: "\f225" +} + + + +.item .mdl-card.as-dialog { + position:fixed; + display:block; + top:100px; + /* max-width: 960px; */ + width: calc( 100% - 140px); + height: calc( 100% - 140px); + z-index:6; +} + +.item .mdl-card.as-dialog:before { + position:fixed; + display:block; + top:0px; + left:0px; + background:#000; + width:10%; + height:10%; + z-index:5; + content:""; +} + + + + + +.selection-bar { + display:block !important; + opacity:0; + transform: translateY(-70px); +} + + +.selection-bar, +.selection-bar .mdl-layout__drawer-button { + color:rgba(0,0,0,.87); +} + +.selection-mode .selection-bar { + display:block; + transform: translateY(0px); + opacity:1; +} + +.selection-mode .selectable .action.select, +.selectable:hover .action.select { + display:block; + opacity:1; +} + +.selectable>.action.select { + position:absolute; + left:-8px; + top:-12px; + background: #fff; + border-radius: 50%; + width:24px; + height:24px; + min-width:24px; + box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); + z-index: 2; + + /*display:none;*/ + opacity:0; +} + +.selection-bar, +.selectable .action.select { + transition: transform 0.3s ease, opacity 0.3s ease; +} + +.item .mdl-card__actions { + display:none; +} + +.mdl-card.upgraded .mdl-card__actions { + display:block; +} + + + + +.action.pin { + /* position:absolute; */ + /* top:0px; */ + /* right: 8px; */ +} + +.action.pin:before { + font-family: "Material Design Icons"; + content: "\f403"; + line-height:24px; +} + + +.item .mdl-card__actions { + text-align:right; + visibility: hidden; + opacity:0; + transition: transform 0.3s ease, opacity 0.3s ease; + +} + +.item .action.select i.material-icons { + font-size:14px; +} + +.item.selected { + background:#555; + /*outline: 1px solid #555;*/ + box-shadow: 0 0 8px rgba(0,0,0,0.87); +} + + + +.item:hover .mdl-card__actions { + visibility: visible; + opacity:1; +} + + +.item.selected .action.select { + background: #555; + color: #fff; + display:block; +} + +.item .mdl-button--icon { + min-width:32px; +} + +.gallery { + width: calc(100% - 16px); + padding: 0px; +} + +.breadcrumb { + margin-top: 24px; + display:block; +} +.breadcrumb + h1 { + margin-top:0px; +} + + +.gallery .item.mdl-card { + min-height: auto; +} + +.gallery .item .mdl-card_media img { + width:100%; + height:auto; +} + +.gallery .item.no-thumb .mdl-card_media a { + display: block; + /*min-height: 100px;*/ + width:100%; + background: rgba(255,255,255,0.25); + text-decoration:none; + color:#fff; + vertical-align: middle; + text-align: center; +} + +.item .mdl-card { + width:100%; + min-height:48px; +} + +/* +.gallery .item.no-thumb.type-directory .mdl-card_media a::before { + content: "folder"; + font-family: "Material Icons"; + margin-right:8px; + font-size:128px; + line-height:128px; + text-decoration:none; + +} +*/ + +.main-width { + max-width: 960px; + margin: auto; + position: relative; +} + +@media (max-width: 976px) { + .main-width { + margin:0 8px; + } +} + + +#scooter { + position: absolute; + overflow: hidden; + top:0px; + width:100%; + bottom:0px; + height:0px; +} + +#sizer { + background:rgba(0,0,0,0.10); + position:relative; + height:100%; +} + +#sizer .gutter { + background:rgba(0,0,0,0.1); + height:100%; +} + +/* Layout Hack */ + +.mdl-layout { + overflow: visible; +} +.mdl-layout__drawer { + position: fixed; +} +.mdl-layout__content { + display: block; + overflow: visible; + margin-top: 64px; +} +.is-small-screen .mdl-layout__content { + margin-top: 56px; +} +.mdl-layout__header { + position: fixed; +} +.mdl-layout__obfuscator { + position: fixed; +} diff --git a/assets/nuweb/mdlio-app.js b/assets/nuweb/mdlio-app.js new file mode 100755 index 0000000..1f7aed0 --- /dev/null +++ b/assets/nuweb/mdlio-app.js @@ -0,0 +1,444 @@ +window.mdlio = { + + outlayer: function(outlayer) { + this.outlayers = []; + if (outlayer) { + if (Array.isArray(outlayer)) { + for (var e of outlayer) { + this.outlayers.push(e); + } + } else { + this.outlayers.push(outlayer); + } + } + this.add = function(outlayer) { + this.outlayers.push(outlayer); + } + ; + this.appended = function(items) { + mdlio.upgrade.appended(items); + for (outlayer of this.outlayers) { + outlayer.appended(items); + } + }; + }, + cards: { + upgrade: function(element) { + element.querySelectorAll(".mdl-card").forEach(mdlio.cards.upgradeCard) + }, + upgradeCard: function(card) { + console.log(card); + + if(card.querySelector(".mdl-card_title")) { + card.classList.add("has-title"); + } + if(card.querySelector(".mdl-card__actions")) { + card.classList.add("has-actions"); + } + + const parent=card.parentNode; + const as=card.querySelector(".action.select"); + + /*if(parent.matches(".card-wrapper") && as) { + parent.appendChild(as); + }*/ + + card.classList.remove("upgradeable"); + card.classList.add("upgraded"); + + }, + }, + lightbox: function(grid, selector, options) { + var pswpElement = document.querySelectorAll('.pswp')[0]; + if (pswpElement == null ) { + pswpElement = mdlio.addPSWP(); + } + /*this.box = $(grid).find(selector).simpleLightbox(options); */ + var items = []; + this.items = items; + const linkClicked = function(e) { + console.log(this, this.lboxId); + e.preventDefault(); + var options = { + index: this.lboxId + }; + var gallery = new PhotoSwipe(pswpElement,PhotoSwipeUI_Default,items,options); + gallery.init(); + }; + this.appended = function(appendedItems) { + //this.box.destroy(); + for (var item of appendedItems) { + var link = item.querySelector(selector); + if (link == null ) { + continue; + } + var img = link.querySelector('img'); + var width = img.naturalWidth; + var height = img.naturalHeight; + var maybeSize = link.getAttribute('data-img-size'); + if (maybeSize) { + console.log(maybeSize); + [ width , height ] = maybeSize.split('x').map(function(x) { + return Number.parseInt(x); + }); + } + var slide = { + msrc: img.getAttribute('src'), + src: link.getAttribute('href'), + w: width, + h: height + }; + console.log(slide); + var slideId = items.push(slide) - 1; + var links = item.querySelectorAll(selector); + for (link of links) { + if (link.getAttribute('href') == slide.src) { + link.lboxId = slideId; + link.addEventListener("click", linkClicked); + } + } + } + //this.box = $(grid).find(selector).simpleLightbox(options); + } + }, + infiniteScroll: function(grid, item, nextPage, outlayer) { + var outlayers = new mdlio.outlayer(outlayer); + var infScroll = new InfiniteScroll(grid,{ + path: nextPage, + hideNav: nextPage, + append: item, + outlayer: outlayers, + status: '.page-load-status', + scrollThresold: 100, + prefill: true //elementScroll: '.mdl-layout__content', + }); + infScroll.outlayers = outlayers; + return infScroll; + }, + cardsGallery: function(grid, item, lightboxItem) { + const lightbox = new mdlio.lightbox(grid,lightboxItem + " a"); + const msnry = new Masonry(grid,{ + itemSelector: 'none', + // select none at first + columnWidth: document.querySelector('#gutter'), + gutter: 0, + containerStyle: { + width: 'calc(100% - 16px)', + padding: '0px', + position: 'relative' + }, + percentPosition: true, + // nicer reveal transition + visibleStyle: { + transform: 'translateY(0)', + opacity: 1 + }, + hiddenStyle: { + transform: 'translateY(100px)', + opacity: 0 + }, + }); + this.lightbox = lightbox; + this.masonry = msnry; + imagesLoaded(grid, function() { + grid.classList.remove('are-images-unloaded'); + msnry.options.itemSelector = item; + var items = grid.querySelectorAll(item); + lightbox.appended(items); + msnry.appended(items); + }); + if (document.querySelector(".next-page")) { + this.infiniteScroll = new mdlio.infiniteScroll(grid,item,'.next-page',[msnry, this.lightbox]); + } + }, + addPSWP: function() { + var body = document.querySelector('body'); + var pswp = document.createElement('div'); + pswp.classList.add('pswp'); + pswp.innerHTML = ` +
+ +
-## Sets HTTP response status code.
-## NOTE: If any content was already returned this function does not work.
-##
-nuweb.status() {
- local code=$1;
- local message=$2;
- echo "HTTP/1.1 $code $message"
-}
-
-## nuweb.content_type::
-## Sets HTTP response content type
-## NOTE: If any content was already returned this function does not work.
-nuweb.content_type() {
- echo "Content-Type: $@"
-}
-
-## nuweb.redirect:: [--relative]
-##
-nuweb.redirect() {
- local prefix="";
- if [ "$1" == "--relative" ]; then
- shift;
- prefix="$(dirname "$SCRIPT_NAME")/"
- fi
-
- echo Location: "$prefix$@"
- echo
- echo
-}
-
-## nuweb.redirect.exec::
-##
-nuweb.redirect.exec() {
- if [ "$1" == "--relative" ]; then
- args="--relative";
- shift;
- fi
- fn=$1; shift;
- nuweb.redirect $args $($fn $@)
-}
-
-## nuweb.http.query.var:: [defaultValue]
-## Reads HTTP query string from variable *QUERY_STRING*, parses it and returns
-## value of parameter *param* or *defaultValue*.
-##
-## NOTE: Currently does not perform urldecode
-nuweb.http.query.var() {
- local to_read=$1;
- local line_separrated=$(sed "s/&/\n/g" <<< $QUERY_STRING)
-
- while IFS="=" read -r var value; do
- if [ "$var" = "$to_read" ]; then
- echo "$value"
- return;
- fi
- done <<< "$line_separrated"
- echo $2
-}
-
-## nuweb.http.query.to_var::
-##
-nuweb.http.query.to_var() {
- local line_separrated=$(sed "s/&/\n/g" <<< $QUERY_STRING)
- while IFS="=" read -r var value; do
- declare -x "nuweb_QUERY_$var"="$value"
- done <<< "$line_separrated"
-}
diff --git a/inc/nuweb.nuxsh.sh b/inc/nuweb.nuxsh.sh
new file mode 100755
index 0000000..4818a4b
--- /dev/null
+++ b/inc/nuweb.nuxsh.sh
@@ -0,0 +1,115 @@
+## #nuweb - Server-side HTTP scripting library for BASH
+##
+## *nuweb* is set of BASH function to ease implementation of CGI scripts using
+## BASH. Idea behind it, is to allow for reuse of existing shell scripts
+## and command-line utilities, without need to duplicate functionality.
+##
+## *nuweb* is based on *nux-env*, which allows large code-share with *nux-env*
+## command line tools and use of *nux-env* libraries.
+##
+## *nuweb* is separated into several components:
+##
+## nuweb::
+## this library, base functionality
+## nuweb/router:: router support functionality - dispatch of code
+## based on path and query parameters
+## nuweb/html::
+## basic support for generating HTML content
+##
+
+## #Public functions:
+
+## nuweb.status::
+## Sets HTTP response status code.
+## NOTE: If any content was already returned this function does not work.
+##
+@namespace nuweb {
+ function :status {
+ local code=$1;shift;
+ local message=$@;
+ echo "HTTP/1.1 $code $message"
+ }
+
+## nuweb.content_type::
+## Sets HTTP response content type
+## NOTE: If any content was already returned this function does not work.
+ function :content_type {
+ echo "Content-Type: $@"
+ }
+
+## nuweb.redirect:: [--relative]
+##
+ function :redirect {
+ local prefix="";
+ if [ "$1" == "--relative" ]; then
+ shift;
+ prefix="$(dirname "$SCRIPT_NAME")/"
+ fi
+ nux.log debug "Redirecting to:" "$@"
+ if [ -z "$@" ]; then
+ :status 404 NOT FOUND
+ else
+ echo Location: "$prefix$@"
+ echo
+ echo
+ fi
+ }
+
+## nuweb.redirect.exec::
+##
+ function :redirect.exec {
+ if [ "$1" == "--relative" ]; then
+ args="--relative";
+ shift;
+ fi
+ fn=$1; shift;
+ nuweb.redirect $args "$($fn $@)"
+ }
+
+## nuweb.http.query.var:: [defaultValue]
+## Reads HTTP query string from variable *QUERY_STRING*, parses it and returns
+## value of parameter *param* or *defaultValue*.
+##
+## NOTE: Currently does not perform urldecode
+}
+
+
+function nuweb.http.post.with_env fn {
+ if [ "${CONTENT_TYPE%;*}" = "application/x-www-form-urlencoded" ]; then
+ post_query=$(cat);
+ nux.log debug "POST Query: $post_query"
+ nuweb.http.query.with_env0 "$post_query" $fn "$@"
+ else
+ $fn "$@"
+ fi
+
+}
+
+@namespace nuweb.http.query {
+ function :var() {
+ local to_read=$1;
+ local line_separrated=$(sed "s/&/\n/g" <<< $QUERY_STRING)
+
+ while IFS="=" read -r var value; do
+ if [ "$var" = "$to_read" ]; then
+ echo "$value"
+ return;
+ fi
+ done <<< "$line_separrated"
+ echo $2
+}
+
+## nuweb.http.query.to_var::
+##
+ function :with_env {
+ :with_env0 "$QUERY_STRING" "$@"
+ }
+
+ function :with_env0 query fn {
+ nux.log debug "GET Query: $QUERY_STRING";
+ while IFS="=" read -d "&" -r var value; do
+ declare -x "NUWEB_QUERY_${var//-/_}"="$(dirty.url.decode "$value")";
+ done <<< "${query}&";
+ $fn "$@"
+ }
+}
diff --git a/inc/nuweb/html.inc.sh b/inc/nuweb/html.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nuweb/html.nuxsh.syntax.nuxsh.sh b/inc/nuweb/html.nuxsh.syntax.nuxsh.sh
new file mode 100755
index 0000000..1b8b03d
--- /dev/null
+++ b/inc/nuweb/html.nuxsh.syntax.nuxsh.sh
@@ -0,0 +1,5 @@
+@namespace block.rewrite {
+ :call nuweb.html.html '+e html' '-e html'
+ :call nuweb.html.head '+e html' '-e html'
+
+}
diff --git a/inc/nuweb/html.syntax.nuxsh.sh b/inc/nuweb/html.syntax.nuxsh.sh
new file mode 100755
index 0000000..458e5b0
--- /dev/null
+++ b/inc/nuweb/html.syntax.nuxsh.sh
@@ -0,0 +1,69 @@
+@prefix statement nux.nuxsh.statement
+@prefix block nux.nuxsh.block
+
+@namespace nuweb.html.syntax {
+
+ function :statement {
+ :start "$@"
+ :end "$@"
+ }
+
+ function :start tag indent args {
+ echo -n "${indent}echo '<$tag'";
+
+ nux.log debug "Args are '$args'";
+ set -- $args
+ local attr="";
+ local classes="";
+ for arg; do
+ if [ -n "$attr" ] ; then
+ echo -n $arg"'\"'"
+ attr="";
+ else
+ case "$arg" in
+ @*)
+ attr="${arg#@}";
+ echo -n " '${attr}=\"'"
+ ;;
+ .*) classes="${classes}${arg//./ }";;
+ *)
+ nux.dsl.process.fail "unknown argument '$arg' '$line' "
+ return 1;
+ ;;
+ esac
+ fi
+ done
+ if [ -n "$classes" ] {
+ echo -n " 'class=\"'$classes'\"'"
+ }
+ echo " '>'";
+ }
+
+ function :end tag indent {
+ echo "${indent}echo '$tag>'";
+ }
+
+ function :element {
+ for tag in "$@" ; do
+ block:rewrite.call nuweb.html.dynamic.$tag "nuweb.html.element $tag" "nuweb.html.element.end $tag"
+ block:rewrite.func nuweb.html.$tag "nuweb.html.syntax.start $tag" "nuweb.html.syntax.end $tag"
+ statement:rewrite.func nuweb.html.$tag "nuweb.html.syntax.statement $tag"
+ statement:rewrite.call nuweb.dynamic.$tag "nuweb.html.element --close $tag"
+
+
+ done
+ }
+
+ :element html body head title
+ :element style link meta script
+ :element header main nav
+
+ :element span div p pre
+ :element a img
+
+ :element b i strong small
+
+ :element h1 h2 h3 h4 h5 h6
+
+ :element form input submit button textarea select label
+}
diff --git a/inc/nuweb/mdl.io.app.inc.sh b/inc/nuweb/mdl.io.app.inc.sh
deleted file mode 100644
index edff8f5..0000000
--- a/inc/nuweb/mdl.io.app.inc.sh
+++ /dev/null
@@ -1,268 +0,0 @@
-nux.use nuweb/mdl.io
-nux.use nuweb/router
-nux.use nux.mime
-
-mdlio.app() {
- mdlio.app.html "$@"
-}
-
-app.header() {
- :
-}
-
-mdlio.app.custom() {
- local func=$1; shift;
- nux.exec.or $func app.$func "$@";
-}
-
-mdlio.app.html() {
- nuweb.content_type text/html
- echo
- local spec="$1"; shift;
- $spec "$@";
-
- local appName=$(nux.exec.optional app.name);
- local title="$(nux.exec.optional title)";
- echo ""
- +e html
- +e head
- e meta @charset utf-8
- e meta @http-equiv x-ua-compatible @content ie=edge
- e meta @name "viewport" @content "width=device-width, initial-scale=1.0, minimum-scale=1.0"
- mdlio.css $(mdlio.app.custom color.primary) $(mdlio.app.custom color.accent)
- e link @rel stylesheet @href "$NUWEB_SCRIPT_URI/action:asset/mdlio-app.css"
- e link @rel stylesheet @href "https://unpkg.com/simplelightbox@1.11.0/dist/simplelightbox.css"
-
- nux.exec.optional app.custom.head
- e title "$title - $appName"
- -e head
- +e body .mdl-base
- +mdlio.layout .mdl-layout--fixed-header
- e.mdlio.header++ "$appName"
- mdlio.app.custom header
- -e div
- -e header
- if nux.check.function app.drawer ; then
- +e div .mdl-layout__drawer
- app.drawer
- nux.exec.optional drawer
- -e div
- fi
- +mdlio.main
- nux.exec.optional app.main.start
- main "$@"
-
-
- +e div @id scooter
- +e div .mdl-grid @id sizer
- e div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
- -e div
- -e div
-
- nux.exec.optional app.main.end
- -e main
- -e div
- mdlio.app.photoswipe.html
-
- e script @src https://code.jquery.com/jquery-3.2.1.min.js
- e script @src https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.js
- #e script @src https://unpkg.com/simplelightbox@1.11.0/dist/simple-lightbox.js
- e script @src https://unpkg.com/photoswipe@4.1.2/dist/photoswipe.js
- e script @src https://unpkg.com/photoswipe@4.1.2/dist/photoswipe-ui-default.js
- e link @rel stylesheet @href https://unpkg.com/photoswipe@4.1.2/dist/photoswipe.css
- e link @rel stylesheet @href https://unpkg.com/photoswipe@4.1.2/dist/default-skin/default-skin.css
- e script @src https://unpkg.com/infinite-scroll@3/dist/infinite-scroll.pkgd.js
- e script @src "$NUWEB_SCRIPT_URI/action:asset/mdlio-app.js"
- e script @src "https://code.getmdl.io/1.3.0/material.min.js"
- nux.exec.optional scripts
-
- -e body
- -e html
-}
-
-app.color.primary() {
- echo teal
-}
-
-app.color.accent() {
- echo cyan
-}
-
-mdlio.app.infinity() {
- # outlayer: msnry,
- local container=$1;
- local item=$2;
- local nextPage=$3;
- local outlayer="";
- e script """
- var grid = document.querySelector('$container');
- var infScroll = new InfiniteScroll( grid, {
- path: '$nextPage',
- append: '$item',
- $outlayer
- status: '.page-load-status',
- elementScroll: '.mdl-layout__content',
- });
- """
-
-}
-
-function mdlio.app.masonry() {
- local grid="$1"
- local gridItem="$2"
- local lightBoxItem="$3"
- local gutter="$4"
- local nextPage="$5";
- e script """
- var gallery = new mdlio.cardsGallery(document.querySelector('$grid'), '$gridItem', '$lightBoxItem');
-"""
-
-}
-
-
-function mdlio.app.thumb.uri() {
- local filename="$1";
- local mimetype="$2";
-
- #if [ -d "$filename" ] ; then
- # nux.log info "File $filename is folder."
- # filename=$(find "$1" -maxdepth 1 -iname "*.jpg" -or -iname "*.png" | head -n1)
- # nux.log info "Using $filename for thumbnail."
- #fi
-
- local thumb_name="$(thumby.name.shared "$filename")"
- local dirname=$(dirname "$filename")
- local thumb_path="$dirname/.sh_thumbnails/large/$thumb_name"
- if [ -e "$thumb_path" ] ; then
- nux.dirty.urlencode $thumb_path
- elif thumby.thumb.can.generate "$filename" "$mimetype"; then
- echo "$NUWEB_SCRIPT_URI/action:thumb/$NUWEB_REQUEST_PATH/$filename"
- fi
-}
-
-function mdlio.app.thumb.get() {
- img_path="${@##/}"
- nux.log info "Generating thumb for" $(pwd) "$img_path"
- thumb_path=$(thumby.thumb.get "${DOCUMENT_ROOT}/$img_path");
- if [ -n "$thumb_path" ]; then
- nux.dirty.urlencode ${thumb_path#$DOCUMENT_ROOT};
- fi
-}
-
-
-mdlio.app.run() {
- nuweb.router.exec mdlio.app.routes
-}
-
-mdlio.app.routes() {
- get() {
- local uri_spec="$1"; shift;
- nuweb.get "$uri_spec" mdlio.app "$@"
- }
-
- get.paginate() {
- main() {
- #nux.exec.optional before "$@";
- before=before after=after nuweb.paginate div .gallery .mdl-grid items per-item next-page 20;
- #nux.exec.optional after "$@";
- }
- next-page() {
- +e div .mdl-grid
- e div .mdl-cell .mdl-cell--11-col .mdl-cell--col-3-phone .mdl-cell--col-7-tablet
- +e div .mdl-cell .mdl-cell--1-col
- e a .next-page .mdl-button.mdl-button--colored @href "${REQUEST_URI%%?*}?page=$1&per_page=$2" Next
- -e div
- -e div
- }
- get "$@"
- }
-
- #nuweb.get "/action:zip:serve/@+" mdlio.action.zip.serve
- nuweb.get "/action:thumb/@+" nuweb.redirect.exec mdlio.app.thumb.get
- nuweb.get "/action:asset/@" mdlio.app.asset
- nux.exec.optional app.routes;
-}
-
-
-mdlio.app.asset() {
- file="$NUX_ENV_DIR/assets/nuweb/$1";
- if [ -e "$file" ]; then
- mime=$(nux.mime "$file");
- echo Content-Type: $mime
- echo
- cat "$file"
- fi
-}
-
-
-mdlio.app.photoswipe.html() {
- cat <
-
-
-EOF
-}
diff --git a/inc/nuweb/mdl.io.inc.sh b/inc/nuweb/mdl.io.inc.sh
deleted file mode 100644
index 84663e0..0000000
--- a/inc/nuweb/mdl.io.inc.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-
-nux.use nuweb/html
-
-mdlio.css() {
- e.link stylesheet "https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en"
- e.link stylesheet "https://fonts.googleapis.com/icon?family=Material+Icons"
- e.link stylesheet "https://code.getmdl.io/1.3.0/material.${1}-${2}.min.css"
-
-}
-
-e.mdlio.header++() {
- +e header .mdl-layout__header .mdl-color--primary
- +e div .mdl-layout__header-row
- e span .mdl-layout-title $1
- e div .mdl-layout-spacer
-}
-
-
-e.alias mdlio.layout "div" ".mdl-layout .mdl-js-layout"
-e.alias mdlio.main "main" ".mdl-layout__content"
-e.alias mdlio.card "div" ".mdl-card.mdl-shadow--2dp"
-
-.mdl_cell() {
- echo .mdl-cell.mdl-cell--"$1"-col.mdl-cell--"$2"-col-tablet.mdl-cell--"$2"-col-phone
-}
diff --git a/inc/nuweb/mdlio.app.defaults.nuxsh.sh b/inc/nuweb/mdlio.app.defaults.nuxsh.sh
new file mode 100755
index 0000000..3007c04
--- /dev/null
+++ b/inc/nuweb/mdlio.app.defaults.nuxsh.sh
@@ -0,0 +1,16 @@
+
+@namespace app {
+
+ function :color.primary {
+ echo teal
+ }
+
+ function :color.accent {
+ echo cyan
+ }
+
+ function :header {
+ :
+ }
+
+}
diff --git a/inc/nuweb/mdlio.app.nuxsh.sh b/inc/nuweb/mdlio.app.nuxsh.sh
new file mode 100755
index 0000000..f0b6c5b
--- /dev/null
+++ b/inc/nuweb/mdlio.app.nuxsh.sh
@@ -0,0 +1,228 @@
+@syntax nuweb/html
+
+nux.use nuweb/mdlio
+nux.use nuweb/mdlio.app.defaults
+nux.use nuweb/router
+nux.use nux/mime
+nux.use thumby
+nux.use thumby/builtin
+
+@prefix h nuweb.html
+@prefix router nuweb.router
+
+@block:rewrite:call2 e +e -e ;
+
+@namespace mdlio.app {
+
+ function mdlio.app spec {
+ #nux.exec.optional app.init
+ $spec "$@";
+ mdlio.app.html
+ }
+
+ function :custom func {
+ nux.exec.or $func app.$func "$@";
+ }
+
+ function :additional-css css {
+ mdlio_app_additional_css="$mdlio_app_additional_css $css"
+ }
+
+ function :additional-script script {
+ mdlio_app_additional_script="$mdlio_app_additional_script $script"
+ }
+
+ function :html {
+ nuweb.content_type text/html
+ echo
+
+ local app_uri="${NUWEB_SCRIPT_URI}";
+ local appName=$(nux.exec.optional app.name);
+ echo ""
+ h:html {
+ h:head {
+ h:meta @charset utf-8
+ h:meta @http-equiv x-ua-compatible @content ie=edge
+ h:meta @name "viewport" @content "width=device-width, initial-scale=1.0, minimum-scale=1.0"
+ mdlio.css $(mdlio.app.custom color.primary) $(mdlio.app.custom color.accent)
+ h:link @rel stylesheet @href "$NUWEB_SCRIPT_URI/action/mdlio:asset/mdlio-app.css"
+ h:link @rel stylesheet @href "https://unpkg.com/simplelightbox@1.11.0/dist/simplelightbox.css"
+
+ for css in $mdlio_app_additional_css; do
+ h:link @rel stylesheet @href "$NUWEB_SCRIPT_DIR_URI/$css"
+ done
+
+ nux.exec.optional app.custom.head
+ h:title {
+ nux.exec.optional title
+ echo -
+ nux.exec.optional app.name
+ }
+ }
+ h:body .mdl-base {
+ +mdlio.layout .mdl-layout--fixed-header
+ e.mdlio.header++ "$appName"
+ mdlio.app.custom header
+ -e div
+ -e header
+ if nux.check.function app.drawer ; then
+ h:div .mdl-layout__drawer {
+ app.drawer
+ nux.exec.optional drawer
+ }
+ fi
+ +mdlio.main
+ nux.exec.optional app.main.start
+
+ nux.exec.or app.template-main app.content "$@"
+
+
+
+
+ -e main
+ -e div
+
+ mdlio.app.photoswipe.html
+
+ h:div .scripts {
+ h:script @src "https://code.jquery.com/jquery-3.2.1.min.js"
+ h:script @src "https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.js"
+ h:script @src "https://unpkg.com/photoswipe@4.1.2/dist/photoswipe.js"
+ h:script @src "https://unpkg.com/photoswipe@4.1.2/dist/photoswipe-ui-default.js"
+ h:link @rel stylesheet @href https://unpkg.com/photoswipe@4.1.2/dist/photoswipe.css
+ h:link @rel stylesheet @href https://unpkg.com/photoswipe@4.1.2/dist/default-skin/default-skin.css
+ h:script @src "https://unpkg.com/infinite-scroll@3/dist/infinite-scroll.pkgd.js"
+ h:script @src "$(mdlio.app.action.uri mdlio:asset /mdlio-app.js)"
+ h:script @src "https://code.getmdl.io/1.3.0/material.min.js"
+
+ for script in $mdlio_app_additional_script; do
+ h:script @src "$NUWEB_SCRIPT_DIR_URI/$script"
+ done
+
+ nux.exec.optional scripts
+ }
+ }
+ }
+ }
+
+ function :grid-sizer {
+ h:div @id scooter {
+ h:div .mdl-grid @id sizer {
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ h:div @id gutter .gutter .mdl-cell .mdl-cell--1-col .mdl-cell--1-col-phone .mdl_cell--1-col-tablet
+ }
+ }
+ }
+
+ function :infinity container item nextPage {
+ local outlayer="";
+ e script """
+ var infScroll = new InfiniteScrolldocument.querySelector('$container'); grid, {
+ path: '$nextPage',
+ append: '$item',
+ $outlayer
+ status: '.page-load-status',
+ elementScroll: '.mdl-layout__content'
+ });
+ """
+}
+
+function :masonry grid gridItem lightBoxItem gutter nextPage {
+ e script """
+ var gallery = new mdlio.cardsGallery(document.querySelector('$grid'), '$gridItem', '$lightBoxItem');
+ """
+
+}
+
+function :action.uri action path args {
+ echo "$NUWEB_SCRIPT_URI/action/${action}${path}${args}"
+}
+
+function :thumb.uri filename mimetype {
+ local thumb_name="$(thumby.name.shared "$filename")"
+ local dirname=$(dirname "$filename")
+ local thumb_path="$dirname/.sh_thumbnails/large/$thumb_name"
+
+ if thumby.thumb.can.generate "$filename" "$mimetype"; then
+ if thumby.thumb.should.generate "$filename" "$mimetype"; then
+ :action.uri mdlio:thumb "$NUWEB_REQUEST_PATH/$filename"
+ return 0;
+ fi
+ fi
+
+
+ if [ -e "$thumb_path" ] ; then
+ nux.dirty.urlencode "$thumb_path"
+ fi
+}
+
+function :thumb.get {
+ img_path="${@##/}"
+ nux.log info "Generating thumb for" $(pwd) "$img_path"
+ thumb_path="$(thumby.thumb.get "${DOCUMENT_ROOT}/$img_path")";
+ if [ -n "$thumb_path" ]; then
+ nux.dirty.urlencode "${thumb_path#$DOCUMENT_ROOT}";
+ fi
+}
+
+
+function :run {
+ nuweb.router.exec mdlio.app.routes
+}
+
+function :routes {
+ function :post uri_spec {
+ router:post "$uri_spec" mdlio.app "$@"
+ }
+
+ function :get uri_spec {
+ router:get "$uri_spec" mdlio.app "$@"
+ }
+
+ function :get.paginate {
+ function app.content {
+ #nux.exec.optional before "$@";
+ before=before after=after nuweb.paginate div .gallery .mdl-grid items per-item next-page 20;
+ #nux.exec.optional after "$@";
+ }
+ function next-page {
+ h:div .mdl-grid {
+ h:div .mdl-cell .mdl-cell--11-col .mdl-cell--col-3-phone .mdl-cell--col-7-tablet
+ h:div .mdl-cell .mdl-cell--1-col {
+ h:a .next-page .mdl-button.mdl-button--colored @href "${REQUEST_URI%%?*}?page=$1&per_page=$2" Next
+ }
+ }
+ }
+ :get "$@"
+ }
+
+ #nuweb.get "/action:zip:serve/@+" mdlio.action.zip.serve
+ router:get "/action/mdlio:thumb/@+" nuweb.redirect.exec mdlio.app.thumb.get
+ router:get "/action/mdlio:asset/@" mdlio.app.asset
+ nux.exec.optional app.routes;
+ :get "/" app.main;
+}
+
+
+function :asset name {
+ local file="$NUX_ENV_DIR/assets/nuweb/$name";
+ if [ -e "$file" ]; then
+ mime=$(nux.mime "$file");
+ echo Content-Type: $mime
+ echo
+ cat "$file"
+ fi
+}
+
+function :photoswipe.html {
+ echo ""
+}
+
+}
diff --git a/inc/nuweb/mdlio.app.syntax.nuxsh.sh b/inc/nuweb/mdlio.app.syntax.nuxsh.sh
new file mode 100755
index 0000000..215add9
--- /dev/null
+++ b/inc/nuweb/mdlio.app.syntax.nuxsh.sh
@@ -0,0 +1,50 @@
+@syntax nuweb/html
+
+@prefix statement nux.nuxsh.statement
+@prefix block nux.nuxsh.block
+@prefix hs nuweb.html.syntax
+
+nux.use nuweb/html.syntax
+
+@namespace nuweb.mdlio.syntax {
+ function :element name tag {
+ block:rewrite.call nuweb.mdlio.tag.$name "nuweb.html.element $tag $@" "nuweb.html.element.end $tag"
+ statement:rewrite.call nuweb.mdlio.tag.$name "nuweb.html.element --close $tag $@"
+ }
+
+ function :block-as-function fqn {
+ block:rewrite.call $fqn "function $fqn {" "}"
+ }
+
+ function :statement-as-echo-function fqn {
+ statement:rewrite.call $fqn "function $fqn() { echo " ";}"
+ }
+
+ :element card div .mdl-card.mdl-shadow--2dp
+ :element card-media div .mdl-card_media
+ :element card-title div .mdl-card_title
+
+ :element nav nav .mdl-navigation
+
+
+ :block-as-function app.name
+ :block-as-function app.main
+ :block-as-function app.content
+ :block-as-function app.drawer
+ :block-as-function app.page-title
+ :block-as-function app.title
+ :block-as-function app.scripts
+ :block-as-function app.template-main
+ :block-as-function app.routes
+
+ #:statement-as-echo-function app.page-title
+ #:statement-as-echo-function app.content
+}
+
+function .block.app.start.plan {
+ identifier=app .match.namespace_block_start.plan
+}
+
+function .block.app.end.plan {
+ .block.rule.namespace.end.plan
+}
diff --git a/inc/nuweb/mdlio.nuxsh.sh b/inc/nuweb/mdlio.nuxsh.sh
new file mode 100755
index 0000000..f9c56b6
--- /dev/null
+++ b/inc/nuweb/mdlio.nuxsh.sh
@@ -0,0 +1,49 @@
+@syntax nuweb/html
+@prefix h nuweb.html
+@prefix hd nuweb.html.dynamic
+nux.use nuweb/html
+
+function mdlio.css() {
+ e.link stylesheet "https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en"
+ e.link stylesheet "https://fonts.googleapis.com/icon?family=Material+Icons"
+ e.link stylesheet "https://code.getmdl.io/1.3.0/material.${1}-${2}.min.css"
+
+}
+
+function e.mdlio.header++() {
+ +e header .mdl-layout__header .mdl-color--primary
+ +e div .mdl-layout__header-row
+ e span .mdl-layout-title $1
+ e div .mdl-layout-spacer
+}
+
+@namespace nuweb.mdlio.tag {
+
+ function :textfield id type label {
+ h:div .mdl-textfield.mdl-js-textfield.mdl-textfield--floating-label {
+ hd:input .mdl-textfield__input @type "$type" @id "$id" "$@"
+ h:label .mdl-textfield__label @for $id {
+ echo $label
+ }
+ }
+ }
+
+ function :submit name {
+ hd:input @type submit .mdl-button.mdl-js-button.mdl-button--raised.mdl-button--accent @value "$name" "$@"
+ }
+
+ function :nav-link href {
+ h:a .mdl-navigation__link @href "$href" {
+ echo "$@"
+ }
+ }
+
+}
+
+e.alias mdlio.layout "div" ".mdl-layout .mdl-js-layout"
+e.alias mdlio.main "main" ".mdl-layout__content"
+e.alias mdlio.card "div" ".mdl-card.mdl-shadow--2dp"
+
+function .mdl_cell() {
+ echo mdl-cell mdl-cell--"$1"-col mdl-cell--"$2"-col-tablet mdl-cell--"$2"-col-phone
+}
diff --git a/inc/nuweb/router.inc.sh b/inc/nuweb/router.inc.sh
old mode 100644
new mode 100755
index 133614e..c2b4396
--- a/inc/nuweb/router.inc.sh
+++ b/inc/nuweb/router.inc.sh
@@ -20,13 +20,18 @@
##
##
nuweb.router.tryexec.concrete() {
- full_spec=$1;
+ method="$1";
+ full_spec="$2";
+ func="$3";
+ shift; shift; shift;
+ if [ "$REQUEST_METHOD" != "$method" ]; then
+ return 1;
+ fi
+
path_spec=${full_spec%%\?*}
query_spec=${full_spec#$path_spec}
query_spec=${query_spec#\?}
- func=$2;
- shift; shift;
nux.log trace "Checking Path Spec: '$path_spec', Query Spec: '$query_spec' Function:$func Additional Args:$@" >&2
IFS='/' read -ra spec_components <<< "$path_spec"
@@ -41,12 +46,12 @@ nuweb.router.tryexec.concrete() {
elif [ "$spec" == "@" ]; then
path_args="$path_args $path";
elif [ "$spec" != "$path" ] ; then
- return -1
+ return 1
fi
let i=$i+1
done
if [ $i -lt "${#spec_components[@]}" ] ; then
- return -1;
+ return 1;
fi
if [ -n "$query_spec" ]; then
IFS='&' read -ra query_components <<< "$query_spec"
@@ -59,27 +64,29 @@ nuweb.router.tryexec.concrete() {
else
if [ -z "$value" ]; then
#echo "$def $value is empty." >&2;
- return -1;
+ return 1;
elif [ "$valueDef" == "@" ]; then
query_args="$query_args $value"
elif [ "$value" != "$valueDef" ]; then
#echo "$def $value != $valueDef" >&2;
- return -1;
+ return 1;
fi
fi
done
fi
path_c=$(dirty.url.decode "$path_c")
- $func "$@" $path_args "$path_c" $query_args
+ nuweb.http.query.with_env nuweb.http.post.with_env $func "$@" $path_args "$path_c" $query_args
exit 0
}
-
-nuweb.get() {
- nuweb.router.tryexec.concrete $@;
+nuweb.router.get() {
+ nuweb.router.tryexec.concrete GET "$@";
}
+nuweb.router.post() {
+ nuweb.router.tryexec.concrete POST "$@";
+}
##
## nuweb.router.exec:: [path]
@@ -99,6 +106,7 @@ nuweb.router.exec() {
path="/"
fi
+ nux.log debug "Method: '$REQUEST_METHOD' Path: '$path'"
IFS='/' read -ra PATH_COMPONENTS <<< "$path"
$definition
diff --git a/inc/nuweb/utils.inc.sh b/inc/nuweb/utils.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux.cfg.inc.sh b/inc/nux.cfg.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux.dsl.inc.sh b/inc/nux.dsl.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux.inc.sh b/inc/nux.inc.sh
old mode 100644
new mode 100755
index 4a0a9b7..d00db17
--- a/inc/nux.inc.sh
+++ b/inc/nux.inc.sh
@@ -81,7 +81,6 @@ function nux.exec.or {
if nux.check.function "$maybe" ; then
to_exec=$maybe
fi
- nux.log trace "Executing $to_exec , optional was $maybe"
$to_exec "$@";
}
@@ -100,6 +99,8 @@ function nux.url.parse {
}
+nux.use nux/nuxsh
+
nux.use nux/log
nux.use nux/check
-nux.use nux/nuxsh
+nux.use nux/array
diff --git a/inc/nux.mime.inc.sh b/inc/nux.mime.inc.sh
deleted file mode 100644
index 0e3370a..0000000
--- a/inc/nux.mime.inc.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-nux.mime() {
- local type=binary/octet
- local suffix="${1##*.}"
- case "${suffix,,}" in
- txt) type=text/plain;;
- css) type=text/css;;
- jpg) type=image/jpeg;;
- png) type=image/png;;
- zip) type=application/zip;;
- cbr) type=application/x-cbz;;
- cbz) type=application/x-cbr;;
- pdf) type=application/pdf;;
- epub) type=application/epub+zip;;
- mp4) type=video/mp4;;
- *)
- if [ -d "$1" ]; then
- type=directory
- fi
- esac
- echo $type;
-
-}
diff --git a/inc/nux.thumb.inc.sh b/inc/nux.thumb.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux/array.nuxsh.sh b/inc/nux/array.nuxsh.sh
new file mode 100755
index 0000000..aa0ab85
--- /dev/null
+++ b/inc/nux/array.nuxsh.sh
@@ -0,0 +1,13 @@
+@namespace nux.array {
+
+ function :contains array value {
+ local array_ref="$array[@]";
+ for c in "${!array_ref}"; do
+ if [ "$c" == "$value" ]; then
+ return 0;
+ fi
+ done
+ return 1
+ }
+
+}
diff --git a/inc/nux/check.inc.sh b/inc/nux/check.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux/color.nuxsh.sh b/inc/nux/color.nuxsh.sh
old mode 100644
new mode 100755
diff --git a/inc/nux/dsl.inc.sh b/inc/nux/dsl.inc.sh
old mode 100644
new mode 100755
index 1420ea6..494470e
--- a/inc/nux/dsl.inc.sh
+++ b/inc/nux/dsl.inc.sh
@@ -98,11 +98,11 @@ nux.dsl.plan() {
local file="$2";
local cached="${3:-$file${NUDSL_CACHE_SUFFIX}}";
if [ "$file" -ot "$cached" ]; then
- nux.log debug No need to recompile.
+ nux.log trace No need to recompile '$file'.
return;
fi
- nux.log debug Needs regeneration, creating new version.
+ nux.log trace File '$file' Needs regeneration, creating new version.
local dirname=$(dirname "$cached")
mkdir -p "$dirname";
@@ -110,9 +110,9 @@ nux.dsl.plan() {
if (nux.dsl.process plan "$language" "$file" > "$execution_plan") ; then
mv -f "$execution_plan" "$cached";
else
- echo "Plan could not be generated. See errors."
+ echo "Plan for $file could not be generated. See errors." >&2
rm "$execution_plan"
- return -1;
+ return 1;
fi
}
@@ -136,7 +136,7 @@ nux.dsl.process0() {
fi
done
if [ -n "$process_failed" ]; then
- return -1;
+ return 1;
fi
done;
}
diff --git a/inc/nux/help.nuxsh.sh b/inc/nux/help.nuxsh.sh
old mode 100644
new mode 100755
diff --git a/inc/nux.json.inc.sh b/inc/nux/json.inc.sh
old mode 100644
new mode 100755
similarity index 100%
rename from inc/nux.json.inc.sh
rename to inc/nux/json.inc.sh
diff --git a/inc/nux/log.inc.sh b/inc/nux/log.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nux/meta.nuxsh.sh b/inc/nux/meta.nuxsh.sh
new file mode 100755
index 0000000..2a0dbbd
--- /dev/null
+++ b/inc/nux/meta.nuxsh.sh
@@ -0,0 +1,50 @@
+nux_meta_backends="func file"
+
+@namespace nux.meta {
+
+ function :add-impl impl {
+ nux_meta_backends="$impl $nux_meta_backends"
+ }
+
+ function :get filename name default {
+ for backend in $nux_meta_backends; do
+ #nux.log debug "Invoking $backend nux.meta.impl.$backend.get $(declare -f nux.meta.impl.$backend.get)";
+ local value=$(nux.meta.impl.$backend.get "$filename" "$name");
+ if [ -n "$value" ] {
+ echo "$value"
+ return 0;
+ }
+ done
+ if [ -z "$default" ] {
+ return 1;
+ }
+ echo "$default"
+ }
+}
+
+@namespace nux.meta.impl.file {
+
+ function :get filename name {
+ if [ -e "$filename/.nux.meta" ] {
+ grep "^$name " "$filename/.nux.meta" | cut -d " " -f2-
+ }
+ }
+
+ function :add filename name value {
+ local meta="$filename/.nux.meta";
+ local metaline="$name $value";
+
+ if ! ( [ -e "$meta" ] && grep "^$metaline\$" "$meta" > /dev/null ) {
+ nux.log debug "Writing pin to $meta"
+ echo "$metaline" >> "$meta"
+ }
+ }
+
+}
+
+@namespace nux.meta.impl.func {
+ function :get filename name {
+ local funcspec="${name//:/.}"
+ nux.exec.optional "nux.meta.impl.func.$funcspec" "$filename"
+ }
+}
diff --git a/inc/nux/meta/impl/.gitkeep b/inc/nux/meta/impl/.gitkeep
new file mode 100755
index 0000000..e69de29
diff --git a/inc/nux/mime.nuxsh.sh b/inc/nux/mime.nuxsh.sh
new file mode 100755
index 0000000..8684511
--- /dev/null
+++ b/inc/nux/mime.nuxsh.sh
@@ -0,0 +1,37 @@
+function nux.mime {
+ nux.mime.naive.suffix "$@"
+}
+
+@namespace nux.mime {
+
+ function :naive.suffix filename {
+ local type=binary/octet
+ local suffix="${filename##*.}"
+ suffix="${suffix,,}"
+ if [ -d "$filename" ]; then
+ type=directory
+ else
+ case "${suffix,,}" in
+
+ txt) type=text/plain;;
+ css) type=text/css;;
+
+ jpeg) ;&
+ jpg) type=image/jpeg;;
+
+ png) type=image/png;;
+ zip) type=application/zip;;
+
+ cbr) type=application/x-cbz;;
+ cbz) type=application/x-cbr;;
+
+ pdf) type=application/pdf;;
+ epub) type=application/epub+zip;;
+ mp4) type=video/mp4;;
+ esac
+ fi
+ echo $type;
+
+ }
+
+}
diff --git a/inc/nux/mime/impl/.gitkeep b/inc/nux/mime/impl/.gitkeep
new file mode 100755
index 0000000..e69de29
diff --git a/inc/nux/nuxsh.inc.sh b/inc/nux/nuxsh.inc.sh
old mode 100644
new mode 100755
index bc86807..0dc262a
--- a/inc/nux/nuxsh.inc.sh
+++ b/inc/nux/nuxsh.inc.sh
@@ -1,16 +1,17 @@
nux.use nux/dsl
nux.nuxsh.language.def() {
- local identifier='[^ ;{}=()$]+'
+ local identifier_char='[^ ;{}=()$:]'
+ local identifier='[^ ;{}=()$:]+'
local comment='(( *)(#.*))?'
local whitespace="([ ]*)"
- local uarg="([^ #\{\}\"'\"'\"';]+)";
+ local uarg="([^ #{}\"'\"'\"';]+)";
local sarg="('\"'\"'[^'\"'\"']+'\"'\"')";
local darg='("[^"]*")';
local args="((($uarg|$darg|$sarg) *)*)";
- local prefixed_id="([^ :]*:)?($identifier)"
+ local prefixed_id="($identifier_char*:)?($identifier)"
.match.line() {
local type="$1";
@@ -34,11 +35,11 @@ nux.nuxsh.language.def() {
.match.line if_start "(if)( +)$prefixed_id( +)$args?( *)(\{)" \
keyword indent2 prefix identifier indent3 args - - - - - indent4 syntax3
- .match.line function_start "((function)( +))($identifier)((\()|( *))(($identifier,? *)*)(\))?( *)(\{)" \
+ .match.line function_start "((function)( +))(:?$identifier)((\()|( *))(($identifier,? *)*)(\))?( *)(\{)" \
- keyword indent2 identifier - syntax indent3 args - syntax2 indent4 syntax3
- .match.line block_start "($identifier)(( +)$args)?( *)(\{)" \
- identifier - indent2 args - - - - - indent3 syntax3
+ .match.line block_start "$prefixed_id(( +)$args)?( *)(\{)" \
+ prefix identifier - indent2 args - - - - - indent3 syntax3
.match.line statement "$prefixed_id(( +)$args)?( *)(;?)"\
prefix identifier - indent2 args - - - - - indent3 syntax2
@@ -69,16 +70,26 @@ nux.nuxsh.language.def() {
echo ${_block_type[${#_block_type[@]}-1]}
}
+ function .block.args.get {
+ echo ${_block_args[${#_block_args[@]}-1]}
+ }
+
function .block.pop {
unset _block_type[${#_block_type[@]}-1]
+ unset _block_args[${#_block_args[@]}-1]
}
function .block.push {
- _block_type[${#_block_type[@]}]="$1"
+ local block="$1";shift;
+ _block_type[${#_block_type[@]}]="$block"
+ _block_args[${#_block_args[@]}]="$@"
}
.match.block_start.plan() {
- .block.push $identifier;
+ nux.log debug "P '$identifier' '$prefix' "
+ local identifier=$(.identifier)
+ nux.log debug "Block '$identifier' '$prefix' "
+ .block.push "$identifier" "$args";
nux.exec.or .block.$identifier.start.plan .block.start.plan
}
@@ -86,7 +97,7 @@ nux.nuxsh.language.def() {
local identifier=$(.block.get)
if [ "$identifier" == "$blocktrac_root" ]; then
nux.dsl.process.fail "unnecessary block end '$line' "
- return -1;
+ return 1;
fi
nux.exec.or .block.$identifier.end.plan .block.end.plan
.block.pop;
@@ -99,8 +110,8 @@ nux.nuxsh.language.def() {
}
.action.prefix() {
- echo "# prefix: $1 $2"
- eval "_import_prefix_$1='$2'";
+ echo "# prefix: $1 ${2%.}"
+ eval "_import_prefix_$1='${2%.}'";
}
@@ -109,20 +120,27 @@ nux.nuxsh.language.def() {
local var=_import_prefix_${prefix%:}
local prepend=${!var};
if [ -z "$prepend" ] ; then
- nudsl.process.fail "undefined prefix: $prefix";
+ nux.dsl.process.fail "undefined prefix: $prefix";
+ return;
fi
- echo "$prepend$identifier"
+ echo "$prepend.$identifier"
else
- echo "$identifier"
+ cat <<< "$identifier"
fi
}
.match.statement.plan() {
- echo "${indent}$(.identifier) ${args}"
+ identifier=$(.identifier);
+ nux.exec.or .statement.$identifier.plan .statement.plan
+
}
+ .statement.plan() {
+ echo "${indent}$identifier ${args}"
+ }
.match.rule.plan() {
+ echo "rule " >&2;
eval ".action.${rule//:/.} $args";
}
@@ -156,8 +174,8 @@ nux.nuxsh.language.def() {
.match.function_start.plan() {
.block.push function
case $identifier in
- .*) ;;
- :*) identifier="$_namespace${identifier#:}"
+ :) identifier="$_namespace";;
+ :*) identifier="$_namespace.${identifier#:}";;
esac;
echo "${indent}$identifier() {";
for arg in ${args//,/ }; do
@@ -169,7 +187,7 @@ nux.nuxsh.language.def() {
case $identifier in
function) echo "$line";;
*"()") echo "$line";;
- *) nudsl.process.fail Invalid block syntax: "'$identifier' '$line'";
+ *) nux.dsl.process.fail Invalid block syntax: "'$identifier' '$line'";
esac;
}
@@ -189,6 +207,10 @@ nux.nuxsh.language.def() {
"""
}
+ .action.syntax() {
+ nux.use "$1.syntax"
+ }
+
.action.block.rewrite.call() {
echo "# block:rewrite:block:call $@"
eval """.block.$1.start.plan() {
@@ -200,8 +222,56 @@ nux.nuxsh.language.def() {
}
"""
}
+
+ .action.block.rewrite.call2() {
+ echo "# block:rewrite:block:call2 $@"
+ nux.nuxsh.block.rewrite.call "$1" "$2" "$3"
+ }
+
}
+nux.nuxsh.block.rewrite.call() {
+ eval """.block.$1.start.plan() {
+ echo \"\${indent}\"'${2}'\" \$args\"
+ }
+
+ .block.$1.end.plan() {
+ local args=\"\$(.block.args.get)\";
+ echo \"\${indent}\"'${3}' \"\$args\"
+ }
+ """
+}
+
+nux.nuxsh.block.rewrite.func() {
+ eval """
+ .block.$1.start.plan() {
+ ${2} \"\${indent}\" \"\$args\"
+ }
+ .block.$1.end.plan() {
+ ${3} \"\${indent}\" \"\$args\"
+ }
+ """
+}
+
+nux.nuxsh.statement.rewrite.func() {
+ eval """
+ .statement.$1.plan() {
+ ${2} \"\${indent}\" \"\$args\"
+ }
+ """
+}
+
+nux.nuxsh.statement.rewrite.call() {
+ eval """.statement.$1.plan() {
+ nux.nuxsh.statement.rewrite.call0 '$2' '$3'
+ }
+ """
+}
+nux.nuxsh.statement.rewrite.call0() {
+ echo "${indent}${1} $args ${2}"
+}
+
+
function nux.nuxsh.use {
local file="$1";
local cached="$2";
diff --git a/inc/nux.repl.inc.sh b/inc/nux/repl.inc.sh
old mode 100644
new mode 100755
similarity index 100%
rename from inc/nux.repl.inc.sh
rename to inc/nux/repl.inc.sh
diff --git a/inc/nuxfs.inc.sh b/inc/nuxfs.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/nuxr.nuxsh.sh b/inc/nuxr.nuxsh.sh
old mode 100644
new mode 100755
index 8436199..1e66c4f
--- a/inc/nuxr.nuxsh.sh
+++ b/inc/nuxr.nuxsh.sh
@@ -13,7 +13,7 @@ nux.use nuxr/repl
else
echo "$NUX_SCRIPTNAME: Unrecognized task ''$TASK' not available."
echo "Try '$NUX_SCRIPTNAME help' for more information."
- return -1
+ return 1
}
}
@@ -94,7 +94,7 @@ nux.use nuxr/repl
| nux.help.shelldoc
return 0
else
- return -1
+ return 1
}
}
}
diff --git a/inc/nuxr/repl.nuxsh.sh b/inc/nuxr/repl.nuxsh.sh
old mode 100644
new mode 100755
index dfd3f1d..2ef9f19
--- a/inc/nuxr/repl.nuxsh.sh
+++ b/inc/nuxr/repl.nuxsh.sh
@@ -2,7 +2,7 @@
###
#
#
-@namespace nuxr.repl. {
+@namespace nuxr.repl {
function :process {
backendFunc=task.$command;
if nux.check.function repl.command.$command; then
@@ -27,7 +27,7 @@
}
-@namespace repl.command. {
+@namespace repl.command {
##
## repl.command.::
## fallback command which does nothing if user just presses enter.
@@ -54,7 +54,7 @@
}
-@namespace nuxr.repl.completer. {
+@namespace nuxr.repl.completer {
function :search.tasks {
set | grep -G "^task\.$1.* ()" \
diff --git a/inc/taskie/backend.dir.inc.sh b/inc/taskie/backend.dir.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/backend.github.inc.sh b/inc/taskie/backend.github.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/backend.gogs.inc.sh b/inc/taskie/backend.gogs.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/backend.utils.inc.sh b/inc/taskie/backend.utils.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/backend.yaml.inc.sh b/inc/taskie/backend.yaml.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/common.inc.sh b/inc/taskie/common.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/githublike.inc.sh b/inc/taskie/githublike.inc.sh
old mode 100644
new mode 100755
diff --git a/inc/taskie/nux.preprocess.inc.sh b/inc/taskie/nux.preprocess.inc.sh
new file mode 100755
index 0000000..d52287c
--- /dev/null
+++ b/inc/taskie/nux.preprocess.inc.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+nux.prep.rewrite() {
+
+}
+
+nux.prep.include() {
+
+}
+
+nux.prep.exec() {
+
+}
diff --git a/inc/thumby.inc.sh b/inc/thumby.inc.sh
deleted file mode 100644
index 86ceb04..0000000
--- a/inc/thumby.inc.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-nux.use nux.mime
-
-function thumby.name.shared() {
- echo $(basename "$1"|md5sum|cut -d " " -f1).png
-}
-
-function thumby.noop() {
- :
-}
-
-function thumby.mimetype.supported() {
- local mimetype="$1";
- local base="${mimetype%%/*}";
- local helper="${mimetype/\//.}";
- if [ "$base" == "image" ]; then
- return 0;
- elif nux.check.function thumby.thumb.source.locator.$helper; then
- return 0;
- elif nux.check.function thumby.thumb.source.extractor.$helper; then
- return 0;
- fi
- return 1;
-}
-
-
-function thumby.thumb.can.generate() {
- local path="$1";
- local mimetype="$2";
- local helper="${mimetype/\//.}";
-
- if ! thumby.mimetype.supported "$mimetype" ; then
- return 1;
- fi
-
- if nux.check.function thumby.thumb.source.locator.$helper; then
- local source=$(thumby.thumb.source.locator.$helper "$path");
- if [ -z "$source" ] ; then
- return 1;
- fi
- fi
- return 0;
-}
-
-function thumby.thumb.get() {
- local path="$1";
- local mimetype="$2";
-
- if [ ! -e "$path" ] ; then
- return -1;
- fi
-
- if [ -z "$mimetype" ] ; then
- mimetype=$(nux.mime "$path")
- fi
-
- local filename=$(basename "$1")
- local dirname=$(dirname "$1")
- local thumbname="$(thumby.name.shared "$filename")";
- local thumbpath="$dirname/.sh_thumbnails/large/$thumbname";
- if [ ! -e "$thumbpath" ]; then
-
- helper="${mimetype/\//.}"
- nux.log debug "File $path, type $mimetype does not have thumbnail. Trying to generate using $helper."
-
- local preexec=thumby.noop;
- local postexec=thumby.noop;
- local source=$path;
- local streamer=thumby.noop;
- if nux.check.function thumby.thumb.source.locator.$helper ; then
- source=$(thumby.thumb.source.locator.$helper "$path");
- fi
- if nux.check.function thumby.thumb.source.extractor.$helper ; then
- echo "Using source helper" >&2
- source="-"
- streamer=thumby.thumb.source.extractor.$helper;
- fi
-
-
- mkdir -p "$dirname/.sh_thumbnails/large" &>/dev/null
- mtime=`stat -c '%Y' "$path"`
-
- $preexec "$path"
- nux.log info "Source is : $source, Streamer is $streamer";
- $streamer "$path" | convert -thumbnail '256x256>' -strip "$source" "$thumbpath" >&2
- $postexec "$path"
- echo $thumbpath;
- fi
-
-}
-
-function thumby.thumb.generate() {
- convert -thumbnail '256x256>' -strip "$path" "$thumbpath" >&2
-}
-
-function thumby.get.thumb() {
- local path="$1";
- local d="$(dirname "$1")";
- local f=$(basename "$1");
- local thumb_name="$(thumby.name.shared "$f")"
- if [ ! -e "$path" ] ; then
- return;
- elif [ ! -e "$d/.sh_thumbnails/large/$thumb_name" ] ; then
- #mkdir -p .sh_thumbnails/normal &>/dev/null
- mkdir -p "$d/.sh_thumbnails/large" &>/dev/null
- #md5=`echo $path|md5sum|cut -d" " -f1`
- mtime=`stat -c '%Y' "$path"`
- nux.log info "Generating thumbnails for $path $thumb_name" >&2
- #convert -thumbnail '128x128>' -strip -set Thumb::MTime "$mtime" -set Thumb::URI "$path" "$path" .sh_thumbnails/normal/$md5.$THUMB_TYPE >&2
- nux.log info "Command line is: " # echo convert -thumbnail '256x256>' -strip -set Thumb::MTime "$mtime" -set Thumb::URI "$path" "$path" .sh_thumbnails/large/$thumb_name
- nux.log info convert -thumbnail '256x256>' --strip "$path" "$d"/.sh_thumbnails/large/$thumb_name
- convert -thumbnail '256x256>' -strip "$path" "$d"/.sh_thumbnails/large/$thumb_name >&2
- fi
- echo "$d/.sh_thumbnails/large/$thumb_name"
-}
-
-
-thumby.thumb.source.locator.directory() {
- nux.log info "Using find to find jpg or png"
- find "$1" -maxdepth 1 -iname "*.jpg" -or -iname "*.png" | sort -n | head -n1
-}
-
-thumby.thumb.source.locator.application.pdf() {
- echo "$1[0]"
-}
-
-thumby.thumb.source.extractor.application.epub+zip() {
-
- local rootDesc=$(unzip -p "$1" META-INF/container.xml \
- | xmlstarlet sel -N od="urn:oasis:names:tc:opendocument:xmlns:container" \
- -t -v "/od:container/od:rootfiles/od:rootfile[@media-type='application/oebps-package+xml']/@full-path" -n)
- nux.log info "Root description is in: $rootDesc";
- local imgDesc=$(unzip -p "$1" "$rootDesc" \
- | xmlstarlet sel -N opf="http://www.idpf.org/2007/opf" \
- -t -m "/opf:package/opf:manifest/opf:item[@id=/opf:package/opf:metadata/opf:meta[@name='cover']/@content]" \
- -v "@href" -o ":" -v "@media-type" -n)
- IFS=":" read -r img media <<< "$imgDesc";
- nux.log info "Image name is $imgDesc $img";
- if [ -n "$img" ]; then
- unzip -p "$1" $img
- fi
-}
-
-thumby.thumb.source.extractor.application.x-cbr() {
- suffix="${1##*.}"
- case "$suffix" in
- zip) ;&
- cbz)
- potential=$(unzip -l "$1" | sed -re "s/^ *[0-9]+ +[0-9\\-]+ +[0-9:]+ +//gi" | grep -E '\.((jpg)|(png)|(jpeg))$' | sort -n | head -n 1)
- nux.log debug "Potential preview is: $potential";
- if [ -n "$potential" ]; then
- unzip -p "$1" "$potential"
- nux.log debug "Preview extracted."
- fi
- ;;
- *) nux.log error "$suffix is not supported."
- esac
-}
diff --git a/inc/thumby.nuxsh.sh b/inc/thumby.nuxsh.sh
new file mode 100755
index 0000000..5bb778d
--- /dev/null
+++ b/inc/thumby.nuxsh.sh
@@ -0,0 +1,130 @@
+nux.use nux/mime
+
+@namespace thumby {
+ function :name.shared {
+ echo $(basename "$1"|md5sum|cut -d " " -f1).png
+ }
+
+ function :noop {
+ :
+ }
+
+ function :image.size {
+ raw_str=$(identify "$1")
+ str=${raw_str#$1 * }
+ echo ${str%% *}
+ }
+
+ function :mimetype.supported {
+ local mimetype="$1";
+ local base="${mimetype%%/*}";
+ local helper="${mimetype/\//.}";
+ if [ "$base" == "image" ]; then
+ return 0;
+ elif nux.check.function thumby.thumb.source.locator.$helper; then
+ return 0;
+ elif nux.check.function thumby.thumb.source.extractor.$helper; then
+ return 0;
+ fi
+ return 1;
+ }
+}
+
+@namespace thumby.thumb {
+
+ function :should.generate path mimetype {
+ local thumbpath=$(thumby.thumb.path "$path");
+ local source=$(thumby.thumb.source "$path" "$mimetype");
+ if [ "$source" -nt "$thumbpath" ]; then
+ return 0;
+ else
+ return 1;
+ fi
+ }
+
+ function :can.generate path mimetype {
+ local helper="${mimetype/\//.}";
+
+ if ! thumby.mimetype.supported "$mimetype" {
+ return 1;
+ }
+
+ if nux.check.function thumby.thumb.source.locator.$helper {
+ local source=$(thumby.thumb.source.locator.$helper "$path");
+ if [ -z "$source" ] {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ function :source path mimetype {
+ local helper="${mimetype/\//.}";
+ if nux.check.function thumby.thumb.source.locator.$helper; then
+ thumby.thumb.source.locator.$helper "$path"
+ else
+ echo "$path";
+ fi
+ }
+
+ function :path path {
+ local filename=$(basename "$path")
+ local dirname=$(dirname "$path")
+ local thumbname="$(thumby.name.shared "$filename")";
+ echo "$dirname/.sh_thumbnails/large/$thumbname";
+ }
+
+ function :get path mimetype {
+
+ nux.log debug "thumby path: $path";
+ if [ ! -e "$path" ] ; then
+ return 1;
+ fi
+
+ if [ -z "$mimetype" ] ; then
+ mimetype=$(nux.mime "$path")
+ fi
+
+ local filename=$(basename "$path")
+ local dirname=$(dirname "$path")
+ local thumbname="$(thumby.name.shared "$filename")";
+ local thumbpath="$dirname/.sh_thumbnails/large/$thumbname";
+
+ nux.log debug "Dir: $dirname, File: $filename, thumb: $thumbname"
+
+ if thumby.thumb.should.generate "$path" "$mimetype" {
+
+ helper="${mimetype/\//.}"
+ nux.log debug "File $path, type $mimetype does not have thumbnail. Trying to generate using $helper."
+
+ local preexec=thumby.noop;
+ local postexec=thumby.noop;
+ local source=$path;
+ local streamer=thumby.noop;
+ if nux.check.function thumby.thumb.source.locator.$helper ; then
+ source=$(thumby.thumb.source.locator.$helper "$path");
+ fi
+ if nux.check.function thumby.thumb.source.extractor.$helper ; then
+ echo "Using source helper" >&2
+ source="-"
+ streamer=thumby.thumb.source.extractor.$helper;
+ fi
+ nux.log debug "File $path, using '$source' as source. Using stremer '$streamer'"
+ mkdir -p "$dirname/.sh_thumbnails/large" &>/dev/null
+ mtime=`stat -c '%Y' "$path"`
+
+ $preexec "$path"
+ nux.log info "Source is : $source, Streamer is $streamer";
+ $streamer "$path" | convert -thumbnail '256x256>' -strip "$source" "$thumbpath" >&2
+ $postexec "$path"
+ }
+ if [ -e "$thumbpath" ]; then
+ echo $thumbpath;
+ fi
+ }
+
+ function :generate {
+ convert -thumbnail '256x256>' -strip "$path" "$thumbpath" >&2
+ }
+
+}
diff --git a/inc/thumby/builtin.nuxsh.sh b/inc/thumby/builtin.nuxsh.sh
new file mode 100755
index 0000000..cc0d16c
--- /dev/null
+++ b/inc/thumby/builtin.nuxsh.sh
@@ -0,0 +1,50 @@
+
+@namespace thumby.thumb.source {
+
+ function :locator.directory {
+ if [ -e "$1/.thumb.jpg" ]; then
+ echo "$1/.thumb.jpg";
+ elif [ -e "$1/.thumb.png" ]; then
+ echo "$1/.thumb.png";
+ # find -L "$1" -maxdepth 1 -iname "*.jpg" -or -iname "*.png" | sort -n | head -n1
+ fi
+ }
+
+ function :locator.application.pdf {
+ echo "$1[0]"
+ }
+
+ function :extractor.application.epub+zip() {
+
+ local rootDesc=$(unzip -p "$1" META-INF/container.xml \
+ | xmlstarlet sel -N od="urn:oasis:names:tc:opendocument:xmlns:container" \
+ -t -v "/od:container/od:rootfiles/od:rootfile[@media-type='application/oebps-package+xml']/@full-path" -n)
+ nux.log info "Root description is in: $rootDesc";
+ local imgDesc=$(unzip -p "$1" "$rootDesc" \
+ | xmlstarlet sel -N opf="http://www.idpf.org/2007/opf" \
+ -t -m "/opf:package/opf:manifest/opf:item[@id=/opf:package/opf:metadata/opf:meta[@name='cover']/@content]" \
+ -v "@href" -o ":" -v "@media-type" -n)
+ IFS=":" read -r img media <<< "$imgDesc";
+ nux.log info "Image name is $imgDesc $img";
+ if [ -n "$img" ]; then
+ unzip -p "$1" $img
+ fi
+ }
+
+ function :extractor.application.x-cbr() {
+ suffix="${1##*.}"
+ case "$suffix" in
+ zip) ;&
+ cbz)
+ potential=$(unzip -l "$1" | sed -re "s/^ *[0-9]+ +[0-9\\-]+ +[0-9:]+ +//gi" | grep -E '\.((jpg)|(png)|(jpeg))$' | sort -n | head -n 1)
+ nux.log debug "Potential preview is: $potential";
+ if [ -n "$potential" ]; then
+ unzip -p "$1" "$potential"
+ nux.log debug "Preview extracted."
+ fi
+ ;;
+ *) nux.log error "$suffix is not supported."
+ esac
+ }
+
+}