mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Documentation. Copious.
This commit is contained in:
6
docs/.gitignore
vendored
Normal file
6
docs/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.DS_Store
|
||||
.sass-cache
|
||||
output/*
|
||||
|
||||
# Autogenerated from public/css/base.scss
|
||||
public/css/base.css
|
54
docs/Rakefile
Normal file
54
docs/Rakefile
Normal file
@ -0,0 +1,54 @@
|
||||
require 'bonsai'
|
||||
require 'liquid'
|
||||
require 'maruku'
|
||||
require 'json'
|
||||
|
||||
module ExtraFilters
|
||||
def markdownify(input)
|
||||
Maruku.new(input).to_html
|
||||
end
|
||||
|
||||
def sanitize(input)
|
||||
input.gsub(/[^a-zA-Z0-9_]/,"")
|
||||
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)
|
||||
|
||||
|
||||
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 {
|
||||
use Bonsai::StaticPassThrough, :root => Bonsai.root_dir + "/output", :urls => ["/"]
|
||||
run Bonsai::DevelopmentServer
|
||||
}
|
||||
Rack::Handler.default.run(app, :Port => 5000) do
|
||||
Launchy.open("http://localhost:5000/")
|
||||
end
|
||||
}
|
||||
Watch.new("{content,templates,public}/**/*") { Bonsai::Exporter.process! }
|
||||
rescue Interrupt
|
||||
Process.kill("QUIT", server)
|
||||
Process.wait(server)
|
||||
exit
|
||||
end
|
||||
end
|
239
docs/content/1.tutorial/default.yml
Normal file
239
docs/content/1.tutorial/default.yml
Normal file
@ -0,0 +1,239 @@
|
||||
headline: Tutorial
|
||||
body:
|
||||
- text: |
|
||||
|
||||
Twitter have a JSON API, so let's play with that. This URL gets
|
||||
us the last 5 tweets about JSON:
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true'"
|
||||
result: |
|
||||
{"completed_in":0.108,"max_id":247677287108067328,"max_id_str":"247677287108067328","next_page":"?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1","page":1,"query":"json","refresh_url":"?since_id=247677287108067328&q=json&include_entities=1","results":[{"created_at":"Mon, 17 Sep 2012 12:44:01 +0000","entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/XRvh1ZVw","expanded_url":"http:\/\/jase.im\/Ri7I0M","display_url":"jase.im\/Ri7I0M","indices":[112,132]}],"user_mentions":[{"screen_name":"imagemechanics","name":"Jason Cotterell","id":57271393,"id_str":"57271393","indices":[3,18]}]},"from_user":"_AaronNg","from_user_id":79771704,"from_user_id_str":"79771704","from_user_name":"NgChenChong","geo":null,"id":247677287108067328,"id_str":"247677287108067328","iso_language_code":"en","metadata":{"result_type":"recent"},"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","source":"<a href="http:\/\/twitter.com\/">web<\/a>","text":"RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp:\/\/t.co\/XRvh1ZVw","to_user":null,"to_user_id":0,"to_user_id_str":"0","to_user_name":null}, ...
|
||||
|
||||
- text: |
|
||||
|
||||
There's lots of info and no whitespace, so to make it a bit more
|
||||
legible we pipe it through jq, telling jq to just spit the input
|
||||
back at us using the expression `.`:
|
||||
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.'"
|
||||
result: |
|
||||
|
||||
{
|
||||
"since_id_str": "0",
|
||||
"since_id": 0,
|
||||
"results_per_page": 5,
|
||||
"completed_in": 0.108,
|
||||
"max_id": 247677287108067330,
|
||||
"max_id_str": "247677287108067328",
|
||||
"next_page": "?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1",
|
||||
"page": 1,
|
||||
"query": "json",
|
||||
"refresh_url": "?since_id=247677287108067328&q=json&include_entities=1",
|
||||
"results": [
|
||||
{
|
||||
"from_user_name": "NgChenChong",
|
||||
"from_user_id_str": "79771704",
|
||||
"from_user_id": 79771704,
|
||||
"from_user": "_AaronNg",
|
||||
"iso_language_code": "en",
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"to_user": null
|
||||
/* lots more fields... */
|
||||
},
|
||||
/* lots more results... */
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
Let's pull out the first tweet:
|
||||
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.results[0]'"
|
||||
result: |
|
||||
{
|
||||
"from_user_name": "NgChenChong",
|
||||
"from_user_id_str": "79771704",
|
||||
"from_user_id": 79771704,
|
||||
"from_user": "_AaronNg",
|
||||
"iso_language_code": "en",
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"to_user": null
|
||||
/* lots more fields... */
|
||||
},
|
||||
|
||||
- text: |
|
||||
|
||||
For the rest of the examples, I'll leave out the `curl` command - it's not going to change.
|
||||
|
||||
|
||||
There's still a lot of info we don't care about there, so we'll
|
||||
restrict it down to the most interesting fields.
|
||||
|
||||
|
||||
- command: "jq '.results[0] | {from_user, text}'"
|
||||
result: |
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
|
||||
- text: |
|
||||
|
||||
The `|` operator in jq feeds the output of one filter
|
||||
(`.results[0]` which gets the first element of the results
|
||||
array) into the input of another (`{from_user, text}` which
|
||||
builds an object of those two fields).
|
||||
|
||||
Now let's get the rest of the tweets:
|
||||
|
||||
|
||||
|
||||
- command: "jq '.results[] | {from_user, text}'"
|
||||
result: |
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
{
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
}
|
||||
{
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
}
|
||||
{
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
}
|
||||
{
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
`.results[]` returns each element of the results array, one at a
|
||||
time, which are all fed into `{from_user, text}`.
|
||||
|
||||
|
||||
Data in jq is represented as streams of JSON values - every jq
|
||||
expression runs for each value in its input stream, and can
|
||||
produce any number of values to its output stream.
|
||||
|
||||
Streams are serialised by just separating JSON values with
|
||||
whitespace. This is a `cat`-friendly format - you can just join
|
||||
two JSON streams together and get a valid JSON stream.
|
||||
|
||||
If you want to get the output as a single array, you can tell jq to
|
||||
"collect" all of the answers by wrapping the filter in square
|
||||
brackets:
|
||||
|
||||
- command: "jq '[.results[] | {from_user, text}]'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
},
|
||||
{
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
},
|
||||
{
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
},
|
||||
{
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
},
|
||||
{
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
Next, let's try getting the URLs out of those API results as
|
||||
well. In each tweet, the Twitter API includes a field called
|
||||
"entities" which looks like this:
|
||||
|
||||
{
|
||||
"user_mentions": [],
|
||||
"urls": [{
|
||||
"indices": [83, 103],
|
||||
"display_url": "bit.ly/StniqT",
|
||||
"expanded_url": "http://bit.ly/StniqT",
|
||||
"url": "http://t.co/28Jesbio"
|
||||
}],
|
||||
"hashtags": [
|
||||
{"indices": [108, 114], "text": "Apple" },
|
||||
{"indices": [121, 129], "text": "Awesome"}
|
||||
]
|
||||
}
|
||||
|
||||
We want to pull out all of the "url" fields inside that array of url
|
||||
objects, and make a simple list of strings to go along with the
|
||||
"from_user" and "text" fields we already have.
|
||||
|
||||
|
||||
|
||||
- command: "jq '.results[] | {from_user, text, urls: [.entities.urls[].url]}'"
|
||||
result: |
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/XRvh1ZVw"
|
||||
],
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/Lhp92IqD"
|
||||
],
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/7KALdWaX"
|
||||
],
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/28Jesbio"
|
||||
],
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/M70snaIf"
|
||||
],
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
Here we're making an object as before, but this time the urls
|
||||
field is being set to `[.entities.urls[].url]`, which collects
|
||||
all of the URLs defined in the entities object.
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
asdf
|
52
docs/content/2.download/default.yml
Normal file
52
docs/content/2.download/default.yml
Normal file
@ -0,0 +1,52 @@
|
||||
headline: Download jq
|
||||
body:
|
||||
|
||||
- text: |
|
||||
|
||||
jq is written in C and has no runtime dependencies, so it should be
|
||||
possible to build it for nearly any platform. Prebuilt binaries are
|
||||
available for Linux (64-bit x86) and OS X.
|
||||
|
||||
* [Download binary for 64-bit Linux](/download/linux/x68_64/jq)
|
||||
* [Download binary for OS X](/download/osx/64/jq)
|
||||
* [Download source](/download/source/jq.tgz)
|
||||
|
||||
jq is licensed under the MIT license. For all of the gory
|
||||
details, read the file `COPYING` in the source distribution.
|
||||
|
||||
Hacking on jq
|
||||
=============
|
||||
|
||||
If you want to work on jq, grab the source from
|
||||
[https://github.com/stedolan/jq](https://github.com/stedolan/jq).
|
||||
|
||||
|
||||
To build it from a git clone, you'll need to install a few
|
||||
packages first:
|
||||
|
||||
* [Flex](http://www.gnu.org/software/flex/)
|
||||
* [Bison](http://www.gnu.org/software/bison/)
|
||||
* [Python](http://www.python.org)
|
||||
* [GCC](http://gcc.gnu.org)
|
||||
* [Make](http://www.gnu.org/software/make)
|
||||
|
||||
Most of these aren't necessary if you're just trying to compile
|
||||
jq from the released tarball - that version has the
|
||||
non-platform-specific build steps already done, so you'll only
|
||||
need a C compiler and `make` to finish it off.
|
||||
|
||||
For Linux systems, these will all be in your system's package
|
||||
manager, and if you do development on the machine they're most
|
||||
likely already installed. I have no idea how to get these
|
||||
installed on OS X, you're on your own there.
|
||||
|
||||
`flex` and `bison` are used to generate the lexer and parser for
|
||||
jq, and some python scripts generate the UTF8 encoding tables
|
||||
needed for JSON parsing.
|
||||
|
||||
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` from the docs/ subdirectory.
|
688
docs/content/3.manual/manual.yml
Normal file
688
docs/content/3.manual/manual.yml
Normal file
@ -0,0 +1,688 @@
|
||||
headline: jq Manual
|
||||
sections:
|
||||
- title: Basics
|
||||
body: "{ some *intro* text \n\n\n}\n"
|
||||
entries:
|
||||
- title: "`.`"
|
||||
body: |
|
||||
|
||||
The absolute simplest (and least interesting) jq expression
|
||||
is `.`. This is a jq expression that takes its input and
|
||||
produces it unchanged as output.
|
||||
|
||||
Since jq by default pretty-prints all output, this trivial
|
||||
program can be a useful way of formatting JSON output from,
|
||||
say, `curl`.
|
||||
|
||||
examples:
|
||||
- program: '.'
|
||||
input: '"Hello, world!"'
|
||||
output: ['"Hello, world!"']
|
||||
|
||||
- title: "`.foo`"
|
||||
body: |
|
||||
|
||||
The simplest *useful* jq expression is .foo. When given a
|
||||
JSON object (aka dictionary or hash) as input, it produces
|
||||
the value at the key "foo", or null if there\'s none present.
|
||||
|
||||
examples:
|
||||
- program: '.foo'
|
||||
input: '{"foo": 42, "bar": "less interesting data"}'
|
||||
output: [42]
|
||||
- program: '.foo'
|
||||
input: '{"notfoo": true, "alsonotfoo": false}'
|
||||
output: ['null']
|
||||
|
||||
- title: "`.[foo]`"
|
||||
body: |
|
||||
|
||||
You can also look up fields of an object using syntax like
|
||||
`.["foo"]` (.foo above is a shorthand version of this). This
|
||||
one works for arrays as well, if the key is an
|
||||
integer. Arrays are zero-based (like javascript), so .[2]
|
||||
returns the third element of the array.
|
||||
|
||||
examples:
|
||||
- program: '.[0]'
|
||||
input: '[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]'
|
||||
output: ['{"name":"JSON", "good":true}']
|
||||
|
||||
- program: '.[2]'
|
||||
input: '[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]'
|
||||
output: ['null']
|
||||
|
||||
- title: "`.[]`"
|
||||
body: |
|
||||
|
||||
If you use the `.[foo]` syntax, but omit the index
|
||||
entirely, it will return *all* of the elements of an
|
||||
array. Running `.[]` with the input `[1,2,3]` will produce the
|
||||
numbers as three seperate results, rather than as a single
|
||||
array.
|
||||
|
||||
examples:
|
||||
- program: '.[]'
|
||||
input: '[{name":"JSON", "good":true}, {"name":"XML", "good":false}]'
|
||||
output:
|
||||
- '{"name":"JSON", "good":true}'
|
||||
- '{"name":"XML", "good":false}'
|
||||
|
||||
- program: '.[]'
|
||||
input: '[]'
|
||||
output: []
|
||||
|
||||
- title: "`,`"
|
||||
body: |
|
||||
|
||||
If two jq expressions are separated by a comma, then the
|
||||
input will be fed into both and there will be multiple
|
||||
outputs: first, all of the outputs produced by the left
|
||||
expression, and then all of the outputs produced by the
|
||||
right. For instance, jq expression `.foo, .bar`, produces
|
||||
both the "foo" fields and "bar" fields as separate outputs.
|
||||
|
||||
examples:
|
||||
- program: '.foo, .bar'
|
||||
input: '{"foo": 42, "bar": "something else", "baz": true}'
|
||||
output: ['42', '"something else"']
|
||||
|
||||
- program: "[.user, .projects[]]"
|
||||
input: '{"user":"stedolan", "projects": ["jq", "wikiflow"]}'
|
||||
output: ['"stedolan"', '"jq"', '"wikiflow"']
|
||||
|
||||
- program: '.[4,2]'
|
||||
input: '["a","b","c","d","e"]'
|
||||
output: ['"d"', '"c"']
|
||||
|
||||
- title: "`|`"
|
||||
body: |
|
||||
The | operator combines two jq expressions by feeding the output(s) of
|
||||
the one on the left into the input of the one on the right. It\'s
|
||||
pretty much the same as the Unix shell\'s pipe, if you\'re used to
|
||||
that.
|
||||
|
||||
If the one on the left produces multiple results, the one on
|
||||
the right will be run for each of those results. So, the
|
||||
expression `.[] | .foo` retrieves the "foo" field of each
|
||||
element of the input array.
|
||||
|
||||
examples:
|
||||
- program: '.[] | .name'
|
||||
input: '[{name":"JSON", "good":true}, {"name":"XML", "good":false}]'
|
||||
output: ['"JSON"', '"XML"']
|
||||
|
||||
- title: Types and Values
|
||||
body: |
|
||||
|
||||
jq supports the same set of datatypes as JSON - numbers,
|
||||
strings, booleans, arrays, objects (which in JSON-speak are
|
||||
hashes with only string keys), and "null".
|
||||
|
||||
Booleans, null, strings and numbers are written the same way as
|
||||
in javascript. Just like everything else in jq, these simple
|
||||
values take an input and produce an output - `42` is a valid jq
|
||||
expression that takes an input, ignores it, and returns 42
|
||||
instead.
|
||||
|
||||
entries:
|
||||
- title: Array construction - `[]`
|
||||
body: |
|
||||
|
||||
As in JSON, `[]` is used to construct arrays, as in
|
||||
`[1,2,3]`. The elements of the arrays can be any jq
|
||||
expression. All of the results produced by all of the
|
||||
expressions are collected into one big array. You can use it
|
||||
to construct an array out of a known quantity of values (as
|
||||
in `[.foo, .bar, .baz]`) or to "collect" all the results of a
|
||||
jq expression into an array (as in `[.items[].name]`)
|
||||
|
||||
Once you understand the "," operator, you can look at jq\'s array
|
||||
syntax in a different light: the expression [1,2,3] is not using a
|
||||
built-in syntax for comma-separated arrays, but is instead applying
|
||||
the `[]` operator (collect results) to the expression 1,2,3 (which
|
||||
produces three different results).
|
||||
|
||||
If you have a jq expression `X` that produces four results,
|
||||
then the expression `[X]` will produce a single result, an
|
||||
array of four elements.
|
||||
|
||||
examples:
|
||||
- program: "[.user, .projects[]]"
|
||||
input: '{"user":"stedolan", "projects": ["jq", "wikiflow"]}'
|
||||
output: ['["stedolan", "jq", "wikiflow"]']
|
||||
- title: Objects - `{}`
|
||||
body: |
|
||||
|
||||
Like JSON, `{}` is for constructing objects (aka
|
||||
dictionaries or hashes), as in: `{"a": 42, "b": 17}`.
|
||||
|
||||
If the keys are "sensible" (all alphabetic characters), then
|
||||
the quotes can be left off. The value can be any expression
|
||||
(although you may need to wrap it in parentheses if it\'s a
|
||||
complicated one), which gets applied to the {} expression\'s
|
||||
input (remember, all jq expressions have an input and an
|
||||
output).
|
||||
|
||||
{foo: .bar}
|
||||
|
||||
will produce the JSON object `{"foo": 42}` if given the JSON
|
||||
object `{"bar":42, "baz":43}`. You can use this to select
|
||||
particular fields of an object: if the input is an object
|
||||
with "user", "title", "id", and "content" fields and you
|
||||
just want "user" and "title", you can write
|
||||
|
||||
{user: .user, title: .title}
|
||||
|
||||
Because that\'s so common, there\'s a shortcut syntax: `{user, title}`.
|
||||
|
||||
If one of the expressions produces multiple results,
|
||||
multiple dictionaries will be produced. If the input\'s
|
||||
|
||||
{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
|
||||
|
||||
then the expression
|
||||
|
||||
{user, title: .titles[]}
|
||||
|
||||
will produce two outputs:
|
||||
|
||||
{"user":"stedolan", "title": "JQ Primer"}
|
||||
{"user":"stedolan", "title": "More JQ"}
|
||||
|
||||
Putting parentheses around the key means it will be evaluated as an
|
||||
expression. With the same input as above,
|
||||
|
||||
{(.user): .titles}
|
||||
|
||||
produces
|
||||
|
||||
{"stedolan": ["JQ Primer", "More JQ"]}
|
||||
|
||||
examples:
|
||||
- program: '{user, title: .titles[]}'
|
||||
input: '{"user":"stedolan","titles":["JQ Primer", "More JQ"]}'
|
||||
output:
|
||||
- '{"user":"stedolan", "title": "JQ Primer"}'
|
||||
- '{"user":"stedolan", "title": "More JQ"}'
|
||||
- program: '{(.user): .titles}'
|
||||
input: '{"user":"stedolan","titles":["JQ Primer", "More JQ"]}'
|
||||
output: ['{"stedolan": ["JQ Primer", "More JQ"]}']
|
||||
|
||||
- title: Builtin operators and functions
|
||||
body: |
|
||||
|
||||
Some jq operator (for instance, `+`) do different things
|
||||
depending on the type of their arguments (arrays, numbers,
|
||||
etc.). However, jq never does implicit type conversions. If you
|
||||
try to add a string to an object you'll get an error message and
|
||||
no result.
|
||||
|
||||
entries:
|
||||
- title: Addition - `+`
|
||||
body: |
|
||||
|
||||
The operator `+` takes two jq expressions, applies them both
|
||||
to the same input, and adds the results together. What
|
||||
"adding" means depends on the types involved:
|
||||
|
||||
- **Numbers** are added by normal arithmetic.
|
||||
|
||||
- **Arrays** are added by being concatenated into a larger array.
|
||||
|
||||
- **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.
|
||||
|
||||
examples:
|
||||
- program: '.a + 1'
|
||||
input: '{"a": 7}'
|
||||
output: '{"a": 8}'
|
||||
- program: '.a + .b'
|
||||
input: '{"a": [1,2], "b": [3,4]}'
|
||||
output: ['[1,2,3,4]']
|
||||
- program: '{a: 1} + {b: 2} + {c: 3} + {a: 42}'
|
||||
input: 'null'
|
||||
output: ['{"a": 42, "b": 2, "c": 3}']
|
||||
|
||||
- title: Subtraction - `-`
|
||||
body: |
|
||||
|
||||
As well as normal arithmetic subtraction on numbers, the `-`
|
||||
operator can be used on arrays to remove all occurences of
|
||||
the second array's elements from the first array.
|
||||
|
||||
examples:
|
||||
- program: '4 - .a'
|
||||
input: '{"a":3}'
|
||||
output: ['1']
|
||||
- program: . - ["xml", "yaml"]
|
||||
input: '["xml", "yaml", "json"]'
|
||||
output: ['["json"]']
|
||||
|
||||
- title: Multiplication, division - `*` and `/`
|
||||
body: |
|
||||
|
||||
These operators only work on numbers, and do the expected.
|
||||
|
||||
examples:
|
||||
- program: '10 / . * 3'
|
||||
input: 5
|
||||
output: [6]
|
||||
|
||||
- title: `length`
|
||||
body: |
|
||||
|
||||
The builtin function `length` gets the length of various
|
||||
different types of value:
|
||||
|
||||
- The length of a **string** is the number of Unicode
|
||||
codepoints it contains (which will be the same as its
|
||||
JSON-encoded length in bytes if it's pure ASCII).
|
||||
|
||||
- The length of an **array** is the number of elements.
|
||||
|
||||
- The length of an **object** is the number of key-value pairs.
|
||||
|
||||
- The length of **null** is zero.
|
||||
|
||||
examples:
|
||||
- program: '.[] | length'
|
||||
input: '[[1,2], "string", {"a":2}, null]'
|
||||
output: [2, 6, 1, 0]
|
||||
|
||||
- title: `tonumber`
|
||||
body: |
|
||||
|
||||
The `tonumber` function parses its input as a number. It
|
||||
will convert correctly-formatted strings to their numeric
|
||||
equivalent, leave numbers alone, and give an error on all other input.
|
||||
|
||||
examples:
|
||||
- program: '.[] | tonumber'
|
||||
input: '[1, "1"]'
|
||||
output: [1,1]
|
||||
|
||||
- title: `tostring`
|
||||
body: |
|
||||
|
||||
The `tostring` function prints its input as a
|
||||
string. Strings are left unchanged, and all other values are
|
||||
JSON-encoded.
|
||||
|
||||
examples:
|
||||
- program: '.[] | tostring'
|
||||
input: '[1, "1", [1]]'
|
||||
output: ['"1"', '"1"', '"[1]"']
|
||||
|
||||
- title: "String interpolation - `@(text)`"
|
||||
body: |
|
||||
|
||||
jq supports an alternative syntax for strings. Instead of
|
||||
"foo", you can write `@(foo)`. When using this syntax,
|
||||
`%(expression)` may be used to insert the value of
|
||||
`expression` into the string (converted with `tostring`).
|
||||
|
||||
String interpolation does not occur for normal double-quoted
|
||||
strings (like `"foo"`) in order to be fully compatible with
|
||||
JSON.
|
||||
|
||||
All of the usual JSON escapes (`\n`, `\r` and the like) work
|
||||
inside `@()`-quoted strings, as well as `\%` and `\)` if
|
||||
those characters are needed literally.
|
||||
|
||||
examples:
|
||||
- program: '@(The input was %(.), which is one less than %(.+1))'
|
||||
input: '42'
|
||||
output: ['"The input was 42, which is one less than 43"']
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- title: Conditionals and Comparisons
|
||||
entries:
|
||||
- title: `==`, `!=`
|
||||
body: |
|
||||
|
||||
The expression 'a == b' will produce 'true' if the result of a and b
|
||||
are equal (that is, if they represent equivalent JSON documents) and
|
||||
'false' otherwise. In particular, strings are never considered equal
|
||||
to numbers. If you're coming from Javascript, jq's == is like
|
||||
Javascript's === - considering values equal only when they have the
|
||||
same type as well as the same value.
|
||||
|
||||
!= is "not equal", and 'a != b' returns the opposite value of 'a == b'
|
||||
|
||||
examples:
|
||||
- program: '.[] == 1'
|
||||
input: '[1, 1.0, "1", "banana"]'
|
||||
output: ['[true, true, false, false]']
|
||||
|
||||
- title: if-then-else
|
||||
body: |
|
||||
|
||||
`if A then B else C end` will act the same as `B` if `A`
|
||||
produces a value other than false or null, but act the same
|
||||
as `C` otherwise.
|
||||
|
||||
Checking for false or null is a simpler notion of
|
||||
"truthiness" than is found in Javascript or Python, but it
|
||||
means that you'll sometimes have to be more explicit about
|
||||
the condition you want: you can't test whether, e.g. a
|
||||
string is empty using `if .name then A else B end`, you'll
|
||||
need something more like 'if (.name | count) > 0 then A else
|
||||
B end' instead.
|
||||
|
||||
If the condition A produces multiple results, it is
|
||||
considered "true" if any of those results is not false or
|
||||
null. If it produces zero results, it's considered false.
|
||||
|
||||
More cases can be added to an if using `elif A then B` syntax.
|
||||
|
||||
examples:
|
||||
- program: |-
|
||||
if . == 0 then
|
||||
"zero"
|
||||
elif . == 1 then
|
||||
"one"
|
||||
else
|
||||
"many"
|
||||
end
|
||||
input: 2
|
||||
output: ['"many"']
|
||||
|
||||
- title: and/or/not
|
||||
body: |
|
||||
|
||||
jq supports the normal Boolean operators and/or/not. They have the
|
||||
same standard of truth as if expressions - false and null are
|
||||
considered "false values", and anything else is a "true value".
|
||||
|
||||
If an operand of one of these operators produces multiple
|
||||
results, the operator itself will produce a result for each input.
|
||||
|
||||
`not` is in fact a builtin function rather than an operator,
|
||||
so it is called as a filter to which things can be piped
|
||||
rather than with special syntax, as in `.foo and .bar |
|
||||
not`.
|
||||
|
||||
These three only produce the values "true" and "false", and
|
||||
so are only useful for genuine Boolean operations, rather
|
||||
than the common Perl/Python/Ruby idiom of
|
||||
"value_that_may_be_null or default". If you want to use this
|
||||
form of "or", picking between two values rather than
|
||||
evaluating a condition, see the "//" operator below.
|
||||
|
||||
examples:
|
||||
- program: '42 and "a string"'
|
||||
input: 'null'
|
||||
output: ['true']
|
||||
- program: '(true, false) or false'
|
||||
input: 'null'
|
||||
output: ['true', 'false']
|
||||
- program: '(true, false) and (true, false)'
|
||||
input: 'null'
|
||||
output: ['true', 'false', 'false', 'false']
|
||||
- program: '[true, false | not]'
|
||||
input: 'null'
|
||||
output: ['[false, true]']
|
||||
|
||||
- title: Alternative operator - `//`
|
||||
body: |
|
||||
|
||||
A jq expression of the form `a // b` produces the same
|
||||
results as `a`, if `a` produces results other than `false`
|
||||
and `null`. Otherwise, `a // b` produces the same results as `b`.
|
||||
|
||||
This is useful for providing defaults: `.foo or 1` will
|
||||
evaluate to `1` if there's no `.foo` element in the
|
||||
input. It's similar to how `or` is sometimes used in Python
|
||||
(jq's `or` operator is reserved for strictly Boolean
|
||||
operations).
|
||||
|
||||
examples:
|
||||
- program: '.foo // 42'
|
||||
input: '{"foo": 19}'
|
||||
output: [19]
|
||||
- program: '.foo // 42'
|
||||
input: '{}'
|
||||
output: [42]
|
||||
|
||||
- title: Variables and Functions
|
||||
body: |
|
||||
Variables are an absolute necessity in most programming languages, but
|
||||
they're relegated to an "advanced feature" in jq.
|
||||
|
||||
In most languages, variables are the only means of passing around
|
||||
data. If you calculate a value, and you want to use it more than once,
|
||||
you'll need to store it in a variable. To pass a value to another part
|
||||
of the program, you'll need that part of the program to define a
|
||||
variable (as a function parameter, object member, or whatever) in
|
||||
which to place the data.
|
||||
|
||||
It is also possible to define functions in jq, although this is
|
||||
is a feature whose biggest use is defining jq's standard library
|
||||
(many jq functions such as `map` and `find` are in fact written
|
||||
in jq).
|
||||
|
||||
entries:
|
||||
- title: Variables
|
||||
body: |
|
||||
|
||||
In jq, all jq expressions have an input and an output, so manual
|
||||
plumbing is not necessary to pass a value from one part of a program
|
||||
to the next. Many expressions, for instance `a + b`, pass their input
|
||||
to two distinct subexpressions (here `a` and `b` are both passed the
|
||||
same input), so variables aren't usually necessary in order to use a
|
||||
value twice.
|
||||
|
||||
For instance, calculating the average value of an array of numbers
|
||||
requires a few variables in most languages - at least one to hold the
|
||||
array, perhaps one for each element or for a loop counter. In jq, it's
|
||||
simply `add / length` - the `sum` expression is given the array and
|
||||
produces its sum, and the `count` expression is given the array and
|
||||
produces its length.
|
||||
|
||||
So, there's generally a cleaner way to solve most problems in jq that
|
||||
defining variables. Still, sometimes they do make things easier, so jq
|
||||
lets you define variables using `expression as $variable`. All
|
||||
variable names start with `$`. Here's a slightly uglier version of the
|
||||
array-averaging example:
|
||||
|
||||
length as $array_length | add / $array_length
|
||||
|
||||
We'll need a more complicated problem to find a situation where using
|
||||
variables actually makes our lives easier.
|
||||
|
||||
|
||||
Suppose we have an array of blog posts, with "author" and "title"
|
||||
fields, and another object which is used to map author usernames to
|
||||
real names. Our input looks like:
|
||||
|
||||
{"posts": [{"title": "Frist psot", "author": "anon"},
|
||||
{"title": "A well-written article", "author": "person1"}],
|
||||
"realnames": {"anon": "Anonymous Coward",
|
||||
"person1": "Person McPherson"}}
|
||||
|
||||
We want to produce the posts with the author field containing a real
|
||||
name, as in:
|
||||
|
||||
{"title": "Frist psot", "author": "Anonymous Coward"}
|
||||
{"title": "A well-written article", "author": "Person McPherson"}
|
||||
|
||||
We use a variable, $names, to store the realnames object, so that we
|
||||
can refer to it later when looking up author usernames:
|
||||
|
||||
.realnames as $names | .posts[] | {title, author: $names[.author]}
|
||||
|
||||
The expression "asdf as $x" runs asdf, puts the result in $x, and
|
||||
returns the original input. Apart from the side-effect of binding the
|
||||
variable, it has the same effect as ".".
|
||||
|
||||
Variables are scoped over the rest of the expression that defines
|
||||
them, so
|
||||
|
||||
.realnames as $names | (.posts[] | {title, author: $names[.author]})
|
||||
|
||||
will work, but
|
||||
|
||||
(.realnames as $names | .posts[]) | {title, author: $names[.author]}
|
||||
|
||||
won't.
|
||||
|
||||
examples:
|
||||
- program: '.bar as $x | .foo | . + $x'
|
||||
input: '{"foo":10, "bar":200}'
|
||||
output: ['210']
|
||||
|
||||
- title: 'Defining Functions'
|
||||
body: |
|
||||
|
||||
You can give a jq expression a name using "def" syntax:
|
||||
|
||||
def increment: . + 1;
|
||||
|
||||
From then on, `increment` is usable as a filter just like a
|
||||
builtin function (in fact, this is how some of the builtins
|
||||
are defined). A function may take arguments:
|
||||
|
||||
def map(f): [.[] | f];
|
||||
|
||||
Arguments are passed as jq expressions, not as values. The
|
||||
same argument may be referenced multiple times with
|
||||
different inputs (here `f` is run for each element of the
|
||||
input array). Arguments to a function work more like
|
||||
callbacks than like value arguments.
|
||||
|
||||
If you want the value-argument behaviour for defining simple
|
||||
functions, you can just use a variable:
|
||||
|
||||
def addvalue(f): f as $value | map(, + $value);
|
||||
|
||||
With that definition, `addvalue(.foo)` will add the current
|
||||
input's `.foo` field to each element of the array.
|
||||
|
||||
examples:
|
||||
- program: 'def addvalue(f): map(. + [$value]); addvalue(.[0])'
|
||||
input: '[[1,2],[10,20]]'
|
||||
output: ['[[1,2,1], [10,20,10]]']
|
||||
- program: 'def addvalue(f): f as $x | map (. + $x); addvalue(.[0])'
|
||||
input: '[[1,2],[10,20]]'
|
||||
output: ['[[1,2,[1,2]], [10,20,[1,2]]]']
|
||||
|
||||
|
||||
- title: Assignment
|
||||
body: |
|
||||
|
||||
Assignment works a little differently in jq than in most
|
||||
programming languages. jq doesn't distinguish between references
|
||||
to and copies of something - two objects or arrays are either
|
||||
equal or not equal, without any further notion of being "the
|
||||
same object" or "not the same object".
|
||||
|
||||
If an object has two fields which are arrays, `.foo` and `.bar`,
|
||||
and you append something to `.foo`, then `.bar` will not get
|
||||
bigger. Even if you've just set `.bar = .foo`. If you're used to
|
||||
programming in languages like Python, Java, Ruby, Javascript,
|
||||
etc. then you can think of it as though jq does a full deep copy
|
||||
of every object before it does the assignment (for performance,
|
||||
it doesn't actually do that, but that's the general idea).
|
||||
|
||||
entries:
|
||||
- title: "`=`"
|
||||
body: |
|
||||
|
||||
The jq expression `.foo = 1` will take as input an object
|
||||
and produce as output an object with the "foo" field set to
|
||||
1. There is no notion of "modifying" or "changing" something
|
||||
in jq - all jq values are immutable. For instance,
|
||||
|
||||
.foo = .bar | .foo.baz = 1
|
||||
|
||||
will not have the side-effect of setting .bar.baz to be set
|
||||
to 1, as the similar-looking program in Javascript, Python,
|
||||
Ruby or other languages would. Unlike these languages (but
|
||||
like Haskell and some other functional languages), there is
|
||||
no notion of two arrays or objects being "the same array" or
|
||||
"the same object". They can be equal, or not equal, but if
|
||||
we change one of them in no circumstances will the other
|
||||
change behind our backs.
|
||||
|
||||
This means that it's impossible to build circular values in
|
||||
jq (such as an array whose first element is itself). This is
|
||||
quite intentional, and ensures that anything a jq program
|
||||
can produce can be represented in JSON.
|
||||
|
||||
- title: "`|=`"
|
||||
body: |
|
||||
As well as the assignment operator '=', jq provides the "update"
|
||||
operator '|=', which takes a jq expression on the right-hand side and
|
||||
works out the new value for the property being assigned to by running
|
||||
the old value through this expression. For instance, .foo |= .+1 will
|
||||
build an object with the "foo" field set to the input's "foo" plus 1.
|
||||
|
||||
This example should show the difference between '=' and '|=':
|
||||
|
||||
Provide input '{"a": {"b": 10}, "b": 20}' to the programs:
|
||||
|
||||
.a = .b
|
||||
.a |= .b
|
||||
|
||||
The former will set the "a" field of the input to the "b" field of the
|
||||
input, and produce the output {"a": 20}. The latter will set the "a"
|
||||
field of the input to the "a" field's "b" field, producing {"a": 10}.
|
||||
|
||||
- title: "`+=`, `-=`, `*=`, `/=`, `//=`"
|
||||
body: |
|
||||
|
||||
jq has a few operators of the form `a op= b`, which are all
|
||||
equivalent to `a |= . op b`. So, `+= 1` can be used to increment values.
|
||||
|
||||
examples:
|
||||
- program: .foo += 1
|
||||
input: '{"foo": 42}'
|
||||
output: ['{"foo": 43}']
|
||||
|
||||
- title: Complex assignments
|
||||
body: |
|
||||
Lots more things are allowed on the left-hand side of a jq assignment
|
||||
than in most langauges. We've already seen simple field accesses on
|
||||
the left hand side, and it's no surprise that array accesses work just
|
||||
as well:
|
||||
|
||||
.posts[0].title = "JQ Manual"
|
||||
|
||||
What may come as a surprise is that the expression on the left may
|
||||
produce multiple results, referring to different points in the input
|
||||
document:
|
||||
|
||||
.posts[].comments |= . + ["this is great"]
|
||||
|
||||
That example appends the string "this is great" to the "comments"
|
||||
array of each post in the input (where the input is an object with a
|
||||
field "posts" which is an array of posts).
|
||||
|
||||
When jq encounters an assignment like 'a = b', it records the "path"
|
||||
taken to select a part of the input document while executing a. This
|
||||
path is then used to find which part of the input to change while
|
||||
executing the assignment. Any jq expression may be used on the
|
||||
left-hand side of an equals - whichever paths it selects from the
|
||||
input will be where the assignment is performed.
|
||||
|
||||
This is a very powerful operation. Suppose we wanted to add a comment
|
||||
to blog posts, using the same "blog" input above. This time, we only
|
||||
want to comment on the posts written by "stedolan". We can find those
|
||||
posts using the "select" function described earlier:
|
||||
|
||||
.posts[] | select(.author == "stedolan")
|
||||
|
||||
The paths provided by this operation point to each of the posts that
|
||||
"stedolan" wrote, and we can comment on each of them in the same way
|
||||
that we did before:
|
||||
|
||||
(.posts[] | select(.author == "stedolan") | .comments) |= . + ["terrible."]
|
12
docs/content/index/index.yml
Normal file
12
docs/content/index/index.yml
Normal file
@ -0,0 +1,12 @@
|
||||
headline: jq
|
||||
|
||||
blurb: |
|
||||
|
||||
jq is a command-line JSON processor.
|
||||
|
||||
body: |
|
||||
|
||||
|
||||
|
||||
Go read the [tutorial](/tutorial) for more, or the [manual](/manual)
|
||||
for *way* more.
|
28
docs/public/.htaccess
Normal file
28
docs/public/.htaccess
Normal file
@ -0,0 +1,28 @@
|
||||
DirectoryIndex index.html
|
||||
FileETag All
|
||||
|
||||
# Compress all static assets
|
||||
<IfModule mod_deflate.c>
|
||||
# compress content with type html, text, and css
|
||||
AddOutputFilterByType DEFLATE text/css text/html text/javascript application/javascript application/x-javascript text/js text/plain text/xml
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
# properly handle requests coming from behind proxies
|
||||
Header append Vary User-Agent
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Cache, aggressively
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresDefault "access plus 10 days"
|
||||
|
||||
<FilesMatch "\.(eot|ttf|otf)$">
|
||||
ExpiresDefault "access plus 10 years"
|
||||
</filesMatch>
|
||||
</IfModule>
|
||||
|
||||
# Mime-types
|
||||
AddType application/vnd.ms-fontobject .eot
|
||||
AddType font/ttf .ttf
|
||||
AddType font/otf .otf
|
1058
docs/public/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
1058
docs/public/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
docs/public/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
9
docs/public/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5774
docs/public/bootstrap/css/bootstrap.css
vendored
Normal file
5774
docs/public/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
docs/public/bootstrap/css/bootstrap.min.css
vendored
Normal file
9
docs/public/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/public/bootstrap/img/glyphicons-halflings-white.png
Normal file
BIN
docs/public/bootstrap/img/glyphicons-halflings-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
docs/public/bootstrap/img/glyphicons-halflings.png
Normal file
BIN
docs/public/bootstrap/img/glyphicons-halflings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
2027
docs/public/bootstrap/js/bootstrap.js
vendored
Normal file
2027
docs/public/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
docs/public/bootstrap/js/bootstrap.min.js
vendored
Normal file
6
docs/public/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
72
docs/public/css/base.scss
Normal file
72
docs/public/css/base.scss
Normal file
@ -0,0 +1,72 @@
|
||||
@charset "utf-8";
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #F5F5F5;
|
||||
padding: 40px 0;
|
||||
height: 100px;
|
||||
margin-top: 40px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
section {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.manual-example {
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
.manual-example td {
|
||||
white-space: pre-wrap;
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
.manual-example td.jqprogram {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.manual-example th {
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.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;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#blurb {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
#blurb p {
|
||||
font-size: 20pt;
|
||||
}
|
||||
|
||||
h3 code {
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
}
|
BIN
docs/public/jq.png
Normal file
BIN
docs/public/jq.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
2
docs/public/robots.txt
Normal file
2
docs/public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Allow: /
|
11
docs/site.yml
Normal file
11
docs/site.yml
Normal file
@ -0,0 +1,11 @@
|
||||
# The key value pairs found below are available within the templates.
|
||||
|
||||
|
||||
jq_version: 1.0
|
||||
footer: |
|
||||
|
||||
This website is made with [Bonsai](http://www.tinytree.info) and
|
||||
[Twitter Boostrap](http://twitter.github.com/bootstrap/). jq is
|
||||
licensed under the MIT license (code) and the
|
||||
[CC-BY-3.0](http://creativecommons.org/licenses/by/3.0/) license
|
||||
(docs).
|
34
docs/templates/default.liquid
vendored
Normal file
34
docs/templates/default.liquid
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/header" %}
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<h1>{{headline}}</h1>
|
||||
{% for item in body %}
|
||||
{% if item.text %}
|
||||
{{ item.text | markdownify }}
|
||||
{% endif %}
|
||||
|
||||
{% if item.command %}
|
||||
|
||||
|
||||
{% capture resultID %}{{ "result" | unique}}{% endcapture %}
|
||||
<div class="tutorial-example">
|
||||
<div class="accordion-heading">
|
||||
<pre>{{item.command}}</pre>
|
||||
<a data-toggle="collapse" href="#{{resultID}}">Show result</a>
|
||||
</div>
|
||||
<div id="{{resultID}}" class="accordion-body collapse"><pre>{{item.result}}</pre></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
|
||||
</body>
|
||||
</html>
|
38
docs/templates/index.liquid
vendored
Normal file
38
docs/templates/index.liquid
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/header" %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="hero-unit">
|
||||
<img src="/jq.png" style="width: 400px; height: 220px; float: left; margin-right: 60px">
|
||||
<div id="blurb">
|
||||
{{blurb | markdownify}}
|
||||
<div class="btn-group" style="float:right">
|
||||
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
Download jq-{{jq_version}}
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/download/linux/x68_64/jq">Linux (x86_64)</a></li>
|
||||
<li><a href="/download/osx/64/jq">OS X (64-bit)</a></li>
|
||||
<li><a href="/download">Other platforms and source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
|
||||
{{body | markdownify}}
|
||||
</div>
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
</body>
|
||||
</html>
|
109
docs/templates/manual.liquid
vendored
Normal file
109
docs/templates/manual.liquid
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}" data-spy="scroll" data-target="#navcolumn" data-offset="100">
|
||||
{% include "shared/header" %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span3" id="navcolumn">
|
||||
<div class="affix">
|
||||
<h4>Contents</h4>
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
{% for section in sections %}
|
||||
<li {% if forloop.first %} class="active" {% endif %}>
|
||||
<a href="#{{section.title | sanitize}}">{{section.title}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<form class="form-search">
|
||||
<script type="text/javascript">
|
||||
var section_map = {
|
||||
{% for section in sections %}
|
||||
{% for entry in section.entries %}
|
||||
{{entry.title | json}} : {{entry.title | sanitize | json}},
|
||||
{% endfor %}
|
||||
{{section.title | json}} : {{section.title | sanitize | json}}
|
||||
{% unless forloop.last %},{% endunless %}
|
||||
{% endfor %}
|
||||
};
|
||||
var section_names = $.map(section_map, function(v,k){return k});
|
||||
$(function(){
|
||||
$('#searchbox').typeahead({source: section_names})
|
||||
$('#searchbox').change(function() {
|
||||
if ($(this).val() in section_map) {
|
||||
location.hash = '#' + section_map[$(this).val()];
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<input type="text"
|
||||
class="input-medium search-query"
|
||||
placeholder="Search"
|
||||
autocomplete="off"
|
||||
id="searchbox">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<h1>{{headline}}</h1>
|
||||
{% for section in sections %}
|
||||
<section id="{{section.title | sanitize}}">
|
||||
<h2>{{section.title}}</h2>
|
||||
{{section.body | markdownify}}
|
||||
{% for entry in section.entries %}
|
||||
<section id="{{entry.title | sanitize}}">
|
||||
<h3>
|
||||
{{entry.title | markdownify}}
|
||||
{% if entry.subtitle %}<small>{{entry.subtitle}}</small>{% endif %}
|
||||
</h3>
|
||||
{{entry.body | markdownify}}
|
||||
|
||||
{% if entry.examples %}
|
||||
<div>
|
||||
{% capture exampleID %}{{ "" | unique }}{% endcapture %}
|
||||
<a data-toggle="collapse" href="#example{{exampleID}}">
|
||||
<i class="icon-chevron-right"></i>
|
||||
{% if entry.examples[1] %}Examples{%else%}Example{%endif%}
|
||||
</a>
|
||||
<div id="example{{exampleID}}" class="collapse">
|
||||
|
||||
{% for example in entry.examples %}
|
||||
<table class="manual-example">
|
||||
<tr><th></th><td class="jqprogram">jq '{{example.program}}'</td></tr>
|
||||
<tr><th>Input</th><td>{{example.input}}</td></tr>
|
||||
{% unless example.output[0] %}
|
||||
<tr>
|
||||
<th>Output</th>
|
||||
<td><i>none</i></td>
|
||||
</tr>
|
||||
{% endunless %}
|
||||
{% for output in example.output %}
|
||||
<tr>
|
||||
{% if forloop.index == 1 %}
|
||||
<th>Output</th>
|
||||
{% else %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
<td>{{output}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
5
docs/templates/shared/_footer.liquid
vendored
Normal file
5
docs/templates/shared/_footer.liquid
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
<footer>
|
||||
<div class="container">
|
||||
{{ footer | markdownify }}
|
||||
</div>
|
||||
</footer>
|
12
docs/templates/shared/_head.liquid
vendored
Normal file
12
docs/templates/shared/_head.liquid
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>{{headline}} | jq</title>
|
||||
<link rel="stylesheet" href="/bootstrap/css/bootstrap.css" type="text/css">
|
||||
<link rel="stylesheet" href="/css/base.css" type="text/css">
|
||||
<!--[if IE]>
|
||||
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
|
||||
<script src="/bootstrap/js/bootstrap.js"></script>
|
||||
|
||||
</head>
|
24
docs/templates/shared/_header.liquid
vendored
Normal file
24
docs/templates/shared/_header.liquid
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="brand" href="/">jq</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
{% for item in navigation %}
|
||||
<li {% if item.permalink == permalink %} class="active" {% endif %}>
|
||||
<a href="{{item.permalink}}">{{item.name}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li><a href="https://github.com/stedolan/jq/issues">Issues</a></li>
|
||||
<li><a href="https://github.com/stedolan/jq">Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user