Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51fc9e02a5 | ||
|
|
0d31bdc4cf | ||
|
|
0960bfc06d | ||
|
|
22e6f9e966 | ||
|
|
df8346a935 | ||
|
|
e1fb525796 | ||
|
|
da170faafe | ||
|
|
03f746bf24 | ||
|
|
5989388c9c | ||
|
|
208c668818 |
No files matched your search
+12
-8
@@ -17,6 +17,7 @@ jobs:
|
||||
stage: test
|
||||
os: linux
|
||||
compiler: gcc
|
||||
python: 3.6
|
||||
|
||||
addons:
|
||||
apt:
|
||||
@@ -27,13 +28,13 @@ jobs:
|
||||
|
||||
before_install:
|
||||
- uname -s
|
||||
- rvm install ruby-1.9.3-p551
|
||||
- rvm use 1.9.3
|
||||
- rm src/{lexer,parser}.{c,h}
|
||||
- sed -i.bak '/^AM_INIT_AUTOMAKE(\[-Wno-portability 1\.14\])$/s/14/11/' modules/oniguruma/configure.ac
|
||||
|
||||
install:
|
||||
- bundle install --gemfile=docs/Gemfile
|
||||
- pyenv global 3.6
|
||||
- pip3 install pipenv
|
||||
- pushd docs && pipenv sync && popd
|
||||
- wget http://ftp.debian.org/debian/pool/main/b/bison/bison_3.0.2.dfsg-2_amd64.deb
|
||||
- ar p bison_3.0.2.dfsg-2_amd64.deb data.tar.xz | tar xJ
|
||||
- if [ -n "$COVERAGE" ]; then pip install --user cpp-coveralls; fi
|
||||
@@ -104,14 +105,12 @@ jobs:
|
||||
- uname -s
|
||||
- brew update
|
||||
- brew install flex bison
|
||||
- rvm install ruby-1.9.3-p551
|
||||
- rvm use 1.9.3
|
||||
- gem install bundler
|
||||
- rm src/{lexer,parser}.{c,h}
|
||||
- sed -i.bak '/^AM_INIT_AUTOMAKE(\[-Wno-portability 1\.14\])$/s/14/11/' modules/oniguruma/configure.ac
|
||||
|
||||
install:
|
||||
- bundle install --gemfile=docs/Gemfile
|
||||
- pip3 install pipenv
|
||||
- pushd docs && pipenv sync && popd
|
||||
- if [ -n "$COVERAGE" ]; then pip install --user cpp-coveralls; fi
|
||||
|
||||
|
||||
@@ -136,7 +135,9 @@ jobs:
|
||||
|
||||
install:
|
||||
- sudo sh alpine-chroot-install -b v3.7 -a "$ARCH"
|
||||
-p 'build-base automake autoconf bison libtool oniguruma-dev'
|
||||
-p 'build-base automake autoconf bison git libtool oniguruma-dev python3 python3-dev libxml2-dev libxslt-dev'
|
||||
- /alpine/enter-chroot pip3 install pipenv
|
||||
- alpine sh -c 'cd docs && pipenv sync'
|
||||
|
||||
before_script:
|
||||
- autoreconf -if
|
||||
@@ -146,6 +147,9 @@ jobs:
|
||||
- alpine make
|
||||
- alpine make check
|
||||
|
||||
after_failure:
|
||||
- cat test-suite.log
|
||||
- cat tests/*.log
|
||||
|
||||
# Build release binary statically linked with musl libc on Alpine Linux
|
||||
# (inside chroot). If building a tagged commit, then deploy release
|
||||
|
||||
+5
-7
@@ -13,9 +13,8 @@ RUN apt-get update && \
|
||||
git \
|
||||
bison \
|
||||
flex \
|
||||
ruby \
|
||||
wget \
|
||||
ruby-dev && \
|
||||
python3 \
|
||||
wget && \
|
||||
wget https://github.com/kkos/oniguruma/archive/v5.9.6.tar.gz -O onig-5.9.6.tar.gz && \
|
||||
sha512sum onig-5.9.6.tar.gz | grep 6b048d345e148c9da38af7a8df76d4a358eb3d4db91fa7834076e511f526a63544284f212b0d56badbbd33112c8b458a5fff02bfbbda012ecfe478bc436ea679 && \
|
||||
tar zxvf onig-5.9.6.tar.gz && \
|
||||
@@ -25,8 +24,8 @@ RUN apt-get update && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make && \
|
||||
make install ) && \
|
||||
gem install bundler && \
|
||||
(cd /app/docs && bundle install) && \
|
||||
pip3 install pipenv && \
|
||||
(cd /app/docs && pipenv sync) && \
|
||||
(cd /app && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-valgrind --enable-all-static --prefix=/usr/local && \
|
||||
@@ -43,8 +42,7 @@ RUN apt-get update && \
|
||||
bison \
|
||||
git \
|
||||
flex \
|
||||
ruby \
|
||||
ruby-dev && \
|
||||
python3 && \
|
||||
apt-get autoremove -y && \
|
||||
rm -rf oniguruma-5.9.6 && \
|
||||
rm -rf /var/lib/apt/lists/* /var/lib/gems
|
||||
|
||||
+9
-9
@@ -136,8 +136,8 @@ TESTS_ENVIRONMENT = NO_VALGRIND=$(NO_VALGRIND)
|
||||
|
||||
man_MANS = jq.1
|
||||
if ENABLE_DOCS
|
||||
jq.1: $(srcdir)/docs/content/3.manual/manual.yml
|
||||
$(AM_V_GEN) ( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage ) > $@ || { rm -f $@; false; }
|
||||
jq.1: $(srcdir)/docs/content/manual/manual.yml
|
||||
$(AM_V_GEN) ( cd ${abs_srcdir}/docs; pipenv run python build_manpage.py ) > $@ || { rm -f $@; false; }
|
||||
jq.1.prebuilt: jq.1
|
||||
$(AM_V_GEN) cp jq.1 $@ || { rm -f $@; false; }
|
||||
else
|
||||
@@ -165,8 +165,8 @@ install-binaries: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-exec
|
||||
|
||||
DOC_FILES = docs/content docs/public docs/templates docs/site.yml \
|
||||
docs/Gemfile docs/Gemfile.lock docs/Rakefile docs/README.md \
|
||||
jq.1.prebuilt
|
||||
docs/Pipfile docs/Pipfile.lock docs/build_manpage.py \
|
||||
docs/build_manpage.py docs/README.md jq.1.prebuilt
|
||||
|
||||
EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
|
||||
jq.1.prebuilt jq.spec src/lexer.c src/lexer.h src/parser.c \
|
||||
@@ -180,11 +180,11 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
|
||||
tests/modules/test_bind_order0.jq \
|
||||
tests/modules/test_bind_order1.jq \
|
||||
tests/modules/test_bind_order2.jq tests/onig.supp \
|
||||
tests/onig.test tests/setup tests/torture/input0.json \
|
||||
tests/optional.test tests/optionaltest \
|
||||
tests/utf8-truncate.jq tests/utf8test \
|
||||
tests/base64.test tests/base64test \
|
||||
tests/jq-f-test.sh tests/shtest
|
||||
tests/onig.test tests/setup tests/torture/input0.json \
|
||||
tests/optional.test tests/optionaltest \
|
||||
tests/utf8-truncate.jq tests/utf8test \
|
||||
tests/base64.test tests/base64test \
|
||||
tests/jq-f-test.sh tests/shtest
|
||||
|
||||
|
||||
|
||||
|
||||
+11
-9
@@ -1,26 +1,28 @@
|
||||
environment:
|
||||
matrix:
|
||||
- MSYSTEM: MINGW64
|
||||
PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH%
|
||||
PATH: C:\Python36;C:\Python36\Scripts;C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH%
|
||||
- MSYSTEM: MINGW32
|
||||
PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH%
|
||||
PATH: C:\Python36;C:\Python36\Scripts;C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH%
|
||||
|
||||
clone_script:
|
||||
- bash -lc "git clone -q --branch=$APPVEYOR_REPO_BRANCH https://github.com/${APPVEYOR_REPO_NAME}.git $APPVEYOR_BUILD_FOLDER"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER && git checkout -qf $APPVEYOR_REPO_BRANCH"
|
||||
- bash -lc "echo $APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME - $APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"
|
||||
- bash -lc "git clone -q --branch=${APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH:-$APPVEYOR_REPO_BRANCH} https://github.com/${APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME:-$APPVEYOR_REPO_NAME}.git $APPVEYOR_BUILD_FOLDER"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER && git checkout -qf ${APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH:APPVEYOR_REPO_BRANCH}"
|
||||
- bash -lc "cd $APPVEYOR_BUILD_FOLDER && git submodule update --init --recursive"
|
||||
|
||||
install:
|
||||
# update mysy2
|
||||
# update msys2
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S git"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Su"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex git"
|
||||
- C:\msys64\usr\bin\bash -lc "pip3 install --upgrade pipenv"
|
||||
- C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER/docs && ls && pipenv sync"
|
||||
|
||||
build_script:
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && autoreconf -i"
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && ./configure --with-oniguruma=builtin --disable-shared --enable-static --enable-all-static"
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && make -j8"
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && make"
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && cat jq.1 | groff -mandoc -Thtml > jq.html"
|
||||
- 7z a jq-package.zip jq.1 jq.html jq.exe
|
||||
- bash -lc "exec 0</dev/null && cd $APPVEYOR_BUILD_FOLDER && pwd && ls -la"
|
||||
|
||||
+10
-10
@@ -74,7 +74,7 @@ dnl Code coverage
|
||||
AC_ARG_ENABLE([gcov],
|
||||
AC_HELP_STRING([--enable-gcov], [enable gcov code coverage tool]))
|
||||
|
||||
dnl Don't attempt to build docs if there's no Ruby lying around
|
||||
dnl Don't attempt to build docs if python deps aren't installed
|
||||
AC_ARG_ENABLE([docs],
|
||||
AC_HELP_STRING([--disable-docs], [don't build docs]))
|
||||
|
||||
@@ -87,25 +87,25 @@ AC_ARG_ENABLE([all-static],
|
||||
AC_HELP_STRING([--enable-all-static], [link jq with static libraries only]))
|
||||
|
||||
AS_IF([test "x$enable_docs" != "xno"],[
|
||||
AC_CHECK_PROGS(bundle_cmd, bundle)
|
||||
AC_CHECK_PROGS(pipenv_cmd, pipenv)
|
||||
|
||||
AC_CACHE_CHECK([for Ruby dependencies], [jq_cv_ruby_deps],
|
||||
[jq_cv_ruby_deps=yes;
|
||||
AS_IF([test "x$bundle_cmd" = "x" || \
|
||||
! bmsg="`cd ${srcdir}/docs; "$bundle_cmd" check 2>/dev/null`"],[
|
||||
AC_MSG_WARN([$bmsg])
|
||||
AC_CACHE_CHECK([for Python dependencies], [jq_cv_python_deps],
|
||||
[jq_cv_python_deps=yes;
|
||||
AS_IF([test "x$pipenv_cmd" = "x" || \
|
||||
! bmsg="`cd ${srcdir}/docs; LC_ALL=$LANG "$pipenv_cmd" check`"],[
|
||||
AC_MSG_ERROR([$bmsg])
|
||||
cat <<EOF
|
||||
*****************************************************************
|
||||
* Ruby dependencies for building jq documentation not found. *
|
||||
* Python dependencies for building jq documentation not found. *
|
||||
* You can still build, install and hack on jq, but the manpage *
|
||||
* will not be rebuilt and some of the tests will not run. *
|
||||
* See docs/README.md for how to install the docs dependencies. *
|
||||
*****************************************************************
|
||||
EOF
|
||||
jq_cv_ruby_deps=no
|
||||
jq_cv_python_deps=no
|
||||
])])
|
||||
|
||||
if test "x$jq_cv_ruby_deps" != "xyes"; then
|
||||
if test "x$jq_cv_python_deps" != "xyes"; then
|
||||
enable_docs=no
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
.DS_Store
|
||||
.sass-cache
|
||||
output/*
|
||||
|
||||
# Autogenerated from public/css/base.scss
|
||||
public/css/base.css
|
||||
@@ -1,7 +0,0 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "rake"
|
||||
gem "bonsai"
|
||||
gem "maruku"
|
||||
gem "ronn"
|
||||
gem "mustache", "<1.0" # to support ruby <2.0
|
||||
@@ -1,63 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (4.2.3)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.3.8)
|
||||
bonsai (1.4.9)
|
||||
activesupport (>= 3.0.3)
|
||||
builder (>= 3.0.0)
|
||||
i18n (>= 0.5.0)
|
||||
launchy (>= 0.3.7)
|
||||
liquid (>= 2.2.2)
|
||||
maruku (>= 0.6.0)
|
||||
rack
|
||||
sass
|
||||
sinatra (>= 1.0)
|
||||
tilt (>= 1.3)
|
||||
watch (>= 0.1.0)
|
||||
yui-compressor
|
||||
builder (3.2.2)
|
||||
hpricot (0.8.6)
|
||||
i18n (0.7.0)
|
||||
json (1.8.3)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
liquid (3.0.6)
|
||||
maruku (0.7.2)
|
||||
minitest (5.8.0)
|
||||
mustache (0.99.8)
|
||||
rack (1.6.4)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rake (10.4.2)
|
||||
rdiscount (2.1.8)
|
||||
ronn (0.7.3)
|
||||
hpricot (>= 0.8.2)
|
||||
mustache (>= 0.7.0)
|
||||
rdiscount (>= 1.5.8)
|
||||
sass (3.4.16)
|
||||
sinatra (1.4.6)
|
||||
rack (~> 1.4)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.1)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
watch (0.1.0)
|
||||
yui-compressor (0.12.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
bonsai
|
||||
maruku
|
||||
mustache (< 1.0)
|
||||
rake
|
||||
ronn
|
||||
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
jinja2 = "*"
|
||||
pyyaml = "*"
|
||||
markdown = "*"
|
||||
lxml = "*"
|
||||
Generated
+117
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "16a9ef323592a417142c30be17e58c3cf36dc2bfdbf4757106a796b22262a1ce"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.10"
|
||||
},
|
||||
"lxml": {
|
||||
"hashes": [
|
||||
"sha256:0537eee4902e8bf4f41bfee8133f7edf96533dd175930a12086d6a40d62376b2",
|
||||
"sha256:0562ec748abd230ab87d73384e08fa784f9b9cee89e28696087d2d22c052cc27",
|
||||
"sha256:09e91831e749fbf0f24608694e4573be0ef51430229450c39c83176cc2e2d353",
|
||||
"sha256:1ae4c0722fc70c0d4fba43ae33c2885f705e96dce1db41f75ae14a2d2749b428",
|
||||
"sha256:1c630c083d782cbaf1f7f37f6cac87bda9cff643cf2803a5f180f30d97955cef",
|
||||
"sha256:2fe74e3836bd8c0fa7467ffae05545233c7f37de1eb765cacfda15ad20c6574a",
|
||||
"sha256:37af783c2667ead34a811037bda56a0b142ac8438f7ed29ae93f82ddb812fbd6",
|
||||
"sha256:3f2d9eafbb0b24a33f56acd16f39fc935756524dcb3172892721c54713964c70",
|
||||
"sha256:47d8365a8ef14097aa4c65730689be51851b4ade677285a3b2daa03b37893e26",
|
||||
"sha256:510e904079bc56ea784677348e151e1156040dbfb736f1d8ea4b9e6d0ab2d9f4",
|
||||
"sha256:58d0851da422bba31c7f652a7e9335313cf94a641aa6d73b8f3c67602f75b593",
|
||||
"sha256:7940d5c2185ffb989203dacbb28e6ae88b4f1bb25d04e17f94b0edd82232bcbd",
|
||||
"sha256:7cf39bb3a905579836f7a8f3a45320d9eb22f16ab0c1e112efb940ced4d057a5",
|
||||
"sha256:9563a23c1456c0ab550c087833bc13fcc61013a66c6420921d5b70550ea312bf",
|
||||
"sha256:95b392952935947e0786a90b75cc33388549dcb19af716b525dae65b186138fc",
|
||||
"sha256:983129f3fd3cef5c3cf067adcca56e30a169656c00fcc6c648629dbb850b27fa",
|
||||
"sha256:a0b75b1f1854771844c647c464533def3e0a899dd094a85d1d4ed72ecaaee93d",
|
||||
"sha256:b5db89cc0ef624f3a81214b7961a99f443b8c91e88188376b6b322fd10d5b118",
|
||||
"sha256:c0a7751ba1a4bfbe7831920d98cee3ce748007eab8dfda74593d44079568219a",
|
||||
"sha256:c0c5a7d4aafcc30c9b6d8613a362567e32e5f5b708dc41bc3a81dac56f8af8bb",
|
||||
"sha256:d4d63d85eacc6cb37b459b16061e1f100d154bee89dc8d8f9a6128a5a538e92e",
|
||||
"sha256:da5e7e941d6e71c9c9a717c93725cda0708c2474f532e3680ac5e39ec57d224d",
|
||||
"sha256:dccad2b3c583f036f43f80ac99ee212c2fa9a45151358d55f13004d095e683b2",
|
||||
"sha256:df46307d39f2aeaafa1d25309b8a8d11738b73e9861f72d4d0a092528f498baa",
|
||||
"sha256:e70b5e1cb48828ddd2818f99b1662cb9226dc6f57d07fc75485405c77da17436",
|
||||
"sha256:ea825562b8cd057cbc9810d496b8b5dec37a1e2fc7b27bc7c1e72ce94462a09a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.3.1"
|
||||
},
|
||||
"markdown": {
|
||||
"hashes": [
|
||||
"sha256:c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa",
|
||||
"sha256:d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
|
||||
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
|
||||
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
|
||||
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
|
||||
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
|
||||
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
|
||||
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
|
||||
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
|
||||
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
|
||||
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
|
||||
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
|
||||
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
|
||||
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
|
||||
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
|
||||
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
|
||||
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
|
||||
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
|
||||
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
|
||||
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
|
||||
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
|
||||
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
|
||||
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
|
||||
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
|
||||
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
|
||||
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
|
||||
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
|
||||
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
|
||||
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
|
||||
"sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
|
||||
"sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
|
||||
"sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
|
||||
"sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
|
||||
"sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
|
||||
"sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
|
||||
"sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
|
||||
"sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
|
||||
"sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
|
||||
"sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.13"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
+10
-15
@@ -2,24 +2,19 @@ Documentation
|
||||
=============
|
||||
|
||||
The jq website, manpages and some of the tests are generated from this
|
||||
directory. The directory holds a [Bonsai](http://tinytree.info)
|
||||
website, and the manual is a YAML file in `content/3.manual`.
|
||||
directory. The manual is a YAML file in `content/manual`.
|
||||
|
||||
To build the documentation (including building the jq manpage), you'll
|
||||
need a working Ruby setup. The easiest way to get one is to install
|
||||
RVM and Ruby 1.9.3 like so:
|
||||
need python3 and pipenv. You can install pipenv like so:
|
||||
|
||||
\curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
|
||||
pip install pipenv
|
||||
|
||||
After that finishes installing, you'll need to make sure RVM is on
|
||||
your path by doing `source $HOME/.rvm/scripts/rvm`, or just opening a
|
||||
new shell. See <https://rvm.io> for more info on RVM.
|
||||
Though, you may need to say pip3 instead, depending on your system. Once
|
||||
you have pipenv installed, you can install the dependencies by running
|
||||
`pipenv install` from the `docs` directory.
|
||||
|
||||
Once RVM is installed, you can install all the dependencies for jq's
|
||||
documentation build by running this from the `docs` directory:
|
||||
Once this is done, rerun `./configure` in the jq root directory and then
|
||||
the Makefile will be able to generate the jq manpage.
|
||||
|
||||
bundle install
|
||||
|
||||
When bundle manages to install the dependencies, rerun `./configure`
|
||||
in the jq root directory and then the Makefile will be able to
|
||||
generate the jq manpage.
|
||||
To build the website, run `pipenv run ./build_website.py` from inside
|
||||
the `docs` directory.
|
||||
@@ -1,24 +0,0 @@
|
||||
current_dir = File.dirname(__FILE__)
|
||||
rakefile_manual = File.expand_path(File.join(current_dir, "Rakefile.manual"))
|
||||
rakefile_website = File.expand_path(File.join(current_dir, "Rakefile.website"))
|
||||
|
||||
desc "Build the manpage from the bonsai source of the manual"
|
||||
task :manpage do
|
||||
system %(#{$0} -f #{rakefile_manual} manpage)
|
||||
end
|
||||
|
||||
desc "Collect jq unit test cases from the bonsai source of the manual"
|
||||
task :mantests do
|
||||
system %(#{$0} -f #{rakefile_manual} mantests)
|
||||
end
|
||||
|
||||
desc "Build the website from the bonsai sources"
|
||||
task :build do
|
||||
system %(#{$0} -f #{rakefile_website} build)
|
||||
end
|
||||
|
||||
desc "Serve a live view of the website on http://localhost:5000/jq/"
|
||||
task :serve do
|
||||
system %(#{$0} -f #{rakefile_website} serve)
|
||||
end
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
require 'ronn'
|
||||
require 'tempfile'
|
||||
require 'yaml'
|
||||
|
||||
def load_manual
|
||||
YAML::load(File.open("content/3.manual/manual.yml"))
|
||||
end
|
||||
|
||||
task :manpage do
|
||||
Tempfile.open "manpage" do |f|
|
||||
manual = load_manual
|
||||
f.puts manual['manpage_intro']
|
||||
f.puts manual['body']
|
||||
manual['sections'].each do |section|
|
||||
|
||||
f.puts "## #{section['title'].upcase}\n"
|
||||
f.puts section['body']
|
||||
f.puts ""
|
||||
(section['entries'] || []).each do |entry|
|
||||
f.puts "### #{entry['title']}\n"
|
||||
f.puts entry['body']
|
||||
f.puts ""
|
||||
(entry['examples'] || []).each do |example|
|
||||
f.puts " jq '#{example['program']}'"
|
||||
f.puts " #{example['input']}"
|
||||
f.puts " => #{example['output'].join(", ")}"
|
||||
f.puts
|
||||
end
|
||||
end
|
||||
f.puts ""
|
||||
end
|
||||
f.puts manual['manpage_epilogue']
|
||||
f.close
|
||||
puts Ronn::Document.new(f.path).convert('roff').gsub(/<\/?code>/,"")
|
||||
end
|
||||
end
|
||||
|
||||
task :mantests do
|
||||
load_manual['sections'].each do |section|
|
||||
(section['entries'] || []).each do |entry|
|
||||
(entry['examples'] || []).each do |example|
|
||||
puts example['program'].gsub("\n", " ")
|
||||
puts example['input']
|
||||
example['output'].each do |s| puts s end
|
||||
puts
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,76 +0,0 @@
|
||||
require 'bonsai'
|
||||
require 'json'
|
||||
require 'liquid'
|
||||
require 'maruku'
|
||||
|
||||
module ExtraFilters
|
||||
def markdownify(input)
|
||||
Maruku.new(input).to_html
|
||||
end
|
||||
def search_id(input)
|
||||
input.gsub(/`/, '')
|
||||
end
|
||||
def section_id(input)
|
||||
input.gsub(/[^a-zA-Z0-9_]/, '')
|
||||
end
|
||||
def entry_id(input)
|
||||
input.gsub(/[ `]/, '')
|
||||
end
|
||||
def no_paragraph(input)
|
||||
input.gsub('<p>', '').gsub('</p>', '')
|
||||
end
|
||||
def json(input)
|
||||
input.to_json
|
||||
end
|
||||
def unique(input)
|
||||
@n = (@n || 0) + 1
|
||||
input + @n.to_s
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_filter(ExtraFilters)
|
||||
|
||||
begin
|
||||
`java 2>&1`
|
||||
rescue
|
||||
class Bonsai::Exporter
|
||||
def self.compress_assets
|
||||
Bonsai.log "java not found! Not compressing javascript or stylesheets"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task :build do
|
||||
Bonsai.root_dir = Dir.pwd
|
||||
Bonsai::Exporter.publish!
|
||||
end
|
||||
|
||||
task :serve do
|
||||
begin
|
||||
Bonsai.log "Press Control+C to quit"
|
||||
|
||||
require 'rack'
|
||||
require 'sinatra'
|
||||
require 'watch'
|
||||
require 'launchy'
|
||||
|
||||
Bonsai.root_dir = Dir.pwd
|
||||
|
||||
server = fork {
|
||||
app = Rack::Builder.app {
|
||||
map "/jq" do
|
||||
use Bonsai::StaticPassThrough, :root => Bonsai.root_dir + "/output", :urls => ["/"]
|
||||
end
|
||||
run Bonsai::DevelopmentServer
|
||||
}
|
||||
Rack::Handler.default.run(app, :Port => 5000) do
|
||||
Launchy.open("http://localhost:5000/jq/")
|
||||
end
|
||||
}
|
||||
Watch.new("{content,templates,public}/**/*") { Bonsai::Exporter.process! }
|
||||
rescue Interrupt
|
||||
Process.kill("QUIT", server)
|
||||
Process.wait(server)
|
||||
exit
|
||||
end
|
||||
end
|
||||
Executable
+235
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python3
|
||||
from datetime import date
|
||||
from io import StringIO
|
||||
from lxml import etree
|
||||
import markdown
|
||||
from markdown.extensions import Extension
|
||||
import re
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
# Prevent our markdown parser from trying to help by interpreting things in angle brackets as HTML tags.
|
||||
class EscapeHtml(Extension):
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
del md.preprocessors['html_block']
|
||||
del md.inlinePatterns['html']
|
||||
|
||||
class RoffWalker(object):
|
||||
def __init__(self, tree, output=sys.stdout):
|
||||
self.tree = tree
|
||||
self.target = output
|
||||
self.f = StringIO()
|
||||
|
||||
def walk(self):
|
||||
self._walk(self.tree, parent_tag=None)
|
||||
# We don't want to start lines with \. because that can confuse man
|
||||
# For lines that start with \., we need to prefix them with \& so it
|
||||
# knows not to treat that line as a directive
|
||||
data = re.sub(r'^\\\.', r'\&.', self.f.getvalue(), flags=re.MULTILINE)
|
||||
self.target.write(data)
|
||||
|
||||
def _ul_is_special(self, root):
|
||||
if len(root) != 1:
|
||||
return False
|
||||
child = root[0]
|
||||
if child.tag != 'li':
|
||||
return False
|
||||
msg = ''.join(child.itertext()).strip()
|
||||
return msg.endswith(':')
|
||||
|
||||
def _walk_child(self, root):
|
||||
if len(root) > 0:
|
||||
self._walk(root[0], parent_tag=root.tag)
|
||||
|
||||
def _write_element(self, root, ensure_newline=True):
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw(text)
|
||||
self._walk_child(root)
|
||||
self._write_tail(root, ensure_newline=ensure_newline)
|
||||
|
||||
def _write_tail(self, root, ensure_newline=False, inline=False):
|
||||
if root.tail is not None:
|
||||
if inline or root.tail != '\n':
|
||||
text = self._sanitize(root.tail)
|
||||
if text.endswith('\n'):
|
||||
ensure_newline = False
|
||||
self.__write_raw(text)
|
||||
if ensure_newline:
|
||||
self.__write_raw('\n')
|
||||
|
||||
def _walk(self, root, parent_tag=None):
|
||||
last_tag = None
|
||||
while root is not None:
|
||||
if root.tag == 'h1':
|
||||
self.__write_cmd('.TH "JQ" "1" "{}" "" ""'.format(date.today().strftime('%B %Y')))
|
||||
self.__write_cmd('.SH "NAME"')
|
||||
# TODO: properly parse this
|
||||
self.__write_raw(r'\fBjq\fR \- Command\-line JSON processor' + "\n")
|
||||
|
||||
elif root.tag == 'h2':
|
||||
self.__write_cmd('.SH "{}"'.format(''.join(root.itertext()).strip()))
|
||||
|
||||
elif root.tag == 'h3':
|
||||
text = ''.join(root.itertext()).strip()
|
||||
self.__write_cmd('.SS "{}"'.format(self._h3_sanitize(text)))
|
||||
|
||||
elif root.tag == 'p':
|
||||
if last_tag not in ['h2', 'h3'] and parent_tag not in ['li']:
|
||||
self.__write_cmd('.P')
|
||||
self._write_element(root, ensure_newline=(parent_tag != 'li'))
|
||||
|
||||
elif root.tag == 'ul':
|
||||
if self._ul_is_special(root):
|
||||
li = root[0]
|
||||
self.__write_cmd('.TP')
|
||||
self._write_element(li)
|
||||
next = root.getnext()
|
||||
while next is not None and next.tag == 'p':
|
||||
if next.getnext() is not None and next.getnext().tag == 'pre':
|
||||
# we don't want to .IP these, because it'll look funny with the code indent
|
||||
break
|
||||
self.__write_cmd('.IP')
|
||||
self._write_element(next)
|
||||
root = next
|
||||
next = root.getnext()
|
||||
else:
|
||||
self._walk_child(root)
|
||||
self._write_tail(root)
|
||||
# A pre tag after the end of a list doesn't want two of the indentation commands
|
||||
if root.getnext() is None or root.getnext().tag != 'pre':
|
||||
self.__write_cmd('.IP "" 0')
|
||||
|
||||
elif root.tag == 'li':
|
||||
self.__write_cmd(r'.IP "\(bu" 4')
|
||||
if root.text is not None and root.text.strip() != '':
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw(text)
|
||||
self._walk_child(root)
|
||||
self._write_tail(root, ensure_newline=True)
|
||||
|
||||
elif root.tag == 'strong':
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw('\\fB{}\\fR'.format(text))
|
||||
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'em':
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw('\\fI{}\\fR'.format(text))
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'code':
|
||||
if root.text is not None:
|
||||
text = self._code_sanitize(root.text)
|
||||
self.__write_raw('\\fB{}\\fR'.format(text))
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'pre':
|
||||
self.__write_cmd('.IP "" 4')
|
||||
self.__write_cmd('.nf\n') # extra newline for spacing reasons
|
||||
next = root
|
||||
first = True
|
||||
while next is not None and next.tag == 'pre':
|
||||
if not first:
|
||||
self.__write_raw('\n')
|
||||
text = ''.join(next.itertext(with_tail=False))
|
||||
self.__write_raw(self._pre_sanitize(text))
|
||||
first = False
|
||||
root = next
|
||||
next = next.getnext()
|
||||
self.__write_cmd('.fi')
|
||||
self.__write_cmd('.IP "" 0')
|
||||
|
||||
else:
|
||||
self._walk_child(root)
|
||||
|
||||
last_tag = root.tag
|
||||
root = root.getnext()
|
||||
|
||||
def _base_sanitize(self, text):
|
||||
text = re.sub(r'\\', r'\\e', text)
|
||||
text = re.sub(r'\.', r'\\.', text)
|
||||
text = re.sub("'", r"\'", text)
|
||||
text = re.sub('-', r'\-', text)
|
||||
return text
|
||||
|
||||
def _pre_sanitize(self, text):
|
||||
return self._base_sanitize(text)
|
||||
|
||||
def _code_sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(r'\s', ' ', text)
|
||||
return text
|
||||
|
||||
def _h3_sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(' \n|\n ', ' ', text)
|
||||
text = re.sub('\n', ' ', text)
|
||||
return text
|
||||
|
||||
def _sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(r'<([^>]+)>', r'\\fI\1\\fR', text)
|
||||
text = re.sub(r' +', ' ', text)
|
||||
text = re.sub('\n', ' ', text)
|
||||
return text
|
||||
|
||||
def __write_cmd(self, dat):
|
||||
print('.', dat, sep='\n', file=self.f)
|
||||
pass
|
||||
|
||||
def __write_raw(self, dat):
|
||||
print(dat, sep='', end='', file=self.f)
|
||||
pass
|
||||
|
||||
def load_yml_file(fn):
|
||||
with open(fn) as f:
|
||||
return yaml.load(f)
|
||||
|
||||
def dedent_body(body):
|
||||
lines = [re.sub(r'^ (\S)', r'\1', l) for l in body.split('\n')]
|
||||
return '\n'.join(lines)
|
||||
|
||||
def convert_manual_to_markdown():
|
||||
f = StringIO()
|
||||
manual = load_yml_file("content/manual/manual.yml")
|
||||
f.write(manual.get('manpage_intro', '\n'))
|
||||
f.write(dedent_body(manual.get('body', '\n')))
|
||||
for section in manual.get('sections', []):
|
||||
f.write('## {}\n'.format(section.get('title', '').upper()))
|
||||
f.write(dedent_body(section.get('body', '\n')))
|
||||
f.write('\n')
|
||||
for entry in section.get('entries', []):
|
||||
f.write('### {}\n'.format(entry.get('title', '')))
|
||||
f.write(dedent_body(entry.get('body', '\n')))
|
||||
f.write('\n')
|
||||
if entry.get('examples') is not None:
|
||||
f.write("~~~~\n")
|
||||
first = True
|
||||
for example in entry.get('examples'):
|
||||
if not first:
|
||||
f.write('\n')
|
||||
f.write("jq '{}'\n".format(example.get('program', '')))
|
||||
f.write(" {}\n".format(example.get('input', '')))
|
||||
output = [str(x) for x in example.get('output', [])]
|
||||
f.write("=> {}\n".format(', '.join(output)))
|
||||
first = False
|
||||
f.write("~~~~\n")
|
||||
f.write('\n')
|
||||
f.write(manual.get('manpage_epilogue', ''))
|
||||
return f.getvalue()
|
||||
|
||||
# Convert manual.yml to our special markdown format
|
||||
markdown_data = convert_manual_to_markdown()
|
||||
|
||||
# Convert markdown to html
|
||||
html_data = markdown.markdown(markdown_data, extensions=[EscapeHtml(), 'fenced_code'])
|
||||
|
||||
# Parse the html into a tree so we can walk it
|
||||
tr = etree.HTML(html_data, etree.HTMLParser())
|
||||
|
||||
# Convert the markdown to ROFF
|
||||
RoffWalker(tr).walk()
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
import yaml
|
||||
|
||||
with open("content/manual/manual.yml") as f:
|
||||
manual = yaml.load(f)
|
||||
for section in manual.get('sections', []):
|
||||
for entry in section.get('entries', []):
|
||||
for example in entry.get('examples', []):
|
||||
print(example.get('program', '').replace('\n', ' '))
|
||||
print(example.get('input', ''))
|
||||
for s in example.get('output', []):
|
||||
print(s)
|
||||
print('')
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
import glob
|
||||
import itertools
|
||||
from jinja2 import Environment, FileSystemLoader, Markup, select_autoescape, contextfunction
|
||||
from markdown import markdown
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import yaml
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader('templates'),
|
||||
autoescape=select_autoescape(['html.j2']),
|
||||
)
|
||||
|
||||
def load_yml_file(fn):
|
||||
with open(fn) as f:
|
||||
return yaml.load(f)
|
||||
|
||||
env.filters['search_id'] = lambda input: input.replace(r'`', '')
|
||||
env.filters['section_id'] = lambda input: re.sub(r"[^a-zA-Z0-9_]", '', input)
|
||||
env.filters['entry_id'] = lambda input: re.sub(r"[ `]", '', input)
|
||||
env.filters['markdownify'] = lambda input: Markup(markdown(input))
|
||||
env.filters['no_paragraph'] = lambda input: Markup(re.sub(r"</?p>", '', input))
|
||||
|
||||
env.globals['unique_id'] = contextfunction(lambda ctx: str(next(ctx['unique_ctr'])))
|
||||
|
||||
|
||||
env.globals.update(load_yml_file('site.yml'))
|
||||
|
||||
|
||||
env.globals['navigation'] = ['tutorial', 'download', 'manual']
|
||||
|
||||
def generate_file(env, fname='content/1.tutorial/default.yml'):
|
||||
path, base = os.path.split(fname)
|
||||
path = os.path.relpath(path, 'content')
|
||||
output_dir = os.path.join('output', path)
|
||||
output_path = os.path.join(output_dir, 'index.html')
|
||||
|
||||
template_name = re.sub(r".yml$", '.html.j2', base)
|
||||
|
||||
ctx = load_yml_file(fname)
|
||||
ctx.update(unique_ctr=itertools.count(1), permalink=path)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
env.get_template(template_name).stream(ctx).dump(output_path, encoding='utf-8')
|
||||
|
||||
|
||||
def copy_public_files(root=''):
|
||||
for f in os.scandir(os.path.join('public', root)):
|
||||
src = os.path.join(root, f.name)
|
||||
dst = os.path.join('output', src)
|
||||
if f.is_dir():
|
||||
os.makedirs(dst, exist_ok=True)
|
||||
copy_public_files(src)
|
||||
else:
|
||||
shutil.copyfile(f.path, dst)
|
||||
|
||||
copy_public_files()
|
||||
|
||||
for fn in glob.glob('content/**/*.yml', recursive=True):
|
||||
generate_file(env, fn)
|
||||
@@ -180,14 +180,13 @@ body:
|
||||
|
||||
#### Building the documentation
|
||||
|
||||
jq's documentation is compiled into static HTML using
|
||||
[Bonsai](http://www.tinytree.info). To view the documentation
|
||||
locally, run `rake serve` (or `bundle exec rake serve`) from the
|
||||
docs/ subdirectory. To build the docs just `rake build` from the
|
||||
docs subdirectory. You'll need a few Ruby dependencies, which can
|
||||
be installed by following the instructions in `docs/README.md`.
|
||||
jq's documentation is compiled into static HTML using Python.
|
||||
To build the docs, run `pipenv run python3 build_website.py` from
|
||||
the docs/ subdirectory. To serve them locally, you can run
|
||||
`python3 -m SimpleHTTPServer`. You'll need a few Python dependencies,
|
||||
which can be installed by following the instructions in `docs/README.md`.
|
||||
|
||||
The man page is built by `make jq.1`, or just `make`, also from
|
||||
the YAML docs, and you'll still need the Ruby dependencies to
|
||||
the YAML docs, and you'll still need the Python dependencies to
|
||||
build the manpage.
|
||||
|
||||
File renamed without changes.
@@ -172,7 +172,7 @@ sections:
|
||||
ASCII output with every non-ASCII character replaced with the
|
||||
equivalent escape sequence.
|
||||
|
||||
* `--unbuffered`
|
||||
* `--unbuffered`:
|
||||
|
||||
Flush the output after each JSON object is printed (useful if
|
||||
you're piping a slow data source into jq and piping jq's
|
||||
@@ -658,10 +658,10 @@ sections:
|
||||
- **Strings** are added by being joined into a larger string.
|
||||
|
||||
- **Objects** are added by merging, that is, inserting all
|
||||
the key-value pairs from both objects into a single
|
||||
combined object. If both objects contain a value for the
|
||||
same key, the object on the right of the `+` wins. (For
|
||||
recursive merge use the `*` operator.)
|
||||
the key-value pairs from both objects into a single
|
||||
combined object. If both objects contain a value for the
|
||||
same key, the object on the right of the `+` wins. (For
|
||||
recursive merge use the `*` operator.)
|
||||
|
||||
`null` can be added to any value, and returns the other
|
||||
value unchanged.
|
||||
@@ -1975,40 +1975,40 @@ sections:
|
||||
|
||||
jq provides a few SQL-style operators.
|
||||
|
||||
* INDEX(stream; index_expression):
|
||||
* INDEX(stream; index_expression):
|
||||
|
||||
This builtin produces an object whose keys are computed by
|
||||
the given index expression applied to each value from the
|
||||
given stream.
|
||||
This builtin produces an object whose keys are computed by
|
||||
the given index expression applied to each value from the
|
||||
given stream.
|
||||
|
||||
* JOIN($idx; stream; idx_expr; join_expr):
|
||||
* JOIN($idx; stream; idx_expr; join_expr):
|
||||
|
||||
This builtin joins the values from the given stream to the
|
||||
given index. The index's keys are computed by applying the
|
||||
given index expression to each value from the given stream.
|
||||
An array of the value in the stream and the corresponding
|
||||
value from the index is fed to the given join expression to
|
||||
produce each result.
|
||||
This builtin joins the values from the given stream to the
|
||||
given index. The index's keys are computed by applying the
|
||||
given index expression to each value from the given stream.
|
||||
An array of the value in the stream and the corresponding
|
||||
value from the index is fed to the given join expression to
|
||||
produce each result.
|
||||
|
||||
* JOIN($idx; stream; idx_expr):
|
||||
* JOIN($idx; stream; idx_expr):
|
||||
|
||||
Same as `JOIN($idx; stream; idx_expr; .)`.
|
||||
Same as `JOIN($idx; stream; idx_expr; .)`.
|
||||
|
||||
* JOIN($idx; idx_expr):
|
||||
* JOIN($idx; idx_expr):
|
||||
|
||||
This builtin joins the input `.` to the given index, applying
|
||||
the given index expression to `.` to compute the index key.
|
||||
The join operation is as described above.
|
||||
This builtin joins the input `.` to the given index, applying
|
||||
the given index expression to `.` to compute the index key.
|
||||
The join operation is as described above.
|
||||
|
||||
* IN(s):
|
||||
* IN(s):
|
||||
|
||||
This builtin outputs `true` if `.` appears in the given
|
||||
stream, otherwise it outputs `false`.
|
||||
This builtin outputs `true` if `.` appears in the given
|
||||
stream, otherwise it outputs `false`.
|
||||
|
||||
* IN(source; s):
|
||||
* IN(source; s):
|
||||
|
||||
This builtin outputs `true` if any value in the source stream
|
||||
appears in the second stream, otherwise it outputs `false`.
|
||||
This builtin outputs `true` if any value in the source stream
|
||||
appears in the second stream, otherwise it outputs `false`.
|
||||
|
||||
- title: "`builtins`"
|
||||
body: |
|
||||
@@ -2230,6 +2230,7 @@ sections:
|
||||
STRING | FILTER( [REGEX, FLAGS] )
|
||||
|
||||
where:
|
||||
|
||||
* STRING, REGEX and FLAGS are jq strings and subject to jq string interpolation;
|
||||
* REGEX, after string interpolation, should be a valid PCRE regex;
|
||||
* FILTER is one of `test`, `match`, or `capture`, as described below.
|
||||
@@ -2642,9 +2643,9 @@ sections:
|
||||
|
||||
For example, in the following expression there is a binding
|
||||
which is visible "to the right" of it, `... | .*3 as
|
||||
$times_three | [. + $times_three] | ...`, but not "to the
|
||||
$times_three | [. + $times_three] | ...`, but not "to the
|
||||
left". Consider this expression now, `... | (.*3 as
|
||||
$times_three | [.+ $times_three]) | ...`: here the binding
|
||||
$times_three | [. + $times_three]) | ...`: here the binding
|
||||
`$times_three` is _not_ visible past the closing parenthesis.
|
||||
|
||||
- title: Reduce
|
||||
@@ -2867,7 +2868,7 @@ sections:
|
||||
|
||||
Two builtins provide minimal output capabilities, `debug`, and
|
||||
`stderr`. (Recall that a jq program's output values are always
|
||||
output as JSON texts on `stdout`.) The `debug` builtin can have
|
||||
output as JSON texts on `stdout`.) The `debug` builtin can have
|
||||
application-specific behavior, such as for executables that use
|
||||
the libjq C API but aren't the jq executable itself. The `stderr`
|
||||
builtin outputs its input in raw mode to stder with no additional
|
||||
@@ -441,7 +441,7 @@ sections:
|
||||
input: 5
|
||||
output: [6]
|
||||
|
||||
- title: `length`
|
||||
- title: '`length`'
|
||||
body: |
|
||||
|
||||
The builtin function `length` gets the length of various
|
||||
@@ -462,7 +462,7 @@ sections:
|
||||
input: '[[1,2], "string", {"a":2}, null]'
|
||||
output: [2, 6, 1, 0]
|
||||
|
||||
- title: `keys`
|
||||
- title: '`keys`'
|
||||
body: |
|
||||
|
||||
The builtin function `keys`, when given an object, returns
|
||||
@@ -485,7 +485,7 @@ sections:
|
||||
input: '[42,3,35]'
|
||||
output: ['[0,1,2]']
|
||||
|
||||
- title: `has`
|
||||
- title: '`has`'
|
||||
body: |
|
||||
|
||||
The builtin function `has` returns whether the input object
|
||||
@@ -504,7 +504,7 @@ sections:
|
||||
input: '[[0,1], ["a","b","c"]]'
|
||||
output: ['[false, true]']
|
||||
|
||||
- title: `to_entries`, `from_entries`, `with_entries`
|
||||
- title: '`to_entries`, `from_entries`, `with_entries`'
|
||||
body: |
|
||||
|
||||
These functions convert between an object and an array of
|
||||
@@ -529,14 +529,14 @@ sections:
|
||||
output: ['{"KEY_a": 1, "KEY_b": 2}']
|
||||
|
||||
|
||||
- title: `select`
|
||||
- title: '`select`'
|
||||
body: |
|
||||
|
||||
The function `select(foo)` produces its input unchanged if
|
||||
`foo` returns true for that input, and produces no output
|
||||
otherwise.
|
||||
|
||||
It's useful for filtering lists: `[1,2,3] | map(select(. >= 2))`
|
||||
It's useful for filtering lists: '`[1,2,3] | map(select(. >= 2))`'
|
||||
will give you `[3]`.
|
||||
|
||||
examples:
|
||||
@@ -544,7 +544,7 @@ sections:
|
||||
input: '[1,5,3,0,7]'
|
||||
output: ['[5,3,7]']
|
||||
|
||||
- title: `empty`
|
||||
- title: '`empty`'
|
||||
body: |
|
||||
|
||||
`empty` returns no results. None at all. Not even `null`.
|
||||
@@ -559,7 +559,7 @@ sections:
|
||||
input: 'null'
|
||||
output: ['[1,2,3]']
|
||||
|
||||
- title: `map(x)`
|
||||
- title: '`map(x)`'
|
||||
body: |
|
||||
|
||||
For any filter `x`, `map(x)` will run that filter for each
|
||||
@@ -574,7 +574,7 @@ sections:
|
||||
input: '[1,2,3]'
|
||||
output: ['[2,3,4]']
|
||||
|
||||
- title: `add`
|
||||
- title: '`add`'
|
||||
body: |
|
||||
|
||||
The filter `add` takes as input an array, and produces as
|
||||
@@ -596,7 +596,7 @@ sections:
|
||||
input: '[]'
|
||||
output: ["null"]
|
||||
|
||||
- title: `range`
|
||||
- title: '`range`'
|
||||
body: |
|
||||
|
||||
The `range` function produces a range of numbers. `range(4;10)`
|
||||
@@ -612,7 +612,7 @@ sections:
|
||||
input: 'null'
|
||||
output: ['[2,3]']
|
||||
|
||||
- title: `tonumber`
|
||||
- title: '`tonumber`'
|
||||
body: |
|
||||
|
||||
The `tonumber` function parses its input as a number. It
|
||||
@@ -624,7 +624,7 @@ sections:
|
||||
input: '[1, "1"]'
|
||||
output: [1, 1]
|
||||
|
||||
- title: `tostring`
|
||||
- title: '`tostring`'
|
||||
body: |
|
||||
|
||||
The `tostring` function prints its input as a
|
||||
@@ -636,7 +636,7 @@ sections:
|
||||
input: '[1, "1", [1]]'
|
||||
output: ['"1"', '"1"', '"[1]"']
|
||||
|
||||
- title: `type`
|
||||
- title: '`type`'
|
||||
body: |
|
||||
|
||||
The `type` function returns the type of its argument as a
|
||||
@@ -648,7 +648,7 @@ sections:
|
||||
input: '[0, false, [], {}, null, "hello"]'
|
||||
output: ['["number", "boolean", "array", "object", "null", "string"]']
|
||||
|
||||
- title: `sort, sort_by`
|
||||
- title: '`sort, sort_by`'
|
||||
body: |
|
||||
|
||||
The `sort` functions sorts its input, which must be an
|
||||
@@ -680,7 +680,7 @@ sections:
|
||||
input: '[{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}]'
|
||||
output: ['[{"foo":2, "bar":1}, {"foo":3, "bar":100}, {"foo":4, "bar":10}]']
|
||||
|
||||
- title: `group_by`
|
||||
- title: '`group_by`'
|
||||
body: |
|
||||
|
||||
`group_by(.foo)` takes as input an array, groups the
|
||||
@@ -697,7 +697,7 @@ sections:
|
||||
input: '[{"foo":1, "bar":10}, {"foo":3, "bar":100}, {"foo":1, "bar":1}]'
|
||||
output: ['[[{"foo":1, "bar":10}, {"foo":1, "bar":1}], [{"foo":3, "bar":100}]]']
|
||||
|
||||
- title: `min`, `max`, `min_by`, `max_by`
|
||||
- title: '`min`, `max`, `min_by`, `max_by`'
|
||||
body: |
|
||||
|
||||
Find the minimum or maximum element of the input array. The
|
||||
@@ -713,7 +713,7 @@ sections:
|
||||
input: '[{"foo":1, "bar":14}, {"foo":2, "bar":3}]'
|
||||
output: ['{"foo":2, "bar":3}']
|
||||
|
||||
- title: `unique`
|
||||
- title: '`unique`'
|
||||
body: |
|
||||
|
||||
The `unique` function takes as input an array and produces
|
||||
@@ -725,7 +725,7 @@ sections:
|
||||
input: '[1,2,5,3,5,3,1,3]'
|
||||
output: ['[1,2,3,5]']
|
||||
|
||||
- title: `reverse`
|
||||
- title: '`reverse`'
|
||||
body: |
|
||||
|
||||
This function reverses an array.
|
||||
@@ -735,7 +735,7 @@ sections:
|
||||
input: '[1,2,3,4]'
|
||||
output: ['[4,3,2,1]']
|
||||
|
||||
- title: `contains`
|
||||
- title: '`contains`'
|
||||
body: |
|
||||
|
||||
The filter `contains(b)` will produce true if b is
|
||||
@@ -764,7 +764,7 @@ sections:
|
||||
input: '{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}'
|
||||
output: ['false']
|
||||
|
||||
- title: `recurse`
|
||||
- title: '`recurse`'
|
||||
body: |
|
||||
|
||||
The `recurse` function allows you to search through a
|
||||
@@ -796,7 +796,7 @@ sections:
|
||||
- '{"foo":[]}'
|
||||
|
||||
|
||||
- title: "String interpolation - `\(foo)`"
|
||||
- title: String interpolation - `\(foo)`
|
||||
body: |
|
||||
|
||||
Inside a string, you can put an expression inside parens
|
||||
@@ -882,7 +882,7 @@ sections:
|
||||
|
||||
- title: Conditionals and Comparisons
|
||||
entries:
|
||||
- title: `==`, `!=`
|
||||
- title: '`==`, `!=`'
|
||||
body: |
|
||||
|
||||
The expression 'a == b' will produce 'true' if the result of a and b
|
||||
@@ -931,7 +931,7 @@ sections:
|
||||
input: 2
|
||||
output: ['"many"']
|
||||
|
||||
- title: `>, >=, <=, <`
|
||||
- title: '`>, >=, <=, <`'
|
||||
body: |
|
||||
|
||||
The comparison operators `>`, `>=`, `<=`, `<` return whether
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,173 @@
|
||||
body {
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 970px;
|
||||
}
|
||||
|
||||
/* index.liquid *******************************************/
|
||||
#blurb {
|
||||
padding-top: 40px;
|
||||
}
|
||||
#blurb p {
|
||||
font-size: 1.9em;
|
||||
}
|
||||
#blurb .btn-group {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#multiblurb {
|
||||
line-height: 1.7;
|
||||
text-align: center;
|
||||
font-size: 12pt;
|
||||
}
|
||||
#multiblurb code {
|
||||
border: 0;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
#news {
|
||||
font-size: 12pt;
|
||||
}
|
||||
#news .date {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* default.liquid *****************************************/
|
||||
.tutorial-example {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.tutorial-example pre {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.tutorial-example a {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
padding: 15px 8px;
|
||||
color: #777777;
|
||||
font-weight: bold;
|
||||
line-height: 10px;
|
||||
font-size: 12px;
|
||||
border-left: 1px solid #DDDDDD;
|
||||
display: block;
|
||||
}
|
||||
.tutorial-example .accordion-body pre {
|
||||
margin: 0 4px;
|
||||
border-top: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.tutorial-example a {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/* manual.liquid ******************************************/
|
||||
section {
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
h3 code {
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
#navcolumn {
|
||||
/* Put nav column above manual content */
|
||||
position: relative !important;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
#manualcontent {
|
||||
/* Put nav column left of manual content */
|
||||
padding-left: 280px;
|
||||
}
|
||||
}
|
||||
.nav-pills {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.nav-pills li a {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.manual-example table {
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
.manual-example table td {
|
||||
white-space: pre-wrap;
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
}
|
||||
.manual-example table td.jqprogram {
|
||||
font-weight: bold;
|
||||
}
|
||||
.manual-example table th {
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
#navcolumn {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.manual-example {
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.jqplay-btn {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
/* shared/_footer.liquid **********************************/
|
||||
footer {
|
||||
background-color: #F5F5F5;
|
||||
padding: 20px 0;
|
||||
margin-top: 40px;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
}
|
||||
footer p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
/* typeahead **********************************************/
|
||||
.twitter-typeahead {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tt-menu {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 8px 0;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
-webkit-border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.tt-suggestion {
|
||||
padding: 3px 20px;
|
||||
}
|
||||
.tt-suggestion:hover {
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
background-color: #446e9b;
|
||||
}
|
||||
.tt-suggestion.tt-cursor {
|
||||
color: #fff;
|
||||
background-color: #446e9b;
|
||||
}
|
||||
.tt-suggestion p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,26 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/navbar" %}
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<h1>{{headline}}</h1>
|
||||
{% for item in body %}
|
||||
{% if item.text %}
|
||||
{{ item.text | replace: '$JQ_VERSION', jq_version | markdownify }}
|
||||
{{ item.text | replace('$JQ_VERSION', jq_version) | markdownify }}
|
||||
{% endif %}
|
||||
|
||||
{% if item.command %}
|
||||
{% capture resultID %}{{ "result" | unique}}{% endcapture %}
|
||||
{% set resultID = unique_id() %}
|
||||
<div class="tutorial-example">
|
||||
<div class="accordion-heading">
|
||||
<pre>{{item.command}}</pre>
|
||||
<a data-toggle="collapse" href="#{{resultID}}">Show result</a>
|
||||
<a data-toggle="collapse" href="#result{{resultID}}">Show result</a>
|
||||
</div>
|
||||
<div id="{{resultID}}" class="accordion-body collapse">
|
||||
<div id="result{{resultID}}" class="accordion-body collapse">
|
||||
<pre>{{item.result}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,6 +29,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "shared/footer" %}
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/navbar" %}
|
||||
<body id="{{ slug }}">
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@@ -27,7 +27,7 @@
|
||||
<li><a href="https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64">Linux (64-bit)</a></li>
|
||||
<li><a href="https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64">OS X (64-bit)</a></li>
|
||||
<li><a href="https://github.com/stedolan/jq/releases/download/jq-1.6/jq-win64.exe">Windows (64-bit)</a></li>
|
||||
<li><a href="/jq/download/">Other platforms, older versions, and source</a></li>
|
||||
<li><a href="{{root}}/download/">Other platforms, older versions, and source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -68,6 +68,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "shared/footer" %}
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
</body>
|
||||
</html>
|
||||
+16
-16
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body id="{{slug}}" data-spy="scroll" data-target="#navcolumn" data-offset="100">
|
||||
{% include "shared/navbar" %}
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@@ -32,41 +32,41 @@
|
||||
{% for section in sections %}
|
||||
<section id="{{section.title | section_id}}">
|
||||
<h2>{{section.title}}</h2>
|
||||
{{section.body | markdownify}}
|
||||
{{ (section.body | markdownify) if section.body }}
|
||||
{% for entry in section.entries %}
|
||||
<section id="{{entry.title | entry_id}}">
|
||||
<h3>
|
||||
{{entry.title | markdownify | no_paragraph}}
|
||||
{{entry.title | markdownify | no_paragraph }}
|
||||
{% if entry.subtitle %}<small>{{entry.subtitle}}</small>{% endif %}
|
||||
</h3>
|
||||
{{entry.body | markdownify}}
|
||||
|
||||
{% if entry.examples %}
|
||||
<div>
|
||||
{% capture exampleID %}{{ "" | unique }}{% endcapture %}
|
||||
{% set exampleID = unique_id() %}
|
||||
<a data-toggle="collapse" href="#example{{exampleID}}">
|
||||
<i class="glyphicon glyphicon-chevron-right"></i>
|
||||
{% if entry.examples[1] %}Examples{%else%}Example{%endif%}
|
||||
{% if entry.examples | length > 1 %}Examples{%else%}Example{%endif%}
|
||||
</a>
|
||||
<div id="example{{exampleID}}" class="manual-example collapse">
|
||||
{% for example in entry.examples %}
|
||||
<table>
|
||||
<tr><th></th><td class="jqprogram">jq '{{example.program | escape}}'</td></tr>
|
||||
<tr><th>Input</th><td>{{example.input | escape}}</td></tr>
|
||||
{% unless example.output[0] %}
|
||||
<tr><th></th><td class="jqprogram">jq '{{ example.program }}'</td></tr>
|
||||
<tr><th>Input</th><td>{{ example.input }}</td></tr>
|
||||
{% if not example.output[0] %}
|
||||
<tr>
|
||||
<th>Output</th>
|
||||
<td><i>none</i></td>
|
||||
</tr>
|
||||
{% endunless %}
|
||||
{% endif %}
|
||||
{% for output in example.output %}
|
||||
<tr>
|
||||
{% if forloop.index == 1 %}
|
||||
{% if loop.first %}
|
||||
<th>Output</th>
|
||||
{% else %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
<td>{{output | escape}}</td>
|
||||
<td>{{ output }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
@@ -82,15 +82,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "shared/footer" %}
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
<script>
|
||||
var section_map = {
|
||||
{% for section in sections %}
|
||||
{% for entry in section.entries %}
|
||||
{{entry.title | search_id | json}} : {{entry.title | entry_id | json}},
|
||||
{{entry.title | search_id | tojson }} : {{entry.title | entry_id | tojson }},
|
||||
{% endfor %}
|
||||
{{section.title | search_id | json}} : {{section.title | section_id | json}}
|
||||
{% unless forloop.last %},{% endunless %}
|
||||
{{section.title | search_id | tojson }} : {{section.title | section_id | tojson }}
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
};
|
||||
</script>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>This website is made with <a href="http://www.tinytree.info">Bonsai</a> and <a href="http://getbootstrap.com">Bootstrap</a>, themed with <a href="https://bootswatch.com">Bootswatch</a>.</p>
|
||||
<p>This website is made with <a href="http://getbootstrap.com">Bootstrap</a>, themed with <a href="https://bootswatch.com">Bootswatch</a>.</p>
|
||||
<p>jq is licensed under the MIT license (code) and the <a href="https://creativecommons.org/licenses/by/3.0/">CC-BY-3.0</a> license (docs).</p>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -7,9 +7,9 @@
|
||||
<title>{{headline}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<link rel="canonical" href="{{url}}{{permalink | remove:'/index'}}" />
|
||||
<link rel="canonical" href="{{ url }}{{ permalink | replace('/index','') }}" />
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/spacelab/bootstrap.min.css" rel="stylesheet" integrity="sha256-j7Dtnd7ZjexEiPNbscbopFn9+Cs0b3TLipKsWAPHZIM= sha512-RFhfi6P8zWMAJrEGU+CPjuxPh3r/UUBGqQ+/o6WKPIVZmQqeOipGotH2ihRULuQ8wsMBoK15TSZqc/7VYWyuIw==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{{root}}/css/base.css" type="text/css">
|
||||
<link rel="stylesheet" href="{{ root }}/css/base.css" type="text/css">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
+2
-2
@@ -13,8 +13,8 @@
|
||||
<div class="navbar-collapse collapse" id="nav-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
{% for item in navigation %}
|
||||
<li {% if item.permalink == permalink %} class="active" {% endif %}>
|
||||
<a href="{{root}}{{item.permalink}}">{{item.name}}</a>
|
||||
<li {% if item == permalink %} class="active" {% endif %}>
|
||||
<a href="{{root}}/{{item}}">{{item | capitalize}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li><a href="https://github.com/stedolan/jq/issues">Issues</a></li>
|
||||
@@ -11,7 +11,7 @@ set -o xtrace
|
||||
scriptdir=`dirname "$0"`
|
||||
cd "$scriptdir"/../docs
|
||||
rm -rf output
|
||||
rake build
|
||||
pipenv run python3 build_website.py
|
||||
cd ..
|
||||
|
||||
# copy to /tmp
|
||||
|
||||
@@ -1344,8 +1344,13 @@ int jv_contains(jv a, jv b) {
|
||||
} else if (jv_get_kind(a) == JV_KIND_ARRAY) {
|
||||
r = jv_array_contains(jv_copy(a), jv_copy(b));
|
||||
} else if (jv_get_kind(a) == JV_KIND_STRING) {
|
||||
r = _jq_memmem(jv_string_value(a), jv_string_length_bytes(jv_copy(a)),
|
||||
jv_string_value(b), jv_string_length_bytes(jv_copy(b))) != 0;
|
||||
int b_len = jv_string_length_bytes(jv_copy(b));
|
||||
if (b_len != 0) {
|
||||
r = _jq_memmem(jv_string_value(a), jv_string_length_bytes(jv_copy(a)),
|
||||
jv_string_value(b), b_len) != 0;
|
||||
} else {
|
||||
r = 1;
|
||||
}
|
||||
} else {
|
||||
r = jv_equal(jv_copy(a), jv_copy(b));
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@
|
||||
. "${0%/*}/setup" "$@"
|
||||
|
||||
# We set PAGER because there's a mantest for `env` that uses it.
|
||||
(cd $JQBASEDIR/docs && rake mantests) |
|
||||
(cd $JQBASEDIR/docs && pipenv run python3 build_mantests.py) |
|
||||
env PAGER=less $VALGRIND $Q $JQ -L "$mods" --run-tests
|
||||
Reference in new issue
Block a user