diff --git a/assets/nuweb/mdlio-app.css b/assets/nuweb/mdlio-app.css new file mode 100644 index 0000000..0eff490 --- /dev/null +++ b/assets/nuweb/mdlio-app.css @@ -0,0 +1,182 @@ +@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; +} + +.gallery .item .mdl-card_title { + padding: 8px; +} +.gallery .item .mdl-card__title-text { + text-decoration:none; + font-family: "Roboto","Helvetica","Arial",sans-serif +} + +html { + overflow-y: scroll; +} + +.gallery .item.type-image.thumb .mdl-card_title { + display:none; +} + +.relative { + position:relative; +} + +.item.type-person.thumb .mdl-card_title, +.item.type-image.thumb .mdl-card_title { + background: rgba(0,0,0,0.25); + color: #fff; + width: calc(100% - 16px); + text-shadow: 0px 0px 7px rgba(0, 0, 0, 1); + bottom: 0px; + position: absolute; +} + +.gallery .item.type-image:hover .mdl-card_title { + display: block; +} + + + +.file .mdl-card_title-text { + word-break:break-all; +} + + +.file .mdl-card__title-text:before { + font-family: "Material Design Icons"; + margin-right:8px; + content: "\f214"; +} + +.file.type-directory .mdl-card__title-text:before { + content: "\f24b"; +} + +.file.type-person .mdl-card__title-text:before { + content: "\f004"; +} + +.file.type-image .mdl-card__title-text:before { + + content: "\f21f"; +} + +.file.type-tasklist .title:before { + content:"\f755"; +} + +.file.type-video .mdl-card__title-text:before { + content: "\f22b"; +} + +.file[data-mime="application/pdf"] .mdl-card__title-text:before { + content: "\f225" +} + + +.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; +} + +/* +.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 100644 index 0000000..95e674c --- /dev/null +++ b/assets/nuweb/mdlio-app.js @@ -0,0 +1,203 @@ +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) { + for (outlayer of this.outlayers) { + outlayer.appended(items); + } + }; + }, + + 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=` +
+ + +
+ + +
+
+
+
+
+ + +
+ +
+ + + +
+ + + + + + + + + + + +
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+ +
+ +
` + body.appendChild(pswp); + return pswp; + } + +}; diff --git a/bin/nux-env b/bin/nux-env index e43df2a..16c71b3 100755 --- a/bin/nux-env +++ b/bin/nux-env @@ -1,10 +1,11 @@ #!/usr/bin/env nuxr-nuxsh ## Portable *nix environment by tonydamage - -## status:: -## Show status of nux-env installation +## @namespace task. { + +## status:: +## Show status of nux-env installation function :status { echo nux-env folder: $NUX_ENV_DIR pushd $NUX_ENV_DIR > /dev/null @@ -12,8 +13,8 @@ popd > /dev/null } -## update:: -## pulls latest nux-env from repository. +## update:: +## pulls latest nux-env from repository. function :update { pushd $NUX_ENV_DIR > /dev/null git stash @@ -22,8 +23,8 @@ popd > /dev/null } -## install:: -## Install nux-env recommended binaries if not present +## install:: +## Install nux-env recommended binaries if not present function :install { : diff --git a/inc/nuweb.nuxsh.sh b/inc/nuweb.nuxsh.sh new file mode 100644 index 0000000..819c0da --- /dev/null +++ b/inc/nuweb.nuxsh.sh @@ -0,0 +1,98 @@ +## #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 +} + +@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 :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/html.nuxsh.syntax.nuxsh.sh b/inc/nuweb/html.nuxsh.syntax.nuxsh.sh new file mode 100644 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 100644 index 0000000..b38e204 --- /dev/null +++ b/inc/nuweb/html.syntax.nuxsh.sh @@ -0,0 +1,23 @@ +@prefix statement nux.nuxsh.statement +@prefix block nux.nuxsh.block + +@namespace nuweb.html.syntax { + + function :element { + for tag in "$@" ; do + block:rewrite.call nuweb.html.$tag "nuweb.html.element $tag" "nuweb.html.element.end $tag" + statement:rewrite.call nuweb.html.$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 h1 h2 h3 h4 h5 h6 + + :element form input submit button textarea select label +} diff --git a/inc/nuweb/mdlio.app.defaults.nuxsh.sh b/inc/nuweb/mdlio.app.defaults.nuxsh.sh new file mode 100644 index 0000000..32e6991 --- /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 100644 index 0000000..73a6f06 --- /dev/null +++ b/inc/nuweb/mdlio.app.nuxsh.sh @@ -0,0 +1,207 @@ +@syntax nuweb/html + +nux.use nuweb/mdlio +nux.use nuweb/mdlio.app.defaults +nux.use nuweb/router +nux.use nux.mime + +@prefix h nuweb.html +@prefix router nuweb.router + +@block:rewrite:call2 e +e -e ; + +@namespace mdlio.app { + + function mdlio.app { + nux.exec.optional app.init + mdlio.app.html "$@" + } + + function :custom func { + nux.exec.or $func app.$func "$@"; + } + + function :html { + nuweb.content_type text/html + echo + local spec="$1"; shift; + $spec "$@"; + + local app_uri="${NUWEB_SCRIPT_URI}"; + local appName=$(nux.exec.optional app.name); + local title="$(nux.exec.optional title)"; + 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:asset/mdlio-app.css" + h:link @rel stylesheet @href "https://unpkg.com/simplelightbox@1.11.0/dist/simplelightbox.css" + + nux.exec.optional app.custom.head + h:title "$(app.title) - $appName" + } + 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 "$NUWEB_SCRIPT_URI/action:asset/mdlio-app.js" + h:script @src "https://code.getmdl.io/1.3.0/material.min.js" + 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 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:thumb/@+" nuweb.redirect.exec mdlio.app.thumb.get + router:get "/action: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 100644 index 0000000..d81bb8d --- /dev/null +++ b/inc/nuweb/mdlio.app.syntax.nuxsh.sh @@ -0,0 +1,49 @@ +@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 100644 index 0000000..7e5dae3 --- /dev/null +++ b/inc/nuweb/mdlio.nuxsh.sh @@ -0,0 +1,46 @@ +@syntax nuweb/html +@prefix h nuweb.html +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 { + h:input .mdl-textfield__input @type "$type" @id "$id" "$@" + h:label .mdl-textfield__label @for "$id" "$label" + } + } + + function :submit name { + h: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/taskie/nux.preprocess.inc.sh b/inc/taskie/nux.preprocess.inc.sh new file mode 100644 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.nuxsh.sh b/inc/thumby.nuxsh.sh new file mode 100644 index 0000000..2880a13 --- /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 100644 index 0000000..8468d59 --- /dev/null +++ b/inc/thumby/builtin.nuxsh.sh @@ -0,0 +1,46 @@ + +@namespace thumby.thumb.source { + + function :locator.directory { + nux.log info "Using find to find jpg or png" + find -L "$1" -maxdepth 1 -iname "*.jpg" -or -iname "*.png" | sort -n | head -n1 + } + + 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 + } + +}