From 05cae2b23c6aecdfb0648b435f4a1def46c52a48 Mon Sep 17 00:00:00 2001 From: Joan Josep Ordinas Rosa Date: Wed, 10 Aug 2016 18:46:03 +0200 Subject: [PATCH] In principio --- .gitignore | 4 + CHANGES | 71 ++++ LICENSE | 26 ++ Makefile | 105 ++++++ README.md | 26 ++ VERSION | 1 + bin/csv2json | 39 ++ bin/csv2yaml | 47 +++ bin/jqt | 672 +++++++++++++++++++++++++++++++++++ bin/json2csv | 15 + bin/json2yaml | 51 +++ bin/yaml2csv | 45 +++ bin/yaml2json | 39 ++ docs/.gitignore | 2 + docs/Makefile | 99 ++++++ docs/README.md | 8 + docs/config.yaml | 35 ++ docs/document.md | 13 + docs/engine.md | 47 +++ docs/filters.jq | 9 + docs/footer.html | 6 + docs/github.css | 202 +++++++++++ docs/head.html | 18 + docs/home.md | 86 +++++ docs/index.html | 11 + docs/jqt.css | 68 ++++ docs/main.html | 44 +++ docs/metadata.md | 13 + docs/page.html | 16 + docs/snippets.md | 14 + docs/template.md | 30 ++ make.d/config.make | 65 ++++ make.d/debug.make | 30 ++ make.d/setup.make | 15 + share/analytics.m | 19 + share/libjqt.jq | 17 + share/libjqt.m | 87 +++++ share/macros.m | 35 ++ share/xhtml-lat1.m | 103 ++++++ share/xhtml-special.m | 57 +++ share/xhtml-symbol.m | 161 +++++++++ share/youtube.m | 12 + tests/cond-00.jqt | 53 +++ tests/cond-00.json | 9 + tests/cond-01.jqt | 2 + tests/cond-01.json | 1 + tests/cond-02.jqt | 5 + tests/cond-03.jqt | 3 + tests/cond-51.jqt | 6 + tests/cond-51.json | 1 + tests/expand-00.jqt | 1 + tests/expand-01.jqt | 0 tests/expand-02.jqt | 1 + tests/expand-03.jqt | 1 + tests/expand-04.jqt | 6 + tests/expand-05.jqt | 5 + tests/expand-06.jqt | 36 ++ tests/expand-07.jqt | 8 + tests/expand-08.jqt | 12 + tests/expand-09.jqt | 3 + tests/expand-10.jqt | 3 + tests/expand-11.jqt | 2 + tests/expand-12.jqt | 4 + tests/expected/bloc-00.txt | 24 ++ tests/expected/cond-00.txt | 18 + tests/expected/cond-01.txt | 1 + tests/expected/cond-02.txt | 3 + tests/expected/cond-03.txt | 3 + tests/expected/cond-51.txt | 1 + tests/expected/expand-00.jqt | 0 tests/expected/expand-01.jqt | 0 tests/expected/expand-02.jqt | 1 + tests/expected/expand-03.jqt | 0 tests/expected/expand-04.jqt | 0 tests/expected/expand-05.jqt | 3 + tests/expected/expand-06.jqt | 13 + tests/expected/expand-07.jqt | 4 + tests/expected/expand-08.jqt | 11 + tests/expected/expand-09.jqt | 5 + tests/expected/expand-10.jqt | 5 + tests/expected/expand-11.jqt | 5 + tests/expected/expand-12.jqt | 2 + tests/expected/expr-00.txt | 103 ++++++ tests/expected/expr-01.txt | 1 + tests/expected/expr-02.txt | 2 + tests/expected/expr-03.txt | 4 + tests/expected/expr-51.txt | 1 + tests/expected/expr-52.txt | 14 + tests/expected/loop-00.txt | 6 + tests/expected/loop-01.txt | 2 + tests/expected/loop-51.txt | 2 + tests/expected/loop-52.txt | 6 + tests/expected/loop-53.txt | 4 + tests/expected/macros-00.txt | 19 + tests/expected/syntax-00.txt | 49 +++ tests/expr-00.jqt | 91 +++++ tests/expr-00.json | 9 + tests/expr-01.jqt | 1 + tests/expr-01.json | 1 + tests/expr-02.jqt | 6 + tests/expr-02.json | 1 + tests/expr-03.jqt | 4 + tests/expr-03.json | 4 + tests/expr-51.jqt | 1 + tests/expr-51.json | 1 + tests/expr-52.jqt | 9 + tests/expr-52.json | 4 + tests/filters/filters.jq | 19 + tests/loop-00.jqt | 7 + tests/loop-00.json | 9 + tests/loop-01.jqt | 1 + tests/loop-01.json | 1 + tests/loop-51.jqt | 1 + tests/loop-51.json | 3 + tests/loop-52.jqt | 5 + tests/loop-52.json | 1 + tests/loop-53.jqt | 3 + tests/loop-53.json | 1 + tests/macros-00.jqt | 6 + tests/md-00.md | 1 + tests/md-01.md | 6 + tests/syntax-00.jqt | 86 +++++ tools/bump-version.sh | 61 ++++ tools/examples.md | 348 ++++++++++++++++++ tools/make-examples-md | 64 ++++ 125 files changed, 3692 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGES create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 VERSION create mode 100755 bin/csv2json create mode 100755 bin/csv2yaml create mode 100755 bin/jqt create mode 100755 bin/json2csv create mode 100755 bin/json2yaml create mode 100755 bin/yaml2csv create mode 100755 bin/yaml2json create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/config.yaml create mode 100644 docs/document.md create mode 100644 docs/engine.md create mode 100644 docs/filters.jq create mode 100644 docs/footer.html create mode 100644 docs/github.css create mode 100644 docs/head.html create mode 100644 docs/home.md create mode 100644 docs/index.html create mode 100644 docs/jqt.css create mode 100644 docs/main.html create mode 100644 docs/metadata.md create mode 100644 docs/page.html create mode 100644 docs/snippets.md create mode 100644 docs/template.md create mode 100644 make.d/config.make create mode 100644 make.d/debug.make create mode 100644 make.d/setup.make create mode 100644 share/analytics.m create mode 100644 share/libjqt.jq create mode 100644 share/libjqt.m create mode 100644 share/macros.m create mode 100644 share/xhtml-lat1.m create mode 100644 share/xhtml-special.m create mode 100644 share/xhtml-symbol.m create mode 100644 share/youtube.m create mode 100644 tests/cond-00.jqt create mode 100644 tests/cond-00.json create mode 100644 tests/cond-01.jqt create mode 100644 tests/cond-01.json create mode 100644 tests/cond-02.jqt create mode 100644 tests/cond-03.jqt create mode 100644 tests/cond-51.jqt create mode 100644 tests/cond-51.json create mode 100644 tests/expand-00.jqt create mode 100644 tests/expand-01.jqt create mode 100644 tests/expand-02.jqt create mode 100644 tests/expand-03.jqt create mode 100644 tests/expand-04.jqt create mode 100644 tests/expand-05.jqt create mode 100644 tests/expand-06.jqt create mode 100644 tests/expand-07.jqt create mode 100644 tests/expand-08.jqt create mode 100644 tests/expand-09.jqt create mode 100644 tests/expand-10.jqt create mode 100644 tests/expand-11.jqt create mode 100644 tests/expand-12.jqt create mode 100644 tests/expected/bloc-00.txt create mode 100644 tests/expected/cond-00.txt create mode 100644 tests/expected/cond-01.txt create mode 100644 tests/expected/cond-02.txt create mode 100644 tests/expected/cond-03.txt create mode 100644 tests/expected/cond-51.txt create mode 100644 tests/expected/expand-00.jqt create mode 100644 tests/expected/expand-01.jqt create mode 100644 tests/expected/expand-02.jqt create mode 100644 tests/expected/expand-03.jqt create mode 100644 tests/expected/expand-04.jqt create mode 100644 tests/expected/expand-05.jqt create mode 100644 tests/expected/expand-06.jqt create mode 100644 tests/expected/expand-07.jqt create mode 100644 tests/expected/expand-08.jqt create mode 100644 tests/expected/expand-09.jqt create mode 100644 tests/expected/expand-10.jqt create mode 100644 tests/expected/expand-11.jqt create mode 100644 tests/expected/expand-12.jqt create mode 100644 tests/expected/expr-00.txt create mode 100644 tests/expected/expr-01.txt create mode 100644 tests/expected/expr-02.txt create mode 100644 tests/expected/expr-03.txt create mode 100644 tests/expected/expr-51.txt create mode 100644 tests/expected/expr-52.txt create mode 100644 tests/expected/loop-00.txt create mode 100644 tests/expected/loop-01.txt create mode 100644 tests/expected/loop-51.txt create mode 100644 tests/expected/loop-52.txt create mode 100644 tests/expected/loop-53.txt create mode 100644 tests/expected/macros-00.txt create mode 100644 tests/expected/syntax-00.txt create mode 100644 tests/expr-00.jqt create mode 100644 tests/expr-00.json create mode 100644 tests/expr-01.jqt create mode 100644 tests/expr-01.json create mode 100644 tests/expr-02.jqt create mode 100644 tests/expr-02.json create mode 100644 tests/expr-03.jqt create mode 100644 tests/expr-03.json create mode 100644 tests/expr-51.jqt create mode 100644 tests/expr-51.json create mode 100644 tests/expr-52.jqt create mode 100644 tests/expr-52.json create mode 100644 tests/filters/filters.jq create mode 100644 tests/loop-00.jqt create mode 100644 tests/loop-00.json create mode 100644 tests/loop-01.jqt create mode 100644 tests/loop-01.json create mode 100644 tests/loop-51.jqt create mode 100644 tests/loop-51.json create mode 100644 tests/loop-52.jqt create mode 100644 tests/loop-52.json create mode 100644 tests/loop-53.jqt create mode 100644 tests/loop-53.json create mode 100644 tests/macros-00.jqt create mode 100644 tests/md-00.md create mode 100644 tests/md-01.md create mode 100644 tests/syntax-00.jqt create mode 100755 tools/bump-version.sh create mode 100644 tools/examples.md create mode 100755 tools/make-examples-md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f01f78 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Output of templates expansion +tests/generated/*.jqe +tests/generated/*.jqs +tests/generated/*.txt diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..fd8c418 --- /dev/null +++ b/CHANGES @@ -0,0 +1,71 @@ +Version 0.2.0: + + +Version 0.1.0 + - Added VERSION and CHANGES files, version bump to v0.1.0 + - Version bump to 0.2.0 + - Added VERSION and CHANGES files, version bump to v0.1.0 + - Finished tool + - Home finished + - New syntax colors + - Index renamed + - Blocks implemented + - Added page for engine + - Finished layout + - menu with logo + - Link to website + - Colorized code and simple TOC + - Fixed: tee input cannot be empty + - Merge branch 'FM' + - Removed -F + - Unified -m -M -F + - Using config.json + - Added 6 conversors: csv, yaml, json + - Better API for metadata + - No front-matter in templates + - It works! + - First doc created! + - Renamed extensions for macro files + - New fifo based implementation + - More complete example + - Standalone jqt + - Expand JSON + - Independent expand + - Merge branch 'unify' + - Unified macro syntax + - Merge branch 'master' into unify + - Merge branch 'top' + - Accept empty documents + - Changed @ by % in data + - Compact markup + - New chart + - Merge branch 'MERGE' + - External file to merge script + - Check some error conditions + - Merge branch 'FM' + - New sync hack + - Better sync + - Bug on subshells fixed + - markup extract YAML + - Full merge + - Full merge 2 + - Full merge 1 + - Finished merge! + - Merge front-end and content + - You cannot have and eat your cake + - Start merge + - Front matter management + - Added YAML options + - Help for Pandoc options + - Sorted pandoc options + - Better documentation. + - Going to prepare content + - Created jqt + - Content is now optional + - Better render interface + - Refactoring for unification (1) + - Integrated entities + - Added expand tests + - Makefile defined + - In principio + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d9b2aba --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +jqt is copyright (c) 2016 Joan Josep Ordinas Rosa + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +jqt's documentation (everything found under the docs/ subdirectory in +the source tree) is licensed under the Creative Commons CC BY 3.0 +license, which can be found at: + + https://creativecommons.org/licenses/by/3.0/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0e399b4 --- /dev/null +++ b/Makefile @@ -0,0 +1,105 @@ +# jqt management +# + +project=jqt + +include make.d/config.make +include make.d/debug.make + +######################################################################## +# Parameters (redefine as you like) +######################################################################## + +prefix ?= /usr/local +bindir ?= $(prefix)/bin +datadir ?= $(prefix)/share + +######################################################################## +# Rules +######################################################################## + +# Configure tools +include make.d/setup.make + +# Default target +all: check + +######################################################################## +# Utilities +######################################################################## + +.PHONY: clean clobber install uninstall + +clean: + rm -f tests/generated/* + +clobber: clean + +install: + test -d $(bindir) || $(SUDO) mkdir --verbose --parents $(bindir) + test -d $(datadir)/$(project) || $(SUDO) mkdir --verbose --parents $(datadir)/$(project) + $(SUDO) install --verbose --compare --mode 555 bin/* $(bindir) + $(SUDO) install --verbose --compare --mode 644 share/* $(datadir)/$(project) + +uninstall: + $(SUDO) rm --verbose --force -- $(addprefix $(prefix)/,$(wildcard bin/*)) + test -d $(datadir)/$(project) \ + && $(SUDO) rm --verbose --force --recursive $(datadir)/$(project) \ + || true + +# Show targets +.PHONY: help +help: + echo 'Targets:'; \ + $(MAKE) --print-data-base --just-print 2>&1 \ + | grep -v '^[mM]akefile' \ + | awk '/^[^ \t.%][-A-Za-z0-9_]*:/ { print $$1 }' \ + | sort --unique \ + | sed 's/:\+$$//' \ + | pr --omit-pagination --indent=4 --width=80 --columns=4 + +######################################################################## +# Tests +######################################################################## + +.PHONY: check cond expr loop macros syntax expand + +check: expand jqt +jqt: cond expr loop macros syntax + +define TestJQT +# Run one example +$(1)-%.jqt: + echo "==> $$(basename $$@)" + if [[ -e tests/$$(basename $$@).json ]]; then \ + jqt -ifilters -Ltests/filters -Mtop:tests/$$(basename $$@).json -dtests/md-00.md tests/$$@ tests/generated/$$(basename $$@).txt; \ + else \ + jqt -ifilters -Ltests/filters -dtests/md-00.md tests/$$@ tests/generated/$$(basename $$@).txt; \ + fi + diff tests/expected/$$(basename $$@).txt tests/generated/$$(basename $$@).txt +# Run one example named without file suffix +$(1)-%: $(1)-%.jqt ; +# Run all tests +$(1): $(sort $(subst tests/,,$(wildcard tests/$(1)-[0-9][0-9].jqt))) +endef + +define TestGPP +# Run one example +$(2)-%.$(1): + echo "==> $$(basename $$@)" + jqt -E tests/$$@ > tests/generated/$$@ + diff tests/expected/$$@ tests/generated/$$@ +# Run one example named without file suffix +$(2)-%: $(2)-%.$(1) ; +# Run all tests +$(2): $(sort $(subst tests/,,$(wildcard tests/$(2)-[0-9][0-9].$(1)))) +endef + +$(eval $(call TestGPP,jqt,expand)) +$(eval $(call TestJQT,cond)) +$(eval $(call TestJQT,expr)) +$(eval $(call TestJQT,loop)) +$(eval $(call TestJQT,macros)) +$(eval $(call TestJQT,syntax)) + +# vim:ai:sw=8:ts=8:noet:syntax=make diff --git a/README.md b/README.md new file mode 100644 index 0000000..7028045 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# _jqt_ · The _jq_ template engine + +_jqt_ is a template engine that uses [_jq_](https://stedolan.github.io/jq/) as expression language. + +If you want to learn to use _jqt_, read the documentation at +. This documentation is generated using _jqt_ from the `docs/` +folder of this repository. + +The tools used in the implementation of _jqt_ are: + +* [jq](https://stedolan.github.io/jq/), a lightweight and flexible command-line JSON processor. +* [GPP](https://logological.org/gpp), a general-purpose preprocessor. +* [Pandoc](http://pandoc.org/), a universal document converter. +* [GNU Make](https://www.gnu.org/software/make/), the classical tool for managing projects. +* [Bash](https://www.gnu.org/software/bash/), [sed](https://www.gnu.org/software/sed/) and other shell tools. + +You must install all these software before diving into _jqt_. + +_jqt_ is developed under the _Fedora_ Linux distribution, and a lot of +portability issues are expected at this stage of development. Please, use this +GitHub repository features if you want to send any kind of questions. + + + diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..0ea3a94 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.2.0 diff --git a/bin/csv2json b/bin/csv2json new file mode 100755 index 0000000..18b6658 --- /dev/null +++ b/bin/csv2json @@ -0,0 +1,39 @@ +#!/usr/bin/python + +# Simple CSV to JSON conversor + +import sys +import csv +import json + +def error(e): + sys.stderr.write(type(e).__name__ + ': ' + str(e) + '\n') + sys.exit(1) + +def load_csv(): + if len(sys.argv) > 1: + reader = csv.DictReader(open(sys.argv[1]) ) + else: + reader = csv.DictReader(sys.stdin) + return reader + +def dump_json(seq): + d = None + for d in seq: + json.dump(d, sys.stdout, indent=2, sort_keys=False) + sys.stdout.write('\n') + if d is None: + sys.stdout.write('\n') + +# +# Main +# + +try: + dump_json(load_csv()) +except Exception as e: + error(e) + +sys.exit(0); + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=python diff --git a/bin/csv2yaml b/bin/csv2yaml new file mode 100755 index 0000000..922eff7 --- /dev/null +++ b/bin/csv2yaml @@ -0,0 +1,47 @@ +#!/usr/bin/python + +# Simple CSV to YAML conversor + +import sys +import csv +import yaml + +def error(e): + sys.stderr.write(type(e).__name__ + ': ' + str(e) + '\n') + sys.exit(1) + +def load_csv(): + if len(sys.argv) > 1: + reader = csv.DictReader(open(sys.argv[1]) ) + else: + reader = csv.DictReader(sys.stdin) + return reader + +def dump_yaml(seq): + d = None + for d in seq: + yaml.safe_dump(d, sys.stdout, + default_flow_style=False, + default_style=None, + encoding='utf-8', + explicit_start=True, + explicit_end=False, + indent=2, + ) + if d is None: # some dumped? + sys.stdout.write('\n') + else: + sys.stdout.write('...\n') + +# +# Main +# + +try: + dump_yaml(load_csv()) +except Exception as e: + error(e) + +sys.exit(0); + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=python diff --git a/bin/jqt b/bin/jqt new file mode 100755 index 0000000..b2b2123 --- /dev/null +++ b/bin/jqt @@ -0,0 +1,672 @@ +#!/bin/bash + +# jqt - jq based template engine + +declare -r VERSION='0.1' # jqt version +declare -r DATADIR='/usr/local/share' + +declare -r SELF=${0##*/} + +######################################################################## +# Bash options +######################################################################## + +# Safety +set -o errexit -o pipefail -o nounset -o noclobber + +# Bash extensions +set +o posix +shopt -s lastpipe + +######################################################################## +# Global filenames +######################################################################## + +declare -r TMPDIR="/tmp/${SELF}-$$" + +function initialize +{ + mkdir $TMPDIR + trap "rm -rf ${TMPDIR}" EXIT HUP INT TERM +} + +function mkpipe +{ + local -r LOCK="${TMPDIR}/mkpipe-lock" + local -i i=0 + while ! { : > $LOCK; } 2>/dev/null; do + sleep 0.01; + i+=1 + (( i > 100 )) && die 'Bored waiting a lock' + done + + local n="${TMPDIR}/$RANDOM" + while [[ -e $n ]]; do n="${TMPDIR}/$RANDOM"; done + mkfifo --mode 600 $n + + rm -f $LOCK + + echo -n $n +} + +######################################################################## +# Extract YAML front matter +######################################################################## + +# < stdin > stdout +function fork_yaml +{ + local front_matter=$1 p=$(mkpipe) line + + # < stdin > stdout + { read -r line + if [[ $line != '---' ]]; then + echo '{ "front-matter": false }' + else { + echo 'front-matter: true' + IFS='' + while read -r line; do + [[ $line == '---' ]] && break + [[ $line == '...' ]] && break + [[ $line == '#'* ]] && continue + echo "$line" + done + } | yaml2json + fi + } < $p > $front_matter & + # Warning: input cannot be absolutely empty!!! + tee $p +} + +######################################################################## +# Expand template and document +######################################################################## + +declare -a DEFINE=( "-Dversion=$VERSION" ) +declare -a GPP_PATH=( "-I${DATADIR}/jqt" ) + +# < stdin > stdout +function expand_jqt +{ + # File to load before input file (only one allowed) + local -r lib="libjqt.m" + + # Macros + local -r -a user=( -U + # Macro call delimiters + '<%' '>' + # Arguments delimiters + '\B' '\B' '\W>' + # Stackable characters + '<' '>' + # String to be used for referring to parameters by number + '$' + # The quote character must be defined adhoc for each file, like: + # <%mode quote "\\"> + # Also, if desired, multicharacter quote strings can be defined like: + # <%mode string iiq "[" "]" "\\"> + '' + ) + local -r -a meta=( -M '<%' '>' '\B' '\B' '\W>' '<' '>') + + # Comments and strings + local -r -a skips=( + +sccc '&\n' '' '' # continuation line (& and \n removed) + +sccc '<#' '#>\n' '' # multiline comment, must end in \n + +siqi "'" "'" '' # literal string; like sh single quotes + +siQi '"' '"' '' # interpolated string; like sh double quotes + +ssss '' '' # preserved XML comments + +sSSS '{{' '}}' '' # jq processing + +sSSS '{%' '%}' '' + +sSSS '{#' '#}' '' + ) + gpp --nostdinc \ + --warninglevel 2 \ + "${user[@]}" \ + "${meta[@]}" \ + "${skips[@]}" \ + "${GPP_PATH[@]}" \ + "${DEFINE[@]}" \ + --include "$lib" +} + +# < stdin > stdout +function expand_md +{ + local -r lib="libjqt.m" + local -r -a user=( -U '<%' '>' '\B' '\B' '\W>' '<' '>' '$' '' ) + local -r -a meta=( -M '<%' '>' '\B' '\B' '\W>' '<' '>' ) + local -r -a skips=( + +sccc '&\n' '' '' + +sccc '<#' '#>\n' '' + +siqi "'" "'" '' + +siQi '"' '"' '' + +ssss '' '' + +ssss '\n```' '\n```' '' + +ssss '\n~~~' '\n~~~' '' + ) + gpp --nostdinc \ + --warninglevel 2 \ + "${user[@]}" \ + "${meta[@]}" \ + "${skips[@]}" \ + "${GPP_PATH[@]}" \ + "${DEFINE[@]}" \ + --include "$lib" + echo # always generate almost one line!!! +} + +# < stdin > stdout +function expand_json +{ + local -r -a meta=( -M '' '\b' '\b' '>' '<' '>' ) + local -r -a user=( -U '&' ';' '(' ')' ';' '(' ')' '\$' '' ) + local -r -a skips=( + +cccc '\\n' '' \ + +cccc '/*' '*/' \ + +cccc '//' '\n' \ + +sSSS '"' '"' '\' \ + +sqqq '`' '`' '' \ + ) + gpp --nostdinc \ + --warninglevel 2 \ + "${user[@]}" \ + "${meta[@]}" \ + "${skips[@]}" \ + "${GPP_PATH[@]}" \ + "${DEFINE[@]}" + echo # always generate almost one line +} + +######################################################################## +# Convert template to script +######################################################################## + +declare -A IMPORTS=( [jqt]='libjqt' ) +declare -A INCLUDES=() + +# < stdin > stdout +function convert +{ + local module + + # script preamble + echo '# vim:tabstop=2:syntax=jq' + + # jq modules + for module in ${!INCLUDES[@]}; do + echo "include \"${INCLUDES[$module]}\";" + done + for module in ${!IMPORTS[@]}; do + echo "import \"${IMPORTS[$module]}\" as $module;" + done + + # $M as a global metadata reference + echo '. as $M |' + + # convert template to script + sed -e ' +:RAW +# if raw block: {% raw %} ... {%%} + /^[ \t]*{%[ \t]*raw[ \t]*%}[ \t]*$/,/^[ \]t*{%[ \t]*endraw[ \t]*%}[ \t]*$/ { + /^[ \t]*{%[ \t]*\(end\)\?raw[ \t]*%}[ \t]*$/ d + s/["\\]/\\&/g + s/^.*$/"&",/ + b + } + +:COMMENT +# comments, multiline, not nested: {# ... #} + /^\(.*\){#.*#}/ { + s//\1/ + t COMMENT + } + /{#/! b BLOCK + N + b COMMENT + +:BLOCK +# if end multiline block: {% end %} + /^[ \t]*{%[ \t]*end[ \t]*%}[ \t]*$/ { + s//empty)),/ + b + } +# if start multiline block: {% ... %} + /^\([ \t]*\){%\(.\+\)%}[ \t]*$/ { + s//\1(\2 | (/ + b + } + +:EXPRESSION +# expressions, multiline, not nested: ... {{ ... }} ... + /^\(.*\){{\(.\+\)}}.*$/ { + h + s//\2/ + y/"\\\n/\cA\cB\cC/ + G + s/^\(.*\)\n\(.*\){{.*}}/\2\cB(\1)/ + b EXPRESSION + } + /{{/! b LINE + N + b EXPRESSION + +:LINE +# if one line block: {% ... %} ... + /^\([ \t]*\){%\(.\+\)%}\(.\+\)$/ { + h + s//\2/ + y/"\\\n/\cA\cB\cC/ + G + s/^\(.*\)\n\([ \t]*\){%.\+%}\(.*\)$/(\2\1 | \cA\3\cA),/ + s/["\\]/\\&/g + y/\cA\cB\cC/"\\\n/ + b + } +# else simple text line + s/["\\]/\\&/g + y/\cA\cB\cC/"\\\n/ + s/^.*$/"&",/ +' + # script ending + echo 'empty' +} + +######################################################################## +# Markup document +######################################################################## + +declare DOCUMENT='' DOCUMENT_ID='stdin' HTML_VERSION='html' +declare -a PANDOC_OPTS=( '--from=markdown-pandoc_title_block' ) + +# < stdin > stdout +function markup +{ + local template=${TMPDIR}/template.html + + echo \ +'$if(highlighting-css)$ + +$endif$ + +$if(toc)$ +$toc$ +$endif$ + +$body$ +' > $template + + pandoc "${PANDOC_OPTS[@]}" \ + --to=$HTML_VERSION \ + --table-of-contents \ + --toc-depth=6 \ + --template=$template \ + --output='-' +} + +######################################################################## +# Manage front matter +######################################################################## + +function has_front_matter +{ + # warning: consume one line + local line + read -r line + [[ $line == '---' ]] +} + +function extract_front_matter +{ + # warning: assume front matter exists + sed -n -e '1d;/^---$/q;/^\.\.\.$/q;/^#/d;p' +} + +function remove_front_matter +{ + # warning: remove all YAML blocks + sed -e '/^---$/,/\(^\.\.\.$$\)\|\(^---$\)/d' +} + +######################################################################## +# Merge document and all metadata +######################################################################## + +declare DOCUMENT_METADATA_NAME='front' # front matter +declare DOCUMENT_CONTENT_NAME='body' # body matter + +declare -A JSON_METADATA=() YAML_METADATA=() +declare -A JSON_METADATA_DOT=() YAML_METADATA_DOT=() + +function yaml2json +{ + python -c ' +import sys, yaml, json +json.dump(yaml.safe_load(sys.stdin), sys.stdout, indent=2, sort_keys=False) +sys.stdout.write("\n") +' +} + +# < stdin > stdout +function merge +{ + local front_matter=$1 key + local -r script=$(mkpipe) + + JSON_METADATA[$DOCUMENT_METADATA_NAME]=$front_matter + + { echo '(./"") as [$css, $toc, $body] |' + echo "{id:\"${DOCUMENT%.md}\", $DOCUMENT_CONTENT_NAME:"'$body, toc:$toc, highlight:$css}' + for key in "${!YAML_METADATA[@]}"; do + echo "+{ $key:" + yaml2json < "${YAML_METADATA[$key]}" + echo "}" + done + for key in "${!YAML_METADATA_DOT[@]}"; do + echo "+" + yaml2json < "${YAML_METADATA_DOT[$key]}" + done + for key in "${!JSON_METADATA[@]}"; do + echo "+{ $key:" + expand_json < "${JSON_METADATA[$key]}" + echo "}" + done + for key in "${!JSON_METADATA_DOT[@]}"; do + echo "+" + expand_json < "${JSON_METADATA_DOT[$key]}" + done + } > $script & + + jq --raw-input \ + --slurp \ + --from-file $script +} + +######################################################################## +# Render template +######################################################################## + +declare -a JQ_PATH=( '-L' "$DATADIR/jqt" ) + +# < stdin > stdout +function render +{ + local script=$1 + + jq "${JQ_PATH[@]}" \ + '--raw-output' \ + '--from-file' \ + "$script" +} + +######################################################################## +# Help +######################################################################## + +declare -r USAGE=\ +"Usage: $SELF [-h | --help ] + $SELF [options] < infile > result + $SELF [options] infile > result + $SELF [options] infile result" + +function usage +{ + (( $# > 0 )) && echo 1>&2 "$SELF: $@" + echo 1>&2 "$USAGE" + exit 2 +} + +function die +{ + echo 1>&2 "$SELF: $@" + exit 1 +} + +function help +{ + cat < 2 )) && usage 'Expected one or two arguments' + +(( flagE+flagS+flagP+flagH+flagC > 1 )) && die 'Cannot mix options: -E, -S, -P, -H, -C' +(( extract+remove+front_matter > 1 )) && die 'Cannot mix options: -e, -r, -t' +(( flagE+flagS+flagP+flagH+flagC+extract+remove+front_matter > 1 )) && die 'Incompatible options' + +######################################################################## +# Main +######################################################################## + +initialize + +declare -r FRONT_MATTER=$(mkpipe) +declare -r RENDER_SCRIPT=$(mkpipe) + +(( $# >= 1 )) && exec < $1 +(( $# == 2 )) && exec >| $2 + +if (( extract )); then extract_front_matter +elif (( remove )); then remove_front_matter +elif (( front_matter )); then has_front_matter +elif (( flagE )); then expand_jqt +elif (( flagS )); then expand_jqt | convert +elif (( flagP )); then expand_md +elif (( flagH )); then expand_md | markup +elif (( flagC )); then expand_md | fork_yaml $FRONT_MATTER | markup | merge $FRONT_MATTER +elif [[ -z $DOCUMENT ]]; then expand_md | markup +else + # process template + expand_jqt \ + | convert \ + > $RENDER_SCRIPT & + + # process document + < $DOCUMENT \ + expand_md \ + | fork_yaml $FRONT_MATTER \ + | markup \ + | merge $FRONT_MATTER \ + | render $RENDER_SCRIPT +fi + +exit 0 + +# vim:ts=4:sw=4:ai:et:fileencoding=utf-8:syntax=sh diff --git a/bin/json2csv b/bin/json2csv new file mode 100755 index 0000000..b378244 --- /dev/null +++ b/bin/json2csv @@ -0,0 +1,15 @@ +#!/bin/bash + +# Simple JSON to CSV conversor + +test $# -gt 0 && exec < $1 + +jq --slurp --raw-output ' + (.[0]//{} | keys_unsorted) as $cols | + map(. as $row | $cols | map($row[.])) as $rows | + $cols, $rows[] | @csv +' + +exit + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=sh diff --git a/bin/json2yaml b/bin/json2yaml new file mode 100755 index 0000000..b9c7802 --- /dev/null +++ b/bin/json2yaml @@ -0,0 +1,51 @@ +#!/usr/bin/python + +# Simple JSON to YAML conversor + +import sys +import yaml +import json + +def error(e): + sys.stderr.write(type(e).__name__ + ': ' + str(e) + '\n') + sys.exit(1) + +def load_json(): + if len(sys.argv) > 1: + data = open(sys.argv[1]).read().strip() + else: + data = sys.stdin.read().strip() + decoder = json.JSONDecoder(encoding="utf-8", strict=True) + while data != "": + obj, end = decoder.raw_decode(data) + yield obj + data = data[end:].strip() + +def dump_yaml(seq): + obj = None + for obj in seq: + yaml.safe_dump(obj, sys.stdout, + default_flow_style=False, + default_style=None, + encoding='utf-8', + explicit_start=True, + explicit_end=False, + indent=2, + ) + if obj is None: # some dumped? + sys.stdout.write('\n') + else: + sys.stdout.write('...\n') + +# +# Main +# + +try: + dump_yaml(load_json()) +except Exception as e: + error(e) + +sys.exit(0); + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=python diff --git a/bin/yaml2csv b/bin/yaml2csv new file mode 100755 index 0000000..b3e4c59 --- /dev/null +++ b/bin/yaml2csv @@ -0,0 +1,45 @@ +#!/usr/bin/python + +# Simple YAML to CSV conversor + +import sys +import yaml +import csv + +def error(e): + sys.stderr.write(type(e).__name__ + ': ' + str(e) + '\n') + sys.exit(1) + +def load_yaml(): + if len(sys.argv) > 1: + seq = yaml.safe_load_all(open(sys.argv[1])) + else: + seq = yaml.safe_load_all(sys.stdin) + return seq + +def dump_csv(seq): + try: + d = next(seq) + except StopIteration: + sys.stdout.write('\n') + return + writer = csv.DictWriter(sys.stdout, + fieldnames=d.keys(), + quoting=csv.QUOTE_NONNUMERIC) + writer.writeheader() + writer.writerow(d) + for d in seq: + writer.writerow(d) + +# +# Main +# + +try: + dump_csv(load_yaml()) +except Exception as e: + error(e) + +sys.exit(0); + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=python diff --git a/bin/yaml2json b/bin/yaml2json new file mode 100755 index 0000000..29b9356 --- /dev/null +++ b/bin/yaml2json @@ -0,0 +1,39 @@ +#!/usr/bin/python + +# Simple YAML to JSON conversor + +import sys +import yaml +import json + +def error(e): + sys.stderr.write(type(e).__name__ + ': ' + str(e) + '\n') + sys.exit(1) + +def load_yaml(): + if len(sys.argv) > 1: + seq = yaml.safe_load_all(open(sys.argv[1])) + else: + seq = yaml.safe_load_all(sys.stdin) + return seq + +def dump_json(seq): + d = None + for d in seq: + json.dump(d, sys.stdout, indent=2, sort_keys=False) + sys.stdout.write('\n') + if d is None: # some dumped? + sys.stdout.write('\n') + +# +# Main +# + +try: + dump_json(load_yaml()) +except Exception as e: + error(e) + +sys.exit(0); + +# vim:ai:sw=4:ts=4:et:fileencoding=utf-8:syntax=python diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..b76449b --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +snippets.json +snippets.pandoc diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..3fe94d3 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,99 @@ +# jqt docs management +# + +######################################################################## +# Configuration +######################################################################## + +# Disable builtins. +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --no-builtin-variables + +# Warn when an undefined variable is referenced. +MAKEFLAGS += --warn-undefined-variables + +# Make will not print the recipe used to remake files. +#.SILENT: + +# Eliminate use of the built-in implicit rules. Also clear out the +# default list of suffixes for suffix rules. +.SUFFIXES: + +# Sets the default goal to be used if no targets were specified on the +# command line. +.DEFAULT_GOAL := all + +.PHONY: all + +# Default shell: if we require GNU Make, why not require Bash? +SHELL := /bin/bash + +# The argument(s) passed to the shell are taken from the variable +# .SHELLFLAGS. +.SHELLFLAGS := -o errexit -o pipefail -o nounset -c + +######################################################################## +# Variables +######################################################################## + +OUTPUT = /tmp/jqt + +JQT = jqt -ifilters -Mconfig:config.yaml -msnippets:snippets.json +HTMLMIN = sed '/^$$/d' + +TEMPLATES = main.html head.html footer.html +COMMON = $(TEMPLATES) config.yaml snippets.json filters.jq +ASSETS = github.css jqt.css README.md + +TARGETS = \ + $(OUTPUT)/document.html \ + $(OUTPUT)/engine.html \ + $(OUTPUT)/index.html \ + $(OUTPUT)/metadata.html \ + $(OUTPUT)/template.html \ + +######################################################################## +# Rules +######################################################################## + +all: $(TARGETS) + cp -uv $(ASSETS) $(OUTPUT) + xmllint --noout --valid $(OUTPUT)/*.html + +snippets.pandoc: snippets.md + sed -n 's/^\([a-zA-Z_-]\+\): *[^#].*/\1: >\n $$\1$$/p' $< > $@ + +snippets.json: snippets.md snippets.pandoc + pandoc --from markdown --to html --template=snippets.pandoc $< | yaml2json > $@ + +$(OUTPUT): + mkdir $(OUTPUT) >/dev/null 2>&1 || true + +$(OUTPUT)/index.html: home.md index.html $(COMMON) | $(OUTPUT) + $(JQT) -DBODY_BLOCK=index.html -d $< main.html | $(HTMLMIN) > $@ + +define Page +$(OUTPUT)/$(1).html: $(1).md page.html $$(COMMON) | $$(OUTPUT) + $$(JQT) -DBODY_BLOCK=page.html -d $$< main.html | $$(HTMLMIN) > $$@ +endef + +$(eval $(call Page,engine)) +$(eval $(call Page,document)) +$(eval $(call Page,metadata)) +$(eval $(call Page,template)) + +######################################################################## +# Utilities +######################################################################## + +.PHONY: clean clobber build + +clean: + rm -f $(OUTPUT)/* snippets.json snippets.pandoc + +clobber: clean + rmdir $(OUTPUT) >/dev/null 2>&1 || true + +build: clean all + +# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..04f6b39 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ +# _jqt_ · The _jq_ template engine + +This is the documentation for _jqt_. +Visit the web site at . + + diff --git a/docs/config.yaml b/docs/config.yaml new file mode 100644 index 0000000..3eaaabc --- /dev/null +++ b/docs/config.yaml @@ -0,0 +1,35 @@ +# +# jqt docs configuration +# + +# Global parameters + +version: "0.1" +title: jqt · The jq template engine +baseurl: http://TO_BE_DEFINED/ +lang: en + +baseURL: &baseurl https://fadado.github.com/jqt/ + +author: +- email: jordinas@gmail.com + name: Joan Josep Ordinas Rosa + +menu: +- URL: ./index.html + id: home + name: Home +- URL: ./engine.html + id: engine + name: Engine +- URL: ./document.html + id: document + name: Document +- URL: ./template.html + id: template + name: Template +- URL: ./metadata.html + id: metadata + name: Metadata + +# vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=yaml diff --git a/docs/document.md b/docs/document.md new file mode 100644 index 0000000..64bba8e --- /dev/null +++ b/docs/document.md @@ -0,0 +1,13 @@ +--- +<%include "config.yaml"> +title: Content documents +updated: "2016-08-05T09:15:11Z" +--- + +<%include "macros.m">& + +MarkDown documents and snippets. + +<# +vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown +#> diff --git a/docs/engine.md b/docs/engine.md new file mode 100644 index 0000000..e0a57cb --- /dev/null +++ b/docs/engine.md @@ -0,0 +1,47 @@ +--- +<%include "config.yaml"> +title: Template engine +updated: "2016-08-05T09:15:11Z" +--- + +<%include "macros.m">& + +## <%cite jq> templates + +The <%cite jq> template language will be called <%cite jqt>. The tools used in the +implementation of <%cite jqt> are: + +* [jq](https://stedolan.github.io/jq/), a lightweight and flexible command-line JSON processor. +* [Bash](https://www.gnu.org/software/bash/), [sed](https://www.gnu.org/software/sed/) and other shell tools. +* [GNU Make](https://www.gnu.org/software/make/), the tool that builds executable programs and libraries from source code. +* [GPP](https://logological.org/gpp), a general-purpose preprocessor. +* [Pandoc](http://pandoc.org/), a universal document converter. + +Template engine components + +### Flow + + +``` + jqt +------+ +-------+ jq +Template +----------->|expand|-->|convert|-------------------------------+ + +------+ +-------+ | + | + HTML | + fragment v + MarkDown +------+ +------+ /-------->+-----+ JSON +------+ +Document +----------->|expand|-->|markup|--+ |merge|-------->|render|--> HTML + +------+ +------+ \-------->+-----+ +------+ + YAML ^ ^ + front-matter | | + | | + JSON +------+ | | + +----------->|expand|-------------------------+ | +Metadata +------+ | + +-------------------------------------------------+ + YAML +``` + +<# +vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown +#> diff --git a/docs/filters.jq b/docs/filters.jq new file mode 100644 index 0000000..2f12e64 --- /dev/null +++ b/docs/filters.jq @@ -0,0 +1,9 @@ +# Filters + +# Remove XML tags +def striptags: + # warning: algorithm too simplistic + gsub("<[^>]*>"; "") +; + +# vim:ai:sw=4:ts=4:et:syntax=jq diff --git a/docs/footer.html b/docs/footer.html new file mode 100644 index 0000000..30cd768 --- /dev/null +++ b/docs/footer.html @@ -0,0 +1,6 @@ +
+{{.snippets.footer}} +
+<# + vim:ts=2:sw=2:ai:noet:fileencoding=utf8:syntax=html +#> diff --git a/docs/github.css b/docs/github.css new file mode 100644 index 0000000..bde269e --- /dev/null +++ b/docs/github.css @@ -0,0 +1,202 @@ +*{margin:0;padding:0;} +body { + font:13.34px helvetica,arial,freesans,clean,sans-serif; + color:black; + line-height:1.4em; + background-color: #F8F8F8; + padding: 0.7em; +} +p { + margin:1em 0; + line-height:1.5em; +} +table { + font-size:inherit; + margin:1em; +} +table th{border-bottom:1px solid #bbb;padding:.2em 1em;} +table td{border-bottom:1px solid #ddd;padding:.2em 1em;} +input[type=text],input[type=password],input[type=image],textarea{font:99% helvetica,arial,freesans,sans-serif;} +select,option{padding:0 .25em;} +optgroup{margin-top:.5em;} +pre,code{font:12px Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace;} +pre { + margin:1em 0; + font-size:12px; + background-color:#eee; + border:1px solid #ddd; + padding:5px; + line-height:1.5em; + color:#444; + overflow:auto; + -webkit-box-shadow:rgba(0,0,0,0.07) 0 1px 2px inset; + -webkit-border-radius:3px; + border-radius:3px; +} +pre code { + padding:0; + font-size:12px; + background-color:#eee; + border:none; +} +code { + font-size:12px; + background-color:#f8f8ff; + color:#444; + padding:0 .2em; + border:1px solid #dedede; +} +img{border:0;max-width:100%;} +abbr{border-bottom:none;} +a{color:#4183c4;text-decoration:none;} +a:hover{text-decoration:underline;} +a code,a:link code,a:visited code{color:#4183c4;} +h2,h3{margin:1em 0;} +h1,h2,h3,h4,h5,h6{border:0;} +/*JJOR: h1{font-size:170%;border-top:4px solid #aaa;padding-top:.5em;margin-top:1.5em;}*/ +h1{font-size:170%;border-top:4px solid #aaa;padding-top:.5em;margin-top:1em;} +h1:first-child{margin-top:0;padding-top:.25em;border-top:none;} +h2{font-size:150%;margin-top:1.5em;border-top:4px solid #e0e0e0;padding-top:.5em;} +h3{margin-top:1em;} +hr{border:1px solid #ddd;} +ul{margin:1em 0 1em 2em;} +ol{margin:1em 0 1em 2em;} +ul li,ol li{margin-top:.5em;margin-bottom:.5em;} +ul ul,ul ol,ol ol,ol ul{margin-top:0;margin-bottom:0;} +blockquote{margin:1em 0;border-left:5px solid #ddd;padding-left:.6em;color:#555;} +dt{font-weight:bold;margin-left:1em;} +dd{margin-left:2em;margin-bottom:1em;} +@media screen and (min-width: 768px) { + body { + width: 748px; + margin:10px auto; + } +} + +/* github.com style (c) Vasily Polovnyov */ +pre code { + display: block; padding: 0.5em; + color: #333; + background: #f8f8ff +} + +pre .comment, +pre .template_comment, +pre .diff .header, +pre .javadoc { + color: #998; + font-style: italic +} + +pre .keyword, +pre .css .rule .keyword, +pre .winutils, +pre .javascript .title, +pre .nginx .title, +pre .subst, +pre .request, +pre .status { + color: #333; + font-weight: bold +} + +pre .number, +pre .hexcolor, +pre .ruby .constant { + color: #099; +} + +pre .string, +pre .tag .value, +pre .phpdoc, +pre .tex .formula { + color: #d14 +} + +pre .title, +pre .id, +pre .coffeescript .params, +pre .scss .preprocessor { + color: #900; + font-weight: bold +} + +pre .javascript .title, +pre .lisp .title, +pre .clojure .title, +pre .subst { + font-weight: normal +} + +pre .class .title, +pre .haskell .type, +pre .vhdl .literal, +pre .tex .command { + color: #458; + font-weight: bold +} + +pre .tag, +pre .tag .title, +pre .rules .property, +pre .django .tag .keyword { + color: #000080; + font-weight: normal +} + +pre .attribute, +pre .variable, +pre .lisp .body { + color: #008080 +} + +pre .regexp { + color: #009926 +} + +pre .class { + color: #458; + font-weight: bold +} + +pre .symbol, +pre .ruby .symbol .string, +pre .lisp .keyword, +pre .tex .special, +pre .prompt { + color: #990073 +} + +pre .built_in, +pre .lisp .title, +pre .clojure .built_in { + color: #0086b3 +} + +pre .preprocessor, +pre .pi, +pre .doctype, +pre .shebang, +pre .cdata { + color: #999; + font-weight: bold +} + +pre .deletion { + background: #fdd +} + +pre .addition { + background: #dfd +} + +pre .diff .change { + background: #0086b3 +} + +pre .chunk { + color: #aaa +} +/* + vim:ts=4:sw=4:ai:noet:fileencoding=utf-8:syntax=css + */ diff --git a/docs/head.html b/docs/head.html new file mode 100644 index 0000000..c20f412 --- /dev/null +++ b/docs/head.html @@ -0,0 +1,18 @@ +<# + Meta elements +#> + + + + + + +<# + CSS styles +#> + + +{{.highlight}} +<# + vim:ts=2:sw=2:ai:noet:fileencoding=utf8:syntax=html +#> diff --git a/docs/home.md b/docs/home.md new file mode 100644 index 0000000..ed8a59f --- /dev/null +++ b/docs/home.md @@ -0,0 +1,86 @@ +--- +<%include "config.yaml"> +title: Welcome +updated: "2016-08-05T09:15:11Z" +--- + +<%include "macros.m">& + +[JQ]: +[REPO]: + +Could be [<%cite jq>][JQ] the basis for a template engine? +Let's explore… + +## <%cite 'jq'> + +<%cite jq> have nice features as string interpolation and implicit backtracking. +Mixed with the help of some syntactic sugar a powerful template engine appear. +Imagine the following simple strings, in the middle of a <%cite jq> program, +with generators separated with the comma operator: + +### Simple expansion + +```html +..., "\(.title)", ... +``` + +### Conditional expansion + +```html +..., "", ... +``` + +### Repeated expansion + +```html +..., "", ... +``` + +In these examples the strings expand, vanish, or multiply without any +explicit `if` or `for`! + +## <%cite jqt> + +To write <%cite jq> scripts using strings with interpolations is not the idea we have +for a template language. We need some syntactic sugar, and this is provided to you by +<%cite jqt>. You write templates in a very fashionable style, the templates +are translated into a <%cite jq> script and then <%cite jq> is feed with the created +script and some metadata and content in JSON or YAML format… and the magic is done! + +And, how do the _syntactic sugar_ looks like? Do you think the following +example looks like a template? + +```html + + + {# block comments #} + {{.title | gsub("<[^>]*>"; "")}} + + {# implicit loop if several authors #} + {% .author | sort[] %} + {# include files in preprocessing stage #} + <%include "head.html"> + + +

{{.title}}

+

{{.subtitle//empty}}

{# line vanishes if subtitle not defined #} +
    + {% range(.n) %} {# loop from 0 to .n-1 #} +
  • {{.}}
  • + {% end %} +
+ + +``` + +## <%cite 'jqt'> status + +_jqt_ is developed under the _Fedora_ Linux distribution, and a lot of +portability issues are expected at this stage of development. Please, use the +project [GitHub repository][REPO] features if you want to collaborate or send +any kind of questions. + +<# +vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown +#> diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..d4fe472 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,11 @@ +<# + Index page +#> + +
+ {{.body}} +
+ +<# + vim:ts=2:sw=2:ai:noet:fileencoding=utf8:syntax=html +#> diff --git a/docs/jqt.css b/docs/jqt.css new file mode 100644 index 0000000..e44eb67 --- /dev/null +++ b/docs/jqt.css @@ -0,0 +1,68 @@ +@import url(github.css); + +/* + * jqt added styles + */ +#MENU { + margin: 0; + padding: 0; + text-transform: lowercase; + font-variant: small-caps; + font-size: 120%; +} +#MENU li { + display: inline; + margin-left: 1em; + font-weight: bold; +} +#MENU li.logo { + display: inline; + margin-right: 0; + margin-left:0; + font-weight: normal; + font-size: 180%; +} +#MENU li.logo a { + text-decoration: none; + background-color: inherit; +} +#MENU a { + padding: 2px; + outline: none; +} +#MENU a:hover { + padding: 2px; + background-color: gainsboro; +} +#MENU a.current { + padding: 2px; + background-color: gainsboro; +} +#TOC { + font-family: sans-serif; + font-size: 90%; + width: 20em; + margin: 2em auto 2em auto; + padding: 0 2em; + border: 3px solid grey; + text-align: center; +} +#TOC p { + font-weight: bold; + border-bottom: 1px solid black; +} +#TOC ul { + list-style-type: square; + text-align: left; +} +#TOC li { + margin: 0; +} +#FOOTER div.github { + font-family: sans-serif; + color: #4183c4; + text-align: center; +} +/* + vim:ts=4:sw=4:ai:noet:fileencoding=utf-8:syntax=css + */ diff --git a/docs/main.html b/docs/main.html new file mode 100644 index 0000000..2d60500 --- /dev/null +++ b/docs/main.html @@ -0,0 +1,44 @@ +<# + Main template +#> + + + + {% .id=="home"//empty | $M %}{{.snippets.title | striptags}} + {% .id!="home"//empty | $M %}{{.front.title}} – {{.snippets.title | striptags}} + <%include "head.html"> + + + + + + + {% .id=="home"//empty | $M %}

{{.snippets.title | ascii_downcase}}

+ {% .id!="home"//empty | $M %}

{{.front.title}} – {{.snippets.title | ascii_downcase}}

+ +<%ifdef BODY_BLOCK> + <%inceval <%BODY_BLOCK>> +<%else> + {{.body}} +<%endif> + + + + +<# + vim:ts=2:sw=2:ai:noet:fileencoding=utf8:syntax=html +#> diff --git a/docs/metadata.md b/docs/metadata.md new file mode 100644 index 0000000..fbbc295 --- /dev/null +++ b/docs/metadata.md @@ -0,0 +1,13 @@ +--- +<%include "config.yaml"> +title: Data model +updated: "2016-08-05T09:15:11Z" +--- + +<%include "macros.m">& + +Metadata in YAML and JSON formats + +<# +vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown +#> diff --git a/docs/page.html b/docs/page.html new file mode 100644 index 0000000..6f3b5d2 --- /dev/null +++ b/docs/page.html @@ -0,0 +1,16 @@ +<# + General page +#> + +
+

{{.snippets."toc-title"}}

+ {{.toc}} +
+ +
+ {{.body}} +
+ +<# + vim:ts=2:sw=2:ai:noet:fileencoding=utf8:syntax=html +#> diff --git a/docs/snippets.md b/docs/snippets.md new file mode 100644 index 0000000..f3381a5 --- /dev/null +++ b/docs/snippets.md @@ -0,0 +1,14 @@ +--- +title: _jqt_ · The _jq_ template engine + +footer: | + * * * + This website is made with [_jqt_](https://fadado.github.io/jqt/).\ + _jqt_ is licensed under the MIT license (code) and the + [CC-BY-3.0](https://creativecommons.org/licenses/by/3.0/) license (docs). + +toc-title: Table of contents + +# vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=markdown +--- +<# empty body #> diff --git a/docs/template.md b/docs/template.md new file mode 100644 index 0000000..399ccf9 --- /dev/null +++ b/docs/template.md @@ -0,0 +1,30 @@ +--- +<%include "config.yaml"> +title: Templates syntax +updated: "2016-08-05T09:15:11Z" +--- + +<%include "macros.m">& + +### Features + +* Each line of text in the template is a generator. +* Interpolation of expressions using the `{{...}}` syntactic sugar. +* Statements with <%cite jq> code inside `{%...%}`. +* One line statements begin with optional space and `{%...%}`. The rest of the + line is in the nested block. +* Multiline blocks begin with optional space and `{%...%}`. +* Multiline blocks finish with optional space and `{% end %}`. +* Raw blocks are enclode between `{% raw %}` and `{%%}` marks. +* The input metadata provided to <%cite jq> is available in the dot (`.`) and the global variable `M$`. + +### Limitations + +You must be careful writing templates. + +* Multiline block start cannot have any suffix text after `{%...%}`. +* The error messages are wrong referencing the lines where the problems happens. + +<# +vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown +#> diff --git a/make.d/config.make b/make.d/config.make new file mode 100644 index 0000000..8dc3e4c --- /dev/null +++ b/make.d/config.make @@ -0,0 +1,65 @@ +######################################################################## +# Prerequisites +######################################################################## + +# We are using some of the newest GNU Make features... so require GNU +# Make version >= 3.82 +version_test := $(filter 3.82,$(firstword $(sort $(MAKE_VERSION) 3.82))) +ifndef version_test +$(error GNU Make version $(MAKE_VERSION); version >= 3.82 is needed) +endif + +# Paranoia +ifeq (0,$(shell id --user)) +ifeq (,$(filter install uninstall,$(MAKECMDGOALS))) +$(error Root only can make "(un)install" targets) +endif +SUDO := +else +SUDO := sudo +endif + +######################################################################## +# Configuration +######################################################################## + +# Disable builtins. +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --no-builtin-variables + +# Warn when an undefined variable is referenced. +MAKEFLAGS += --warn-undefined-variables + +# Make will not print the recipe used to remake files. +.SILENT: + +# Eliminate use of the built-in implicit rules. Also clear out the +# default list of suffixes for suffix rules. +.SUFFIXES: + +# Sets the default goal to be used if no targets were specified on the +# command line. +.DEFAULT_GOAL := all + +# When it is time to consider phony targets, make will run its recipe +# unconditionally, regardless of whether a file with that name exists or +# what its last-modification time is. +.PHONY: all + +# When a target is built all lines of the recipe will be given to a +# single invocation of the shell. +# !!!Does not work in make <= 3.82 event it is documented!!! +#.ONESHELL: + +# Default shell: if we require GNU Make, why not require Bash? +SHELL := /bin/bash + +# The argument(s) passed to the shell are taken from the variable +# .SHELLFLAGS. +.SHELLFLAGS := -o errexit -o pipefail -o nounset -c + +# Make will delete the target of a rule if it has changed and its recipe +# exits with a nonzero exit status. +.DELETE_ON_ERROR: + +# vim:ai:sw=8:ts=8:noet:syntax=make diff --git a/make.d/debug.make b/make.d/debug.make new file mode 100644 index 0000000..7fea9e0 --- /dev/null +++ b/make.d/debug.make @@ -0,0 +1,30 @@ +######################################################################## +# Tools +######################################################################## + +# +# Check required tools +# + +ifneq (file,$(shell type -t gpp)) +$(error Run 'make setup' to install gpp using dnf) +endif + +ifneq (file,$(shell type -t jq)) +$(error Run 'make setup' to install jq using dnf) +endif + +ifneq (file,$(shell type -t pandoc)) +$(error Run 'make setup' to install pandoc using dnf) +endif + +# +# Show variable value. Usage: make ?VARNAME +# + +?%: .force + echo -E '$($*)' + +.force: # simulate phony target + +# vim:ai:sw=8:ts=8:noet:syntax=make diff --git a/make.d/setup.make b/make.d/setup.make new file mode 100644 index 0000000..6051c5e --- /dev/null +++ b/make.d/setup.make @@ -0,0 +1,15 @@ +######################################################################## +# Setup +######################################################################## + +# +# Install dependencies +# + +# Warning: only `dnf`! Use this rule as template to your own script. +setup: + @rpm -q --quiet general-purpose-preprocessor || sudo dnf -y install general-purpose-preprocessor + @rpm -q --quiet jq || sudo dnf -y install jq + @rpm -q --quiet pandoc || sudo dnf -y install pandoc + +# vim:ai:sw=8:ts=8:noet:syntax=make diff --git a/share/analytics.m b/share/analytics.m new file mode 100644 index 0000000..af62a0c --- /dev/null +++ b/share/analytics.m @@ -0,0 +1,19 @@ +<# + # $1: analytics UA + #> + +<# + # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=html + #> diff --git a/share/libjqt.jq b/share/libjqt.jq new file mode 100644 index 0000000..c5b5412 --- /dev/null +++ b/share/libjqt.jq @@ -0,0 +1,17 @@ +######################################################################## +# JQT library +######################################################################## + +# Produces an integer (ordinal) that is the internal representation of the +# first character in `s` +def ord(s): + s | explode[0] +; + +# Produces a string of length 1 consisting of the character whose internal +# representation is `n` +def chr(n): + [n] | implode +; + +# vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/share/libjqt.m b/share/libjqt.m new file mode 100644 index 0000000..d700f28 --- /dev/null +++ b/share/libjqt.m @@ -0,0 +1,87 @@ +<# + # libjqt GPP macros + #> +<# + # Redefine, for clarity, again the GPP mode for jqt + #> +<%mode user "<%" ">" "\B" "\B" "\W>" "<" ">" "$" "">& +<%mode meta "<%" ">" "\B" "\B" "\W>" "<" ">">& +<%mode string ccc "&\n" "">& +<%mode string ccc "<#" "#>\n">& +<%mode string iqi "'" "'" "">& +<%mode string iQi "\"" "\"" "">& +<%mode string sss "" "">& +<%mode string sss "\n```" "\n```" "">& +<%mode string sss "\n~~~" "\n~~~" "">& +<%mode string sss "\n---\n" "\n---\n" "">& +<%mode string sss "{{" "}}" "">& +<%mode string sss "{%" "%}" "">& +<%mode string sss "{#" "#}" "">& +<# + # Quote character, only for this file + #> +<%mode quote "\\">& +<# + # <%partial name arg...> + # Like include but passing (up to 8) parameters to the included file. + # Assume 'm' filename extension. + #> +<%define partial + <%defeval _partial + <\%defeval _partial + <\%include "$1.m"> + > + ><%_partial><%_partial "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"><%undef _partial> +>& +<# + # <%inceval name arg...> + # Like include but passing (up to 8) parameters to the included file. + #> +<%define inceval + <%defeval _inceval + <\%defeval _inceval + <\%include "$1"> + > + ><%_inceval><%_inceval "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"><%undef _inceval> +>& +<# + # <%shortcode name>... <%name arg...> + # Define name as a macro with contents of name.m as a body. + # Assume 'm' filename extension. + # Equivalent to: <%defeval name <%include name.m>> + #> +<%define shortcode + <%defeval _shortcode + <\%defeval $1 + <\%include $1.m> + > + ><%_shortcode><%undef _shortcode> +>& +<# + # <%call scan text> + # Evaluate text with macro calls. + #> +<%define scan + <%defeval _scan $1><%_scan><%undef _scan> +>& +<# + # <%call name arg...> + # Call a macro by name. + #> +<%define call + <%defeval _call + <\%$1 "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"> + ><%_call><%undef _call> +>& +<# + # <%append name text> + # Equivalent to: <%defeval name <%name>text.> + #> +<%define append + <%defeval _append + <\%defeval $1 <%call $1>$2> + ><%_append><%undef _append> +>& +<# + # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=perl + #> diff --git a/share/macros.m b/share/macros.m new file mode 100644 index 0000000..01e5fd1 --- /dev/null +++ b/share/macros.m @@ -0,0 +1,35 @@ +<# + # Example user defined macros + #> +<# + # <%sc word> + # <%sc 'text with spaces'> + #> +<%define sc $1>& +<# + # <%cite word> + # <%cite 'text with spaces'> + #> +<%define cite $1>& +<# + # <%vimeo 38514156 560 315> + #> +<%define vimeo + +>& +<# + # <%slideshare FOuwiWHTdrs1OJ 595 485> + #> +<%define slideshare + +>& +<# + # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=perl + #> diff --git a/share/xhtml-lat1.m b/share/xhtml-lat1.m new file mode 100644 index 0000000..ad481ae --- /dev/null +++ b/share/xhtml-lat1.m @@ -0,0 +1,103 @@ +<%mode comment "#" "\n">& +# Portions (C) International Organization for Standardization 1986 +# Permission to copy in any form is granted for use with +# conforming SGML systems and applications as defined in +# ISO 8879, provided this notice is included in all copies. +# +<%define nbsp \u00A0># no-break space = non-breaking space, U+00A0 ISOnum +<%define iexcl \u00A1># inverted exclamation mark, U+00A1 ISOnum +<%define cent \u00A2># cent sign, U+00A2 ISOnum +<%define pound \u00A3># pound sign, U+00A3 ISOnum +<%define curren \u00A4># currency sign, U+00A4 ISOnum +<%define yen \u00A5># yen sign = yuan sign, U+00A5 ISOnum +<%define brvbar \u00A6># broken bar = broken vertical bar, U+00A6 ISOnum +<%define sect \u00A7># section sign, U+00A7 ISOnum +<%define uml \u00A8># diaeresis = spacing diaeresis, U+00A8 ISOdia +<%define copy \u00A9># copyright sign, U+00A9 ISOnum +<%define ordf \u00AA># feminine ordinal indicator, U+00AA ISOnum +<%define laquo \u00AB># left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum +<%define not \u00AC># not sign = angled dash, U+00AC ISOnum +<%define shy \u00AD># soft hyphen = discretionary hyphen, U+00AD ISOnum +<%define reg \u00AE># registered sign = registered trade mark sign, U+00AE ISOnum +<%define macr \u00AF># macron = spacing macron = overline = APL overbar, U+00AF ISOdia +<%define deg \u00B0># degree sign, U+00B0 ISOnum +<%define plusmn \u00B1># plus-minus sign = plus-or-minus sign, U+00B1 ISOnum +<%define sup2 \u00B2># superscript two = superscript digit two = squared, U+00B2 ISOnum +<%define sup3 \u00B3># superscript three = superscript digit three = cubed, U+00B3 ISOnum +<%define acute \u00B4># acute accent = spacing acute, U+00B4 ISOdia +<%define micro \u00B5># micro sign, U+00B5 ISOnum +<%define para \u00B6># pilcrow sign = paragraph sign, U+00B6 ISOnum +<%define middot \u00B7># middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum +<%define cedil \u00B8># cedilla = spacing cedilla, U+00B8 ISOdia +<%define sup1 \u00B9># superscript one = superscript digit one, U+00B9 ISOnum +<%define ordm \u00BA># masculine ordinal indicator, U+00BA ISOnum +<%define raquo \u00BB># right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum +<%define frac14 \u00BC># vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum +<%define frac12 \u00BD># vulgar fraction one half = fraction one half, U+00BD ISOnum +<%define frac34 \u00BE># vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum +<%define iquest \u00BF># inverted question mark = turned question mark, U+00BF ISOnum +<%define Agrave \u00C0># latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1 +<%define Aacute \u00C1># latin capital letter A with acute, U+00C1 ISOlat1 +<%define Acirc \u00C2># latin capital letter A with circumflex, U+00C2 ISOlat1 +<%define Atilde \u00C3># latin capital letter A with tilde, U+00C3 ISOlat1 +<%define Auml \u00C4># latin capital letter A with diaeresis, U+00C4 ISOlat1 +<%define Aring \u00C5># latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 +<%define AElig \u00C6># latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 +<%define Ccedil \u00C7># latin capital letter C with cedilla, U+00C7 ISOlat1 +<%define Egrave \u00C8># latin capital letter E with grave, U+00C8 ISOlat1 +<%define Eacute \u00C9># latin capital letter E with acute, U+00C9 ISOlat1 +<%define Ecirc \u00CA># latin capital letter E with circumflex, U+00CA ISOlat1 +<%define Euml \u00CB># latin capital letter E with diaeresis, U+00CB ISOlat1 +<%define Igrave \u00CC># latin capital letter I with grave, U+00CC ISOlat1 +<%define Iacute \u00CD># latin capital letter I with acute, U+00CD ISOlat1 +<%define Icirc \u00CE># latin capital letter I with circumflex, U+00CE ISOlat1 +<%define Iuml \u00CF># latin capital letter I with diaeresis, U+00CF ISOlat1 +<%define ETH \u00D0># latin capital letter ETH, U+00D0 ISOlat1 +<%define Ntilde \u00D1># latin capital letter N with tilde, U+00D1 ISOlat1 +<%define Ograve \u00D2># latin capital letter O with grave, U+00D2 ISOlat1 +<%define Oacute \u00D3># latin capital letter O with acute, U+00D3 ISOlat1 +<%define Ocirc \u00D4># latin capital letter O with circumflex, U+00D4 ISOlat1 +<%define Otilde \u00D5># latin capital letter O with tilde, U+00D5 ISOlat1 +<%define Ouml \u00D6># latin capital letter O with diaeresis, U+00D6 ISOlat1 +<%define times \u00D7># multiplication sign, U+00D7 ISOnum +<%define Oslash \u00D8># latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1 +<%define Ugrave \u00D9># latin capital letter U with grave, U+00D9 ISOlat1 +<%define Uacute \u00DA># latin capital letter U with acute, U+00DA ISOlat1 +<%define Ucirc \u00DB># latin capital letter U with circumflex, U+00DB ISOlat1 +<%define Uuml \u00DC># latin capital letter U with diaeresis, U+00DC ISOlat1 +<%define Yacute \u00DD># latin capital letter Y with acute, U+00DD ISOlat1 +<%define THORN \u00DE># latin capital letter THORN, U+00DE ISOlat1 +<%define szlig \u00DF># latin small letter sharp s = ess-zed, U+00DF ISOlat1 +<%define agrave \u00E0># latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 +<%define aacute \u00E1># latin small letter a with acute, U+00E1 ISOlat1 +<%define acirc \u00E2># latin small letter a with circumflex, U+00E2 ISOlat1 +<%define atilde \u00E3># latin small letter a with tilde, U+00E3 ISOlat1 +<%define auml \u00E4># latin small letter a with diaeresis, U+00E4 ISOlat1 +<%define aring \u00E5># latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 +<%define aelig \u00E6># latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 +<%define ccedil \u00E7># latin small letter c with cedilla, U+00E7 ISOlat1 +<%define egrave \u00E8># latin small letter e with grave, U+00E8 ISOlat1 +<%define eacute \u00E9># latin small letter e with acute, U+00E9 ISOlat1 +<%define ecirc \u00EA># latin small letter e with circumflex, U+00EA ISOlat1 +<%define euml \u00EB># latin small letter e with diaeresis, U+00EB ISOlat1 +<%define igrave \u00EC># latin small letter i with grave, U+00EC ISOlat1 +<%define iacute \u00ED># latin small letter i with acute, U+00ED ISOlat1 +<%define icirc \u00EE># latin small letter i with circumflex, U+00EE ISOlat1 +<%define iuml \u00EF># latin small letter i with diaeresis, U+00EF ISOlat1 +<%define eth \u00F0># latin small letter eth, U+00F0 ISOlat1 +<%define ntilde \u00F1># latin small letter n with tilde, U+00F1 ISOlat1 +<%define ograve \u00F2># latin small letter o with grave, U+00F2 ISOlat1 +<%define oacute \u00F3># latin small letter o with acute, U+00F3 ISOlat1 +<%define ocirc \u00F4># latin small letter o with circumflex, U+00F4 ISOlat1 +<%define otilde \u00F5># latin small letter o with tilde, U+00F5 ISOlat1 +<%define ouml \u00F6># latin small letter o with diaeresis, U+00F6 ISOlat1 +<%define divide \u00F7># division sign, U+00F7 ISOnum +<%define oslash \u00F8># latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 +<%define ugrave \u00F9># latin small letter u with grave, U+00F9 ISOlat1 +<%define uacute \u00FA># latin small letter u with acute, U+00FA ISOlat1 +<%define ucirc \u00FB># latin small letter u with circumflex, U+00FB ISOlat1 +<%define uuml \u00FC># latin small letter u with diaeresis, U+00FC ISOlat1 +<%define yacute \u00FD># latin small letter y with acute, U+00FD ISOlat1 +<%define thorn \u00FE># latin small letter thorn, U+00FE ISOlat1 +<%define yuml \u00FF># latin small letter y with diaeresis, U+00FF ISOlat1 +# vim:syntax=perl diff --git a/share/xhtml-special.m b/share/xhtml-special.m new file mode 100644 index 0000000..c07f0bf --- /dev/null +++ b/share/xhtml-special.m @@ -0,0 +1,57 @@ +<%mode comment "#" "\n">& +# Special characters for XHTML +# +# Portions (C) International Organization for Standardization 1986: +# Permission to copy in any form is granted for use with +# conforming SGML systems and applications as defined in +# ISO 8879, provided this notice is included in all copies. +# +# Relevant ISO entity set is given unless names are newly introduced. +# New names (i.e., not in ISO 8879 list) do not clash with any +# existing ISO 8879 entity names. ISO 10646 character numbers +# are given for each character, in hex. values are decimal +# conversions of the ISO 10646 values and refer to the document +# character set. Names are Unicode names. +# +# C0 Controls and Basic Latin +<%define quot \u0022># quotation mark, U+0022 ISOnum +<%define amp \u0026># ampersand, U+0026 ISOnum +<%define lt \u003C># less-than sign, U+003C ISOnum +<%define gt \u003E># greater-than sign, U+003E ISOnum +<%define apos \u0027># apostrophe = APL quote, U+0027 ISOnum +# Latin Extended-A +<%define OElig \u0152># latin capital ligature OE, U+0152 ISOlat2 +<%define oelig \u0153># latin small ligature oe, U+0153 ISOlat2 +# ligature is a misnomer, this is a separate character in some languages +<%define Scaron \u0160># latin capital letter S with caron, U+0160 ISOlat2 +<%define scaron \u0161># latin small letter s with caron, U+0161 ISOlat2 +<%define Yuml \u0178># latin capital letter Y with diaeresis, U+0178 ISOlat2 +# Spacing Modifier Letters +<%define circ \u02C6># modifier letter circumflex accent, U+02C6 ISOpub +<%define tilde \u02DC># small tilde, U+02DC ISOdia +# General Punctuation +<%define ensp \u2002># en space, U+2002 ISOpub +<%define emsp \u2003># em space, U+2003 ISOpub +<%define thinsp \u2009># thin space, U+2009 ISOpub +<%define zwnj \u200C># zero width non-joiner, U+200C NEW RFC 2070 +<%define zwj \u200D># zero width joiner, U+200D NEW RFC 2070 +<%define lrm \u200E># left-to-right mark, U+200E NEW RFC 2070 +<%define rlm \u200F># right-to-left mark, U+200F NEW RFC 2070 +<%define ndash \u2013># en dash, U+2013 ISOpub +<%define mdash \u2014># em dash, U+2014 ISOpub +<%define lsquo \u2018># left single quotation mark, U+2018 ISOnum +<%define rsquo \u2019># right single quotation mark, U+2019 ISOnum +<%define sbquo \u201A># single low-9 quotation mark, U+201A NEW +<%define ldquo \u201C># left double quotation mark, U+201C ISOnum +<%define rdquo \u201D># right double quotation mark, U+201D ISOnum +<%define bdquo \u201E># double low-9 quotation mark, U+201E NEW +<%define dagger \u2020># dagger, U+2020 ISOpub +<%define Dagger \u2021># double dagger, U+2021 ISOpub +<%define permil \u2030># per mille sign, U+2030 ISOtech +<%define lsaquo \u2039># single left-pointing angle quotation mark, U+2039 ISO proposed +# lsaquo is proposed but not yet ISO standardized +<%define rsaquo \u203A># single right-pointing angle quotation mark, U+203A ISO proposed +# rsaquo is proposed but not yet ISO standardized +# Currency Symbols +<%define euro \u20AC># euro sign, U+20AC NEW +# vim:syntax=perl diff --git a/share/xhtml-symbol.m b/share/xhtml-symbol.m new file mode 100644 index 0000000..ace3a83 --- /dev/null +++ b/share/xhtml-symbol.m @@ -0,0 +1,161 @@ +<%mode comment "#" "\n">& +# Mathematical, Greek and Symbolic characters for XHTML +# +# Portions (C) International Organization for Standardization 1986: +# Permission to copy in any form is granted for use with +# conforming SGML systems and applications as defined in +# ISO 8879, provided this notice is included in all copies. +# +# Relevant ISO entity set is given unless names are newly introduced. +# New names (i.e., not in ISO 8879 list) do not clash with any +# existing ISO 8879 entity names. ISO 10646 character numbers +# are given for each character, in hex. values are decimal +# conversions of the ISO 10646 values and refer to the document +# character set. Names are Unicode names. +# +# Latin Extended-B +<%define fnof \u0192># latin small letter f with hook = function = florin, U+0192 ISOtech +# Greek +<%define Alpha \u0391># greek capital letter alpha, U+0391 +<%define Beta \u0392># greek capital letter beta, U+0392 +<%define Gamma \u0393># greek capital letter gamma, U+0393 ISOgrk3 +<%define Delta \u0394># greek capital letter delta, U+0394 ISOgrk3 +<%define Epsilon \u0395># greek capital letter epsilon, U+0395 +<%define Zeta \u0396># greek capital letter zeta, U+0396 +<%define Eta \u0397># greek capital letter eta, U+0397 +<%define Theta \u0398># greek capital letter theta, U+0398 ISOgrk3 +<%define Iota \u0399># greek capital letter iota, U+0399 +<%define Kappa \u039A># greek capital letter kappa, U+039A +<%define Lambda \u039B># greek capital letter lamda, U+039B ISOgrk3 +<%define Mu \u039C># greek capital letter mu, U+039C +<%define Nu \u039D># greek capital letter nu, U+039D +<%define Xi \u039E># greek capital letter xi, U+039E ISOgrk3 +<%define Omicron \u039F># greek capital letter omicron, U+039F +<%define Pi \u03A0># greek capital letter pi, U+03A0 ISOgrk3 +<%define Rho \u03A1># greek capital letter rho, U+03A1 +# there is no Sigmaf, and no U+03A2 character either +<%define Sigma \u03A3># greek capital letter sigma, U+03A3 ISOgrk3 +<%define Tau \u03A4># greek capital letter tau, U+03A4 +<%define Upsilon \u03A5># greek capital letter upsilon, U+03A5 ISOgrk3 +<%define Phi \u03A6># greek capital letter phi, U+03A6 ISOgrk3 +<%define Chi \u03A7># greek capital letter chi, U+03A7 +<%define Psi \u03A8># greek capital letter psi, U+03A8 ISOgrk3 +<%define Omega \u03A9># greek capital letter omega, U+03A9 ISOgrk3 +<%define alpha \u03B1># greek small letter alpha, U+03B1 ISOgrk3 +<%define beta \u03B2># greek small letter beta, U+03B2 ISOgrk3 +<%define gamma \u03B3># greek small letter gamma, U+03B3 ISOgrk3 +<%define delta \u03B4># greek small letter delta, U+03B4 ISOgrk3 +<%define epsilon \u03B5># greek small letter epsilon, U+03B5 ISOgrk3 +<%define zeta \u03B6># greek small letter zeta, U+03B6 ISOgrk3 +<%define eta \u03B7># greek small letter eta, U+03B7 ISOgrk3 +<%define theta \u03B8># greek small letter theta, U+03B8 ISOgrk3 +<%define iota \u03B9># greek small letter iota, U+03B9 ISOgrk3 +<%define kappa \u03BA># greek small letter kappa, U+03BA ISOgrk3 +<%define lambda \u03BB># greek small letter lamda, U+03BB ISOgrk3 +<%define mu \u03BC># greek small letter mu, U+03BC ISOgrk3 +<%define nu \u03BD># greek small letter nu, U+03BD ISOgrk3 +<%define xi \u03BE># greek small letter xi, U+03BE ISOgrk3 +<%define omicron \u03BF># greek small letter omicron, U+03BF NEW +<%define pi \u03C0># greek small letter pi, U+03C0 ISOgrk3 +<%define rho \u03C1># greek small letter rho, U+03C1 ISOgrk3 +<%define sigmaf \u03C2># greek small letter final sigma, U+03C2 ISOgrk3 +<%define sigma \u03C3># greek small letter sigma, U+03C3 ISOgrk3 +<%define tau \u03C4># greek small letter tau, U+03C4 ISOgrk3 +<%define upsilon \u03C5># greek small letter upsilon, U+03C5 ISOgrk3 +<%define phi \u03C6># greek small letter phi, U+03C6 ISOgrk3 +<%define chi \u03C7># greek small letter chi, U+03C7 ISOgrk3 +<%define psi \u03C8># greek small letter psi, U+03C8 ISOgrk3 +<%define omega \u03C9># greek small letter omega, U+03C9 ISOgrk3 +<%define thetasym \u03D1># greek theta symbol, U+03D1 NEW +<%define upsih \u03D2># greek upsilon with hook symbol, U+03D2 NEW +<%define piv \u03D6># greek pi symbol, U+03D6 ISOgrk3 +# General Punctuation +<%define bull \u2022># bullet = black small circle, U+2022 ISOpub +# bullet is NOT the same as bullet operator, U+2219 +<%define hellip \u2026># horizontal ellipsis = three dot leader, U+2026 ISOpub +<%define prime \u2032># prime = minutes = feet, U+2032 ISOtech +<%define Prime \u2033># double prime = seconds = inches, U+2033 ISOtech +<%define oline \u203E># overline = spacing overscore, U+203E NEW +<%define frasl \u2044># fraction slash, U+2044 NEW +# Letterlike Symbols +<%define weierp \u2118># script capital P = power set = Weierstrass p, U+2118 ISOamso +<%define image \u2111># black-letter capital I = imaginary part, U+2111 ISOamso +<%define real \u211C># black-letter capital R = real part symbol, U+211C ISOamso +<%define trade \u2122># trade mark sign, U+2122 ISOnum +<%define alefsym \u2135># alef symbol = first transfinite cardinal, U+2135 NEW +# alef symbol is NOT the same as hebrew letter alef, U+05D0 although the same glyph could be used to depict both characters +# Arrows +<%define larr \u2190># leftwards arrow, U+2190 ISOnum +<%define uarr \u2191># upwards arrow, U+2191 ISOnum +<%define rarr \u2192># rightwards arrow, U+2192 ISOnum +<%define darr \u2193># downwards arrow, U+2193 ISOnum +<%define harr \u2194># left right arrow, U+2194 ISOamsa +<%define crarr \u21B5># downwards arrow with corner leftwards = carriage return, U+21B5 NEW +<%define lArr \u21D0># leftwards double arrow, U+21D0 ISOtech +# Unicode does not say that lArr is the same as the 'is implied by' arrow but also does not have any other character for that function. So lArr can be used for 'is implied by' as ISOtech suggests +<%define uArr \u21D1># upwards double arrow, U+21D1 ISOamsa +<%define rArr \u21D2># rightwards double arrow, U+21D2 ISOtech +# Unicode does not say this is the 'implies' character but does not have another character with this function so rArr can be used for 'implies' as ISOtech suggests +<%define dArr \u21D3># downwards double arrow, U+21D3 ISOamsa +<%define hArr \u21D4># left right double arrow, U+21D4 ISOamsa +# Mathematical Operators +<%define forall \u2200># for all, U+2200 ISOtech +<%define part \u2202># partial differential, U+2202 ISOtech +<%define exist \u2203># there exists, U+2203 ISOtech +<%define empty \u2205># empty set = null set, U+2205 ISOamso +<%define nabla \u2207># nabla = backward difference, U+2207 ISOtech +<%define isin \u2208># element of, U+2208 ISOtech +<%define notin \u2209># not an element of, U+2209 ISOtech +<%define ni \u220B># contains as member, U+220B ISOtech +<%define prod \u220F># n-ary product = product sign, U+220F ISOamsb +# prod is NOT the same character as U+03A0 'greek capital letter pi' though the same glyph might be used for both +<%define sum \u2211># n-ary summation, U+2211 ISOamsb +# sum is NOT the same character as U+03A3 'greek capital letter sigma' though the same glyph might be used for both +<%define minus \u2212># minus sign, U+2212 ISOtech +<%define lowast \u2217># asterisk operator, U+2217 ISOtech +<%define radic \u221A># square root = radical sign, U+221A ISOtech +<%define prop \u221D># proportional to, U+221D ISOtech +<%define infin \u221E># infinity, U+221E ISOtech +<%define ang \u2220># angle, U+2220 ISOamso +<%define and \u2227># logical and = wedge, U+2227 ISOtech +<%define or \u2228># logical or = vee, U+2228 ISOtech +<%define cap \u2229># intersection = cap, U+2229 ISOtech +<%define cup \u222A># union = cup, U+222A ISOtech +<%define int \u222B># integral, U+222B ISOtech +<%define there4 \u2234># therefore, U+2234 ISOtech +<%define sim \u223C># tilde operator = varies with = similar to, U+223C ISOtech +# tilde operator is NOT the same character as the tilde, U+007E, although the same glyph might be used to represent both +<%define cong \u2245># approximately equal to, U+2245 ISOtech +<%define asymp \u2248># almost equal to = asymptotic to, U+2248 ISOamsr +<%define ne \u2260># not equal to, U+2260 ISOtech +<%define equiv \u2261># identical to, U+2261 ISOtech +<%define le \u2264># less-than or equal to, U+2264 ISOtech +<%define ge \u2265># greater-than or equal to, U+2265 ISOtech +<%define sub \u2282># subset of, U+2282 ISOtech +<%define sup \u2283># superset of, U+2283 ISOtech +<%define nsub \u2284># not a subset of, U+2284 ISOamsn +<%define sube \u2286># subset of or equal to, U+2286 ISOtech +<%define supe \u2287># superset of or equal to, U+2287 ISOtech +<%define oplus \u2295># circled plus = direct sum, U+2295 ISOamsb +<%define otimes \u2297># circled times = vector product, U+2297 ISOamsb +<%define perp \u22A5># up tack = orthogonal to = perpendicular, U+22A5 ISOtech +<%define sdot \u22C5># dot operator, U+22C5 ISOamsb +# dot operator is NOT the same character as U+00B7 middle dot +# Miscellaneous Technical +<%define lceil \u2308># left ceiling = APL upstile, U+2308 ISOamsc +<%define rceil \u2309># right ceiling, U+2309 ISOamsc +<%define lfloor \u230A># left floor = APL downstile, U+230A ISOamsc +<%define rfloor \u230B># right floor, U+230B ISOamsc +<%define lang \u2329># left-pointing angle bracket = bra, U+2329 ISOtech +# lang is NOT the same character as U+003C 'less than sign' or U+2039 'single left-pointing angle quotation mark' +<%define rang \u232A># right-pointing angle bracket = ket, U+232A ISOtech +# rang is NOT the same character as U+003E 'greater than sign' or U+203A 'single right-pointing angle quotation mark' +# Geometric Shapes +<%define loz \u25CA># lozenge, U+25CA ISOpub +# Miscellaneous Symbols +<%define spades \u2660># black spade suit, U+2660 ISOpub +# black here seems to mean filled as opposed to hollow +<%define clubs \u2663># black club suit = shamrock, U+2663 ISOpub +<%define hearts \u2665># black heart suit = valentine, U+2665 ISOpub +<%define diams \u2666># black diamond suit, U+2666 ISOpub +# vim:syntax=perl diff --git a/share/youtube.m b/share/youtube.m new file mode 100644 index 0000000..b455e34 --- /dev/null +++ b/share/youtube.m @@ -0,0 +1,12 @@ +<# + # $1: youtube id + # $2: width + # $3: height + #> + +<# + # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=html + #> diff --git a/tests/cond-00.jqt b/tests/cond-00.jqt new file mode 100644 index 0000000..ffdd4b3 --- /dev/null +++ b/tests/cond-00.jqt @@ -0,0 +1,53 @@ +======================= +Conditional blocks +======================= + +_____ +{% .yes//empty %} + I expand! +{% end %} +{% .string//empty %} + I expand to '{{.}}' +{% end %} +{% .number//empty %} + I expand to '{{.}}' +{%end%} +{% .number//empty | $M %} + I expand preserving $M: '{{$M.number}}' +{% end %} +_____ +{% .not//empty %} + I vanish! +{% end %} +{% .nil//empty %} + I vanish! +{% end %} +_____ + +{% .yes//empty | $M %} + {% .string//empty %}I expand to '{{.}}' +{% end %} +{% .yes//empty | $M %} + {% .string//empty %} +I expand to '{{.}}' + {% end %} +{% end %} + +{% (.number > 4)//empty %} + then not +{% end %} +{% (.number < 3 | not)//empty %} + else yes +{% end %} + +{% (.number < 1)//empty %} + case 1 +{% end %} +{% (.number < 1 | not)//empty | $M %} +{% (.number < 2)//empty %} + case 2 +{% end %} +{% (.number < 2 | not)//empty %} + case else +{% end %} +{% end %} diff --git a/tests/cond-00.json b/tests/cond-00.json new file mode 100644 index 0000000..5726842 --- /dev/null +++ b/tests/cond-00.json @@ -0,0 +1,9 @@ +{ + "yes": true, + "not": false, + "nil": null, + "string": "Neque porro quisquam", + "number": 3.14159265358979323846, + "array": [7,6,5,4,3,2,1 ], + "object": { "b": true, "s": "Neque", "n": 3.14 } +} diff --git a/tests/cond-01.jqt b/tests/cond-01.jqt new file mode 100644 index 0000000..54b3515 --- /dev/null +++ b/tests/cond-01.jqt @@ -0,0 +1,2 @@ + + diff --git a/tests/cond-01.json b/tests/cond-01.json new file mode 100644 index 0000000..c3638c4 --- /dev/null +++ b/tests/cond-01.json @@ -0,0 +1 @@ +{ "updated": "2016-06-26" } diff --git a/tests/cond-02.jqt b/tests/cond-02.jqt new file mode 100644 index 0000000..fd10755 --- /dev/null +++ b/tests/cond-02.jqt @@ -0,0 +1,5 @@ +
+ {% true//empty %} + yay + {% end %} +
diff --git a/tests/cond-03.jqt b/tests/cond-03.jqt new file mode 100644 index 0000000..9c4d154 --- /dev/null +++ b/tests/cond-03.jqt @@ -0,0 +1,3 @@ +
+ {{if true then "yay" else "" end}} +
diff --git a/tests/cond-51.jqt b/tests/cond-51.jqt new file mode 100644 index 0000000..9c639be --- /dev/null +++ b/tests/cond-51.jqt @@ -0,0 +1,6 @@ +{% .published//empty | $M %} + +{% end %} +{% .updated//empty %} + +{% end %} diff --git a/tests/cond-51.json b/tests/cond-51.json new file mode 100644 index 0000000..c3638c4 --- /dev/null +++ b/tests/cond-51.json @@ -0,0 +1 @@ +{ "updated": "2016-06-26" } diff --git a/tests/expand-00.jqt b/tests/expand-00.jqt new file mode 100644 index 0000000..4262368 --- /dev/null +++ b/tests/expand-00.jqt @@ -0,0 +1 @@ +<# empty document #> diff --git a/tests/expand-01.jqt b/tests/expand-01.jqt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expand-02.jqt b/tests/expand-02.jqt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/expand-02.jqt @@ -0,0 +1 @@ + diff --git a/tests/expand-03.jqt b/tests/expand-03.jqt new file mode 100644 index 0000000..4bd7e7a --- /dev/null +++ b/tests/expand-03.jqt @@ -0,0 +1 @@ +& diff --git a/tests/expand-04.jqt b/tests/expand-04.jqt new file mode 100644 index 0000000..a8d3f0b --- /dev/null +++ b/tests/expand-04.jqt @@ -0,0 +1,6 @@ +<# multiline #> +& +<# empty #> +& +<# document #> +& diff --git a/tests/expand-05.jqt b/tests/expand-05.jqt new file mode 100644 index 0000000..e93fb7f --- /dev/null +++ b/tests/expand-05.jqt @@ -0,0 +1,5 @@ +<# predefined user macro #> +<%include "macros.m">& +<%sc Title> +<%sc 'Long Title'> +<%sc "Long Title"> diff --git a/tests/expand-06.jqt b/tests/expand-06.jqt new file mode 100644 index 0000000..9855fb6 --- /dev/null +++ b/tests/expand-06.jqt @@ -0,0 +1,36 @@ +<# examples from GPM paper #> +<%define A A$1A>& +<%define B B<%A X$1X>B>& +<%define APA P$1$1P>& +& +<%A C> +<%A ACA> +<%A <%A C>> +<%A XDX> +<%B D> +<%A P> +<%APA Y> +<%call <%A P> Y> +& +<%mode comment qqq "[" "]">& +Q[<%A C>]R +<%A [<%A X>]> +<%B [<%A X>]> +Q[<%]R[>] +Q[[<%A C>]]R +& +<# Output: + ACA + AACAA + AACAA + AXDXA + BAXDXAB + APA + PYYP + PYYP + Q<%A C>R + A<%A X>A + BAX<%A X>XAB + Q<%R> + Q[<%A C>]R +#> diff --git a/tests/expand-07.jqt b/tests/expand-07.jqt new file mode 100644 index 0000000..6edf8d2 --- /dev/null +++ b/tests/expand-07.jqt @@ -0,0 +1,8 @@ +<# XHTML entities #> +<%include "xhtml-lat1.m">& +<%include "xhtml-special.m">& +<%include "xhtml-symbol.m">& +{ + "json": "Give me 100<%euro>." +} + diff --git a/tests/expand-08.jqt b/tests/expand-08.jqt new file mode 100644 index 0000000..95c0adf --- /dev/null +++ b/tests/expand-08.jqt @@ -0,0 +1,12 @@ +<# recursion #> +<%define countdown +<%if $1>& +$1... +<%define _countdown <%countdown $1>>& +<%else>& +Done! +<%define _countdown>& +<%endif>& +<%_countdown <%eval $1-1>>& +>& +<%countdown 10>& diff --git a/tests/expand-09.jqt b/tests/expand-09.jqt new file mode 100644 index 0000000..56dbb0e --- /dev/null +++ b/tests/expand-09.jqt @@ -0,0 +1,3 @@ +<# partial user macro #> +<%defeval youtube <%include youtube.m>>& +<%youtube 7zIoLvbCCm8 420 315> diff --git a/tests/expand-10.jqt b/tests/expand-10.jqt new file mode 100644 index 0000000..c1acf00 --- /dev/null +++ b/tests/expand-10.jqt @@ -0,0 +1,3 @@ +<# partial user macro #> +<%shortcode youtube>& +<%youtube 7zIoLvbCCm8 420 315> diff --git a/tests/expand-11.jqt b/tests/expand-11.jqt new file mode 100644 index 0000000..0e46bcd --- /dev/null +++ b/tests/expand-11.jqt @@ -0,0 +1,2 @@ +<# partial user macro #> +<%partial youtube 7zIoLvbCCm8 420 315> diff --git a/tests/expand-12.jqt b/tests/expand-12.jqt new file mode 100644 index 0000000..d2e657d --- /dev/null +++ b/tests/expand-12.jqt @@ -0,0 +1,4 @@ +<# skip section: XML comment #> +<%define MACRO Lorem Ipsum>& +<%MACRO> + diff --git a/tests/expected/bloc-00.txt b/tests/expected/bloc-00.txt new file mode 100644 index 0000000..b1c6bf8 --- /dev/null +++ b/tests/expected/bloc-00.txt @@ -0,0 +1,24 @@ +======================= +Tests about blocks +======================= + +The value of pi is 3.141592653589793. +Pi squared: 6.283185307179586 +Pi squared: 6.283185307179586 +Array [7,6,5,4,3,2,1] has length 7 +Array [7,6,5,4,3,2,1] has length 7 + +Array $a has value 7 at position 0 +Array .array and array $a are equal? (true) +Values sorted as strings: ["10","12","14","2","4","6","8"] + +----- + I expand! + I expand to 'Neque porro quisquam' + I expand to '3.141592653589793' + I expand preserving $M: '3.141592653589793' +----- +----- + +I expand to 'Neque porro quisquam' +I expand to 'Neque porro quisquam' diff --git a/tests/expected/cond-00.txt b/tests/expected/cond-00.txt new file mode 100644 index 0000000..c738255 --- /dev/null +++ b/tests/expected/cond-00.txt @@ -0,0 +1,18 @@ +======================= +Conditional blocks +======================= + +_____ + I expand! + I expand to 'Neque porro quisquam' + I expand to '3.141592653589793' + I expand preserving $M: '3.141592653589793' +_____ +_____ + +I expand to 'Neque porro quisquam' +I expand to 'Neque porro quisquam' + + else yes + + case else diff --git a/tests/expected/cond-01.txt b/tests/expected/cond-01.txt new file mode 100644 index 0000000..19a5c9f --- /dev/null +++ b/tests/expected/cond-01.txt @@ -0,0 +1 @@ + diff --git a/tests/expected/cond-02.txt b/tests/expected/cond-02.txt new file mode 100644 index 0000000..49d8af9 --- /dev/null +++ b/tests/expected/cond-02.txt @@ -0,0 +1,3 @@ +
+ yay +
diff --git a/tests/expected/cond-03.txt b/tests/expected/cond-03.txt new file mode 100644 index 0000000..49d8af9 --- /dev/null +++ b/tests/expected/cond-03.txt @@ -0,0 +1,3 @@ +
+ yay +
diff --git a/tests/expected/cond-51.txt b/tests/expected/cond-51.txt new file mode 100644 index 0000000..34a3662 --- /dev/null +++ b/tests/expected/cond-51.txt @@ -0,0 +1 @@ + diff --git a/tests/expected/expand-00.jqt b/tests/expected/expand-00.jqt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expected/expand-01.jqt b/tests/expected/expand-01.jqt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expected/expand-02.jqt b/tests/expected/expand-02.jqt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/expected/expand-02.jqt @@ -0,0 +1 @@ + diff --git a/tests/expected/expand-03.jqt b/tests/expected/expand-03.jqt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expected/expand-04.jqt b/tests/expected/expand-04.jqt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expected/expand-05.jqt b/tests/expected/expand-05.jqt new file mode 100644 index 0000000..f54e030 --- /dev/null +++ b/tests/expected/expand-05.jqt @@ -0,0 +1,3 @@ +Title +Long Title +Long Title diff --git a/tests/expected/expand-06.jqt b/tests/expected/expand-06.jqt new file mode 100644 index 0000000..4a4de9b --- /dev/null +++ b/tests/expected/expand-06.jqt @@ -0,0 +1,13 @@ +ACA +AACAA +AACAA +AXDXA +BAXDXAB +APA +PYYP +PYYP +Q<%A C>R +A<%A X>A +BAX<%A X>XAB +Q<%R> +Q[<%A C>]R diff --git a/tests/expected/expand-07.jqt b/tests/expected/expand-07.jqt new file mode 100644 index 0000000..9513ba8 --- /dev/null +++ b/tests/expected/expand-07.jqt @@ -0,0 +1,4 @@ +{ + "json": "Give me 100\u20AC." +} + diff --git a/tests/expected/expand-08.jqt b/tests/expected/expand-08.jqt new file mode 100644 index 0000000..9f442e3 --- /dev/null +++ b/tests/expected/expand-08.jqt @@ -0,0 +1,11 @@ +10... +9... +8... +7... +6... +5... +4... +3... +2... +1... +Done! diff --git a/tests/expected/expand-09.jqt b/tests/expected/expand-09.jqt new file mode 100644 index 0000000..dc2eaae --- /dev/null +++ b/tests/expected/expand-09.jqt @@ -0,0 +1,5 @@ + + diff --git a/tests/expected/expand-10.jqt b/tests/expected/expand-10.jqt new file mode 100644 index 0000000..dc2eaae --- /dev/null +++ b/tests/expected/expand-10.jqt @@ -0,0 +1,5 @@ + + diff --git a/tests/expected/expand-11.jqt b/tests/expected/expand-11.jqt new file mode 100644 index 0000000..dc2eaae --- /dev/null +++ b/tests/expected/expand-11.jqt @@ -0,0 +1,5 @@ + + diff --git a/tests/expected/expand-12.jqt b/tests/expected/expand-12.jqt new file mode 100644 index 0000000..7f6a2d9 --- /dev/null +++ b/tests/expected/expand-12.jqt @@ -0,0 +1,2 @@ +Lorem Ipsum + diff --git a/tests/expected/expr-00.txt b/tests/expected/expr-00.txt new file mode 100644 index 0000000..51ea19f --- /dev/null +++ b/tests/expected/expr-00.txt @@ -0,0 +1,103 @@ +======================= +Tests about expressions +======================= + +Escape: \\ TB (\t) LF(\n) CR(\r) + +Interpolated string: true +Interpolated string: false +Interpolated string: null +Interpolated string: Neque porro quisquam +Interpolated string: 3.141592653589793 + +_______________________ +_______________________ + +Not vanished line: true +Not vanished line: Neque porro quisquam +Not vanished line: 3.141592653589793 +Not vanished line: [7,6,5,4,3,2,1] +Not vanished line: {"b":true,"s":"Neque","n":3.14} + +Nested expression: ===3.141592653589793=== +Nested expression: ===Neque porro quisquam=== +Nested expression: =-*-= + +Nested expression: ===3.141592653589793=== +Nested expression: ===Neque porro quisquam=== +Nested expression: =-*-= + +Local name: 3.141592653589793 +Local name: ["2","4","6","8","10","12","14"] +Local name: ["10","12","14","2","4","6","8"] + +Repeated line: 0 +Repeated line: 1 +Repeated line: 2 +Repeated line: 3 +Repeated line: 4 +Repeated line: 5 +Repeated line: 6 +Repeated line: b +Repeated line: n +Repeated line: s +Repeated line: 7 +Repeated line: 6 +Repeated line: 5 +Repeated line: 4 +Repeated line: 3 +Repeated line: 2 +Repeated line: 1 + +Repeated line: 3.141592653589793 +Repeated line: 6.283185307179586 +Repeated line: 9.42477796076938 +Repeated line: 12.566370614359172 + +Repeated line: 1 +Repeated line: 2 +Repeated line: 3 +Repeated line: 4 +Repeated line: 5 +Repeated line: 6 +Repeated line: 7 + +Repeated line: 1 +Repeated line: 2 +Repeated line: 3 +Repeated line: 4 +Repeated line: 5 +Repeated line: 6 +Repeated line: 7 + +The value of pi is 3.141592653589793. +Pi squared: 6.283185307179586 +Pi squared: 6.283185307179586 +Array [7,6,5,4,3,2,1] has length 7 +Array [7,6,5,4,3,2,1] has length 7 + +Array $a has value 7 at position 0 +Array .array and array $a are equal? (true) +Values sorted as strings: ["10","12","14","2","4","6","8"] + +
  • 1
  • +
  • 2
  • +
  • 3
  • +
  • 4
  • +
  • 5
  • +
  • 6
  • +
  • 7
  • + +Slice: [7,6,5,4] +Limit: [7,6,5,4] + +Modulo: 2 +Modulo: 2 + +Object: {"a":1,"b":2} + +Fibonacci(10): [0,1,1,2,3,5,8,13,21,34] +Fibonacci(10): 34 +Fibonacci(10): 34 + +======================= diff --git a/tests/expected/expr-01.txt b/tests/expected/expr-01.txt new file mode 100644 index 0000000..d8790ea --- /dev/null +++ b/tests/expected/expr-01.txt @@ -0,0 +1 @@ +The value of pi is 3.14159265359. diff --git a/tests/expected/expr-02.txt b/tests/expected/expr-02.txt new file mode 100644 index 0000000..728375f --- /dev/null +++ b/tests/expected/expr-02.txt @@ -0,0 +1,2 @@ + + diff --git a/tests/expected/expr-03.txt b/tests/expected/expr-03.txt new file mode 100644 index 0000000..43f0146 --- /dev/null +++ b/tests/expected/expr-03.txt @@ -0,0 +1,4 @@ + + + Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit... + diff --git a/tests/expected/expr-51.txt b/tests/expected/expr-51.txt new file mode 100644 index 0000000..d8790ea --- /dev/null +++ b/tests/expected/expr-51.txt @@ -0,0 +1 @@ +The value of pi is 3.14159265359. diff --git a/tests/expected/expr-52.txt b/tests/expected/expr-52.txt new file mode 100644 index 0000000..b36f906 --- /dev/null +++ b/tests/expected/expr-52.txt @@ -0,0 +1,14 @@ + + + + Value with <unsafe> data + + + 1, + 2, + 3, + 4, + 5, + 6 + + diff --git a/tests/expected/loop-00.txt b/tests/expected/loop-00.txt new file mode 100644 index 0000000..6a50358 --- /dev/null +++ b/tests/expected/loop-00.txt @@ -0,0 +1,6 @@ +======================= +Looping blocks +======================= + + 2 lines + 2 lines diff --git a/tests/expected/loop-01.txt b/tests/expected/loop-01.txt new file mode 100644 index 0000000..d605314 --- /dev/null +++ b/tests/expected/loop-01.txt @@ -0,0 +1,2 @@ + + diff --git a/tests/expected/loop-51.txt b/tests/expected/loop-51.txt new file mode 100644 index 0000000..d605314 --- /dev/null +++ b/tests/expected/loop-51.txt @@ -0,0 +1,2 @@ + + diff --git a/tests/expected/loop-52.txt b/tests/expected/loop-52.txt new file mode 100644 index 0000000..77e4ab9 --- /dev/null +++ b/tests/expected/loop-52.txt @@ -0,0 +1,6 @@ +
      +
    • 0
    • +
    • 1
    • +
    • 2
    • +
    • 3
    • +
    diff --git a/tests/expected/loop-53.txt b/tests/expected/loop-53.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/tests/expected/loop-53.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/tests/expected/macros-00.txt b/tests/expected/macros-00.txt new file mode 100644 index 0000000..a10d18d --- /dev/null +++ b/tests/expected/macros-00.txt @@ -0,0 +1,19 @@ + + + + diff --git a/tests/expected/syntax-00.txt b/tests/expected/syntax-00.txt new file mode 100644 index 0000000..ba20ea6 --- /dev/null +++ b/tests/expected/syntax-00.txt @@ -0,0 +1,49 @@ +======================= +Syntax tests +======================= + +_______________________ +Comments +_______________________ + +1 prefixsuffix +2 prefix suffix +3 prefix suffix +4 prefix suffix +5 +6 prefixsuffix +7 prefixsuffix +8 prefixsuffix +9 + +_______________________ +Expressions +_______________________ + +2 + 2 = 4 +2 + 2 = 4 +2 + 2 = 4 + +_______________________ +One line blocks +_______________________ + +1 Diga 33 +2 Diga 33 +3 Diga 33 +4 Diga 33 +5 Diga 33 + +_______________________ +Raw block +_______________________ + +raw + raw + raw +{{ expression }} + {{ expression }} + {% code %} + {# comment #} + +======================= diff --git a/tests/expr-00.jqt b/tests/expr-00.jqt new file mode 100644 index 0000000..d065f66 --- /dev/null +++ b/tests/expr-00.jqt @@ -0,0 +1,91 @@ +======================= +Tests about expressions +======================= + +Escape: \\ TB (\t) LF(\n) CR(\r) + +Interpolated string: {{.yes}} +Interpolated string: {{.not}} +Interpolated string: {{.nil}} +Interpolated string: {{.string}} +Interpolated string: {{.number}} + +_______________________ +Vanished line: {{empty}} +Vanished line: {{.not//empty}} +Vanished line: {{.nil//empty}} +_______________________ + +Not vanished line: {{.yes//empty}} +Not vanished line: {{.string//empty}} +Not vanished line: {{.number//empty}} +Not vanished line: {{.array//empty}} +Not vanished line: {{.object//empty}} + +Nested expression: {{if .yes then "==={{.number}}===" else "==={{.string}}===" end}} +Nested expression: {{if .not then "==={{.number}}===" else "==={{.string}}===" end}} +Nested expression: {{"={{"-{{"*"}}-"}}="}} + +Nested expression: {{ + if .yes + then "===\(.number)===" + else "===\(.string)===" + end +}} +Nested expression: {{ + if .not + then "===\(.number)===" + else "===\(.string)===" + end +}} +Nested expression: {{ + "=\( + "-\( + "*" + )-" + )=" +}} + +Local name: {{. as $M | $M.number}} +Local name: {{. as $M | $M.array | map(.*2) | sort | map(tostring)}} +Local name: {{. as $M | $M.array | map(.*2) | map(tostring) | sort}} + +Repeated line: {{.array | keys[]}} +Repeated line: {{.object | keys[]}} +Repeated line: {{.array[]}} + +Repeated line: {{. as $M | range(1;5) | .*$M.number}} + +Repeated line: {{.array | sort[]}} + +Repeated line: {{ + if .nil == null + then .array | sort[] + else empty end +}} + +{% .number %}The value of pi is {{.}}. +{% .number %}Pi squared: {{.*2}} +{% .number*2 %}Pi squared: {{.}} +{% .array %}Array {{.}} has length {{.|length}} +{% .array %}Array {{.}} has length {{length}} + +{% .array as $a %}Array $a has value {{$a[0]}} at position 0 +{% .array as $a | $M %}Array .array and array $a are equal? ({{$a == $M.array)}} +{% .array | map(.*2 | tostring) | sort %}Values sorted as strings: {{.}} + +{% .array | sort[] | tostring | "{{.}}" | "
  • {{.}}
  • " %}{{.}} + +Slice: {{ (.array | sort | reverse)[:4]}} +Limit: {{[limit(4; .array | sort | reverse[])]}} + +Modulo: {{ 2 % 7 }} +{% 2 % 7 %}Modulo: {{.}} + +Object: {{ {a:1}+{b:2} }} + +Fibonacci(10): {{ [limit(10; fibonacci)] }} +Fibonacci(10): {{ [limit(10; fibonacci)][-1] }} +Fibonacci(10): {{ [limit(10; fibonacci)] | reverse[0] }} + +======================= diff --git a/tests/expr-00.json b/tests/expr-00.json new file mode 100644 index 0000000..5726842 --- /dev/null +++ b/tests/expr-00.json @@ -0,0 +1,9 @@ +{ + "yes": true, + "not": false, + "nil": null, + "string": "Neque porro quisquam", + "number": 3.14159265358979323846, + "array": [7,6,5,4,3,2,1 ], + "object": { "b": true, "s": "Neque", "n": 3.14 } +} diff --git a/tests/expr-01.jqt b/tests/expr-01.jqt new file mode 100644 index 0000000..cb08199 --- /dev/null +++ b/tests/expr-01.jqt @@ -0,0 +1 @@ +The value of pi is {{.pi}}. diff --git a/tests/expr-01.json b/tests/expr-01.json new file mode 100644 index 0000000..bc4e78e --- /dev/null +++ b/tests/expr-01.json @@ -0,0 +1 @@ +{ "pi": 3.14159265359 } diff --git a/tests/expr-02.jqt b/tests/expr-02.jqt new file mode 100644 index 0000000..8c088e4 --- /dev/null +++ b/tests/expr-02.jqt @@ -0,0 +1,6 @@ + + diff --git a/tests/expr-02.json b/tests/expr-02.json new file mode 100644 index 0000000..de54066 --- /dev/null +++ b/tests/expr-02.json @@ -0,0 +1 @@ +{ "lang": "en_US" } diff --git a/tests/expr-03.jqt b/tests/expr-03.jqt new file mode 100644 index 0000000..bc0dc57 --- /dev/null +++ b/tests/expr-03.jqt @@ -0,0 +1,4 @@ + + + {{.title}} + diff --git a/tests/expr-03.json b/tests/expr-03.json new file mode 100644 index 0000000..8f021ee --- /dev/null +++ b/tests/expr-03.json @@ -0,0 +1,4 @@ +{ + "lang": "en_GB", + "title": "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..." +} diff --git a/tests/expr-51.jqt b/tests/expr-51.jqt new file mode 100644 index 0000000..95202de --- /dev/null +++ b/tests/expr-51.jqt @@ -0,0 +1 @@ +{%.pi%}The value of pi is {{.}}. diff --git a/tests/expr-51.json b/tests/expr-51.json new file mode 100644 index 0000000..bc4e78e --- /dev/null +++ b/tests/expr-51.json @@ -0,0 +1 @@ +{ "pi": 3.14159265359 } diff --git a/tests/expr-52.jqt b/tests/expr-52.jqt new file mode 100644 index 0000000..c3f0ccd --- /dev/null +++ b/tests/expr-52.jqt @@ -0,0 +1,9 @@ + + + + {{.variable | @html}} + + +{{ .item_list | map(" "+@text) | join(",\n") }} + + diff --git a/tests/expr-52.json b/tests/expr-52.json new file mode 100644 index 0000000..8b3244b --- /dev/null +++ b/tests/expr-52.json @@ -0,0 +1,4 @@ +{ + "variable": "Value with data", + "item_list": [1, 2, 3, 4, 5, 6] +} diff --git a/tests/filters/filters.jq b/tests/filters/filters.jq new file mode 100644 index 0000000..0ad8c57 --- /dev/null +++ b/tests/filters/filters.jq @@ -0,0 +1,19 @@ +######################################################################## +# User defined filters +######################################################################## + +# `iterate` returns an infinite stream of repeated applications of `f` to `.`: +# x | iterate(f) = x, x|f, x|f|f... +def iterate(f): + def R: ., (f | R); + . | R +; + +# Infinite generator (use with 'limit') +def fibonacci: + {x: -1, y: 1} + | iterate({x: .y, y: (.x+.y)}) + | (.x+.y) +; + +# vim:ai:sw=4:ts=4:et:syntax=jq diff --git a/tests/loop-00.jqt b/tests/loop-00.jqt new file mode 100644 index 0000000..79becbf --- /dev/null +++ b/tests/loop-00.jqt @@ -0,0 +1,7 @@ +======================= +Looping blocks +======================= + +{% range(2) %} + 2 lines +{% end %} diff --git a/tests/loop-00.json b/tests/loop-00.json new file mode 100644 index 0000000..5726842 --- /dev/null +++ b/tests/loop-00.json @@ -0,0 +1,9 @@ +{ + "yes": true, + "not": false, + "nil": null, + "string": "Neque porro quisquam", + "number": 3.14159265358979323846, + "array": [7,6,5,4,3,2,1 ], + "object": { "b": true, "s": "Neque", "n": 3.14 } +} diff --git a/tests/loop-01.jqt b/tests/loop-01.jqt new file mode 100644 index 0000000..05ef358 --- /dev/null +++ b/tests/loop-01.jqt @@ -0,0 +1 @@ + diff --git a/tests/loop-01.json b/tests/loop-01.json new file mode 100644 index 0000000..4906524 --- /dev/null +++ b/tests/loop-01.json @@ -0,0 +1 @@ +{ "author": ["Anonymous", "Unknow"] } diff --git a/tests/loop-51.jqt b/tests/loop-51.jqt new file mode 100644 index 0000000..b48482f --- /dev/null +++ b/tests/loop-51.jqt @@ -0,0 +1 @@ +{% .author | sort[] %} diff --git a/tests/loop-51.json b/tests/loop-51.json new file mode 100644 index 0000000..5642cdf --- /dev/null +++ b/tests/loop-51.json @@ -0,0 +1,3 @@ +{ + "author": ["Anonymous", "Unknow"] +} diff --git a/tests/loop-52.jqt b/tests/loop-52.jqt new file mode 100644 index 0000000..8de19ff --- /dev/null +++ b/tests/loop-52.jqt @@ -0,0 +1,5 @@ +
      + {% range(.n) %} +
    • {{.}}
    • + {% end %} +
    diff --git a/tests/loop-52.json b/tests/loop-52.json new file mode 100644 index 0000000..ff96cb3 --- /dev/null +++ b/tests/loop-52.json @@ -0,0 +1 @@ +{ "n": 4 } diff --git a/tests/loop-53.jqt b/tests/loop-53.jqt new file mode 100644 index 0000000..2ed3ddf --- /dev/null +++ b/tests/loop-53.jqt @@ -0,0 +1,3 @@ +{% range(.n) %} +{{.}} +{% end %} diff --git a/tests/loop-53.json b/tests/loop-53.json new file mode 100644 index 0000000..ff96cb3 --- /dev/null +++ b/tests/loop-53.json @@ -0,0 +1 @@ +{ "n": 4 } diff --git a/tests/macros-00.jqt b/tests/macros-00.jqt new file mode 100644 index 0000000..c2a5710 --- /dev/null +++ b/tests/macros-00.jqt @@ -0,0 +1,6 @@ +<# define required partials #> +<%shortcode youtube>& +<%shortcode analytics>& +<# expand partials #> +<%youtube 7zIoLvbCCm8 420 315> +<%analytics UA-8673551-2> diff --git a/tests/md-00.md b/tests/md-00.md new file mode 100644 index 0000000..e6815e7 --- /dev/null +++ b/tests/md-00.md @@ -0,0 +1 @@ +<#empty#> diff --git a/tests/md-01.md b/tests/md-01.md new file mode 100644 index 0000000..c1371cc --- /dev/null +++ b/tests/md-01.md @@ -0,0 +1,6 @@ +--- +author: Joan Ordinas +date: Wed Jul 27 13:26:28 CEST 2016 +--- + +Hello world! diff --git a/tests/syntax-00.jqt b/tests/syntax-00.jqt new file mode 100644 index 0000000..7e50fb2 --- /dev/null +++ b/tests/syntax-00.jqt @@ -0,0 +1,86 @@ +======================= +Syntax tests +======================= + +_______________________ +Comments +_______________________ + +1 prefix{# comment #}suffix +2 prefix {# comment #} suffix +3 prefix {# comment #} suffix{# comment #} +4 {# comment #}prefix {# comment #} suffix{# comment #} +5 {# MULTI + LINE #} +6 prefix{# MULTI + LINE #}suffix +7 prefix{# MULTI + LINE #}suffix{# comment #} +8 {# comment #}prefix{# MULTI + LINE #}suffix{# comment #} +9 {# + {{ x }} + {% b %} + {% b %}xxxxxxxxxxxx + {% end %} + {{ + x + x + }} +#} + +_______________________ +Expressions +_______________________ + +2 + 2 = {{ 2+2 }} +2 + 2 = {{ 2 + + + 2 }} +{{ 2 +}} + {{ 2 +}} = 4 + +_______________________ +One line blocks +_______________________ + +{% 33 %}1 Diga {{.}} +{% 33 %}2 Diga {{ + . + }} +{% 33 %}3 Diga {{ + .+1-1 +}} +{% 33 %}4 Di{{"ga"}} {{ + .+1-1 +}} +{% 33 %}5 Di{{"ga"+""}} {{ + .-30 +}}3 + +_______________________ +Raw block +_______________________ + +{% raw %} +raw +{%endraw%} +{% raw %} + raw +{%endraw%} + {% raw %} + raw + {%endraw%} +{% raw %} +{{ expression }} +{%endraw%} +{% raw %} + {{ expression }} +{%endraw%} +{%raw%} + {% code %} + {# comment #} +{%endraw%} + +======================= diff --git a/tools/bump-version.sh b/tools/bump-version.sh new file mode 100755 index 0000000..1f44cb6 --- /dev/null +++ b/tools/bump-version.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# works with a file called VERSION in the current directory, +# the contents of which should be a semantic version number +# such as "1.2.3" + +# this script will display the current version, automatically +# suggest a "minor" version update, and ask for input to use +# the suggestion, or a newly entered value. + +# once the new version number is determined, the script will +# pull a list of changes from git history, prepend this to +# a file called CHANGES (under the title of the new version +# number) and create a GIT tag. + +PUSH=${1:-No} + +if [[ -f VERSION ]]; then + declare -r CURRENT_VERSION=$(&2 "Current version : $CURRENT_VERSION" + set -- ${CURRENT_VERSION//./ } + declare -i V_MAJOR=$1 V_MINOR=$2 V_PATCH=$3 + V_MINOR+=1; V_PATCH=0 + declare -r SUGGESTED_VERSION="$V_MAJOR.$V_MINOR.$V_PATCH" + read 1>&2 -p "Enter a version number [$SUGGESTED_VERSION]: " + [[ -z $REPLY ]] && NEXT_VERSION=$SUGGESTED_VERSION + echo 1>&2 "Will set new version to be $NEXT_VERSION" + echo $NEXT_VERSION > VERSION + { echo "Version $NEXT_VERSION:" + git log --pretty=format:" - %s" "v$CURRENT_VERSION"...HEAD + echo -e '\n' + cat CHANGES + } > /tmp/$$-changes + cp /tmp/$$-changes CHANGES; rm /tmp/$$-changes + git add CHANGES VERSION + git commit -m "Version bump to $NEXT_VERSION" + git tag -a -m "Tagging version $NEXT_VERSION" "v$NEXT_VERSION" + [[ $PUSH == yes ]] && git push origin --tags +else + echo 1>&2 'Could not find a VERSION file' + read 1>&2 -p 'Create a new VERSION file [y/yes]? ' + case $REPLY in + ''|[Yy]|[Yy][Ee][Ss]) + echo '0.1.0' > VERSION + { echo 'Version 0.1.0' + git log --pretty=format:' - %s' + echo -e '\n' + } >> CHANGES + git add VERSION CHANGES + git commit -m 'Added VERSION and CHANGES files, version bump to v0.1.0' + git tag -a -m 'Tagging version 0.1.0' 'v0.1.0' + [[ $PUSH == yes ]] && git push origin --tags + ;; + *) echo 1>&2 'Ok' + ;; + esac +fi + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/tools/examples.md b/tools/examples.md new file mode 100644 index 0000000..3b34ff4 --- /dev/null +++ b/tools/examples.md @@ -0,0 +1,348 @@ +# Tests + + +# Examples + + +### Expressions + + +#### Test expr-01 + + +**Template**: + +``` +The value of pi is {{.pi}}. +``` + +**JSON input**: + +``` +{ "pi": 3.14159265359 } +``` + +**Output generated**: + +``` +The value of pi is 3.14159265359. +``` + +#### Test expr-02 + + +**Template**: + +``` + + +``` + +**JSON input**: + +``` +{ "lang": "en_US" } +``` + +**Output generated**: + +``` + + +``` + +#### Test expr-03 + + +**Template**: + +``` + + + {{.title}} + +``` + +**JSON input**: + +``` +{ + "lang": "en_GB", + "title": "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..." +} +``` + +**Output generated**: + +``` + + + Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit... + +``` + +#### Test expr-51 + + +**Template**: + +``` +{%.pi%}The value of pi is {{.}}. +``` + +**JSON input**: + +``` +{ "pi": 3.14159265359 } +``` + +**Output generated**: + +``` +The value of pi is 3.14159265359. +``` + +#### Test expr-52 + + +**Template**: + +``` + + + + {{.variable | @html}} + + +{{ .item_list | map(" "+@text) | join(",\n") }} + + +``` + +**JSON input**: + +``` +{ + "variable": "Value with data", + "item_list": [1, 2, 3, 4, 5, 6] +} +``` + +**Output generated**: + +``` + + + + Value with <unsafe> data + + + 1, + 2, + 3, + 4, + 5, + 6 + + +``` + +### Conditionals + + +#### Test cond-01 + + +**Template**: + +``` + + +``` + +**JSON input**: + +``` +{ "updated": "2016-06-26" } +``` + +**Output generated**: + +``` + +``` + +#### Test cond-02 + + +**Template**: + +``` +
    + {% true//empty %} + yay + {% end %} +
    +``` + +**Output generated**: + +``` +
    + yay +
    +``` + +#### Test cond-03 + + +**Template**: + +``` +
    + {{if true then "yay" else "" end}} +
    +``` + +**Output generated**: + +``` +
    + yay +
    +``` + +#### Test cond-51 + + +**Template**: + +``` +{% .published//empty | $M %} + +{% end %} +{% .updated//empty %} + +{% end %} +``` + +**JSON input**: + +``` +{ "updated": "2016-06-26" } +``` + +**Output generated**: + +``` + +``` + +### Loops + + +#### Test loop-01 + + +**Template**: + +``` + +``` + +**JSON input**: + +``` +{ "author": ["Anonymous", "Unknow"] } +``` + +**Output generated**: + +``` + + +``` + +#### Test loop-51 + + +**Template**: + +``` +{% .author | sort[] %} +``` + +**JSON input**: + +``` +{ + "author": ["Anonymous", "Unknow"] +} +``` + +**Output generated**: + +``` + + +``` + +#### Test loop-52 + + +**Template**: + +``` +
      + {% range(.n) %} +
    • {{.}}
    • + {% end %} +
    +``` + +**JSON input**: + +``` +{ "n": 4 } +``` + +**Output generated**: + +``` +
      +
    • 0
    • +
    • 1
    • +
    • 2
    • +
    • 3
    • +
    +``` + +#### Test loop-53 + + +**Template**: + +``` +{% range(.n) %} +{{.}} +{% end %} +``` + +**JSON input**: + +``` +{ "n": 4 } +``` + +**Output generated**: + +``` +0 +1 +2 +3 +``` diff --git a/tools/make-examples-md b/tools/make-examples-md new file mode 100755 index 0000000..a5af125 --- /dev/null +++ b/tools/make-examples-md @@ -0,0 +1,64 @@ +#!/bin/bash + +function mktest +{ + local TEST=$1 + echo -e "\n#### Test $TEST\n" + + local TEMPLATE=tests/${TEST}.jqt + local METADATA=tests/${TEST}.json + local EXPECTED=tests/expected/${TEST}.txt + [[ -e $EXPECTED ]] || EXPECTED=tests/expected/${TEST}.jqt + + echo -e "\n**Template**:\n" + echo '```' + cat $TEMPLATE + echo '```' + + if [[ -e $METADATA ]]; then + echo -e "\n**JSON input**:\n" + echo '```' + cat $METADATA + echo '```' + fi + + echo -e "\n**Output generated**:\n" + echo '```' + cat $EXPECTED + echo '```' +} + +function mkdoc +{ + for f in tests/$1-??.jqt; do + local TEST=${f#tests/}; TEST=${TEST%.jqt} + [[ $TEST == *00 ]] && continue + mktest $TEST + done +} + +exec > examples.md + +cd .. + +echo -e "# Tests\n" +echo -e "\n# Examples\n" + +echo -e "\n### Expressions\n" +mkdoc expr +echo -e "\n### Conditionals\n" +mkdoc cond +echo -e "\n### Loops\n" +mkdoc loop + +#?echo -e "\n# Bulk tests\n" +#?echo -e "\n### Syntax\n" +#?mktest 'syntax-00' +#?echo -e "\n### Expressions\n" +#?mktest 'expr-00' +#?echo -e "\n### Conditionals\n" +#?mktest 'cond-00' +#?echo -e "\n### Loops\n" +#?mktest 'loop-00' + +# vim:ai:sw=4:ts=4:et:syntax=sh