[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*.cr]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\n\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n    labels:\n      - \"kind:infrastructure\"\n      - \"kind:enhancement\"\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  pull_request:\n    branches:\n      - 'master'\n  schedule:\n    - cron: '0 21 * * *'\n\njobs:\n  check_format:\n    runs-on: ubuntu-latest\n    container:\n      image: crystallang/crystal:latest-alpine\n    steps:\n      - uses: actions/checkout@v6\n      - name: Format\n        run: crystal tool format --check\n  coding_standards:\n    runs-on: ubuntu-latest\n    container:\n      image: crystallang/crystal:latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install Dependencies\n        run: shards install\n      - name: Ameba\n        run: ./bin/ameba\n  test:\n    strategy:\n      fail-fast: false\n      matrix:\n        os:\n          - ubuntu-latest\n          - macos-latest\n        crystal:\n          - latest\n          - nightly\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install Crystal\n        uses: crystal-lang/install-crystal@v1\n        with:\n          crystal: ${{ matrix.crystal }}\n      - name: Build\n        run: shards build --production\n      - name: Specs\n        run: crystal spec --order=random --error-on-warnings\n"
  },
  {
    "path": ".github/workflows/deployment.yml",
    "content": "name: Deployment\n\non:\n  release:\n    types:\n      - created\n\njobs:\n  dist_linux:\n    runs-on: ubuntu-latest\n    container:\n      image: crystallang/crystal:latest-alpine\n    steps:\n    - uses: actions/checkout@v6\n    - name: Update Libs\n      run: apk add --update --upgrade --no-cache --force-overwrite libxml2-dev yaml-dev yaml-static\n    - name: Build\n      run: shards build --production --release --static --no-debug --link-flags=\"-s -Wl,-z,relro,-z,now\"\n    - name: Upload\n      uses: actions/upload-release-asset@v1.0.2\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      with:\n        upload_url: ${{ github.event.release.upload_url }}\n        asset_path: ./bin/oq\n        asset_name: oq-${{ github.event.release.tag_name }}-linux-x86_64\n        asset_content_type: binary/octet-stream\n  dist_snap:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build Snap\n        uses: snapcore/action-build@v1\n        id: build\n      - name: Publish Snap\n        uses: snapcore/action-publish@v1\n        env:\n          SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.STORE_LOGIN }}\n        with:\n          snap: ${{ steps.build.outputs.snap }}\n          release: stable\n  dist_homebrew:\n    runs-on: macos-latest\n    steps:\n      - run: git config --global user.email \"george@dietrich.app\"\n      - run: git config --global user.name \"George Dietrich\"\n      - name: Bump Formula\n        uses: Homebrew/actions/bump-formulae@b5d9170bc1edf1103e40226592b5842b783dd1e0\n        with:\n          token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}\n          formulae: oq\n  deploy_docs:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    permissions:\n      contents: read\n      pages: write\n      id-token: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Install Crystal\n        uses: crystal-lang/install-crystal@v1\n      - name: Build\n        run: crystal docs\n      - name: Setup Pages\n        uses: actions/configure-pages@v6\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v4\n        with:\n          path: 'docs/'\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v5\n"
  },
  {
    "path": ".gitignore",
    "content": "*.dwarf\n*.snap\n/.shards/\n/bin/\n/docs/\n/lib/\n\n# Libraries don't need dependency lock\n# Dependencies will be locked in application that uses them\n/shard.lock\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2021 George Dietrich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# oq\n\n[![Built with Crystal](https://img.shields.io/badge/built%20with-crystal-000000.svg?logo=crystal)](https://crystal-lang.org/)\n[![CI](https://github.com/blacksmoke16/oq/workflows/CI/badge.svg)](https://github.com/blacksmoke16/oq/actions?query=workflow%3ACI)\n[![Latest release](https://img.shields.io/github/release/blacksmoke16/oq.svg?color=teal&logo=github)](https://github.com/blacksmoke16/oq/releases)\n[![oq](https://snapcraft.io/oq/badge.svg)](https://snapcraft.io/oq)\n[![oq](https://img.shields.io/aur/version/oq?label=oq&logo=arch-linux)](https://aur.archlinux.org/packages/oq/)\n[![oq-bin](https://img.shields.io/aur/version/oq-bin?label=oq-bin&logo=arch-linux)](https://aur.archlinux.org/packages/oq-bin/)\n\nA performant, portable [jq](https://github.com/stedolan/jq/) wrapper that facilitates the consumption and output of formats other than JSON; using `jq` filters to transform the data.\n\n* Compiles to a single binary for easy portability.\n* Performant, similar performance with JSON data compared to `jq`.  Slightly longer execution time when going to/from a non-JSON format.\n* Supports various other input/output [formats](https://blacksmoke16.github.io/oq/OQ/Format.html), such as `XML` and `YAML`.\n* Can be used as a dependency within other Crystal projects.\n\n## Installation\n\n### Linux\n\nA statically linked binary for Linux `x86_64` as available on the [Releases](https://github.com/Blacksmoke16/oq/releases) tab.  Additionally it can also be installed via various package managers.\n\n#### Snapcraft\n\nFor more on installing & using `snap` with your Linux distribution, see the [official documentation](https://docs.snapcraft.io/installing-snapd).\n\n```sh\nsudo snap install oq\n```\n\n#### Arch Linux\n\nUsing [yay](https://github.com/Jguer/yay):\n\n```sh\nyay -S oq\n```\n\nA pre-compiled version is also available:\n\n```sh\nyay -S oq-bin\n```\n\n### macOS\n\n```sh\nbrew install oq\n```\n\n### From Source\n\nIf building from source, `jq` will need to be installed separately. Installation instructions can be found in the [official documentation](https://stedolan.github.io/jq/).\n\nRequires Crystal to be installed, see the [installation documentation](https://crystal-lang.org/install).\n\n```sh\ngit clone https://github.com/Blacksmoke16/oq.git\ncd oq/\nshards build --production --release\n```\n\nThe built binary will be available as `./bin/oq`.  This can be relocated elsewhere on your machine; be sure it is in your `PATH` to access it as `oq`.\n\n### Docker\n\n`oq` can easily be included into a Docker image by fetching the static binary from Github for the version of `oq` that you want.\n\n```dockerfile\n# Set an arg to store the oq version that should be installed.\nARG OQ_VERSION=1.3.5\n\n# Grab the binary from the latest Github release and make it executable; placing it within /usr/local/bin.  Can also put it elsewhere if you so desire.\nRUN wget https://github.com/Blacksmoke16/oq/releases/download/v${OQ_VERSION}/oq-v${OQ_VERSION}-linux-x86_64 -O /usr/local/bin/oq && chmod +x /usr/local/bin/oq\n\n# Or using curl (needs to follow Github's redirect):\nRUN curl -L -o /usr/local/bin/oq https://github.com/Blacksmoke16/oq/releases/download/v${OQ_VERSION}/oq-v${OQ_VERSION}-linux-x86_64 && chmod +x /usr/local/bin/oq\n\n# Also be sure to install jq if it is not already!\n```\n\n### Existing Crystal Project\n\nAdd the following to your `shard.yml` and run `shards install`.\n\n```yaml\ndependencies:\n  oq:\n    github: blacksmoke16/oq\n    version: ~> 1.3.0\n```\n\n## Usage\n\n### CLI\n\nUse the `oq` binary, with a few optional custom arguments, see `oq --help`.  All other arguments get passed to `jq`. See [jq manual](https://stedolan.github.io/jq/manual/) for details.\n\n### Library\n\nCheckout the [API Documentation](https://blacksmoke16.github.io/oq/OQ/Processor.html) for using `oq` within an existing Crystal project.\n\n### Examples\n\nConsume JSON and output XML\n\n```sh\n$ echo '{\"name\": \"Jim\"}' | oq -o xml .\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n  <name>Jim</name>\n</root>\n```\n\nConsume YAML from a file and output XML\n\ndata.yaml\n\n```yaml\n---\nname: Jim\nnumbers:\n  - 1\n  - 2\n  - 3\n```\n\n```sh\n$ oq -i yaml -o xml . data.yaml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n  <name>Jim</name>\n  <numbers>1</numbers>\n  <numbers>2</numbers>\n  <numbers>3</numbers>\n</root>\n```\n\nUse `oq` as a library, consuming some raw `JSON` input, convert it to `YAML`, and write the transformed data to a file.\n\n```crystal\nrequire \"oq\"\n\n# This could be any `IO`, e.g. an `HTTP` request body, etc.\ninput_io = IO::Memory.new %({\"name\":\"Jim\"})\n\n# Create a processor, specifying that we want the output format to be `YAML`.\nprocessor = OQ::Processor.new output_format: :yaml\n\nFile.open(\"./out.yml\", \"w\") do |file|\n  # Process the data using our custom input and output IOs.\n  # The first argument represents the input arguments;\n  # i.e. the filter and/or any other arguments that should be passed to `jq`.\n  processor.process [\".\"], input: input_io, output: file\nend\n```\n\n## Contributing\n\n1. Fork it (<https://github.com/Blacksmoke16/oq/fork>)\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Contributors\n\n- [George Dietrich](https://github.com/Blacksmoke16) - creator, maintainer\n- [Michael Springer](https://github.com/sprngr) - contributor\n"
  },
  {
    "path": "shard.yml",
    "content": "name: oq\n\ndescription: |\n  A performant, and portable jq wrapper that facilitates the consumption and output of formats other than JSON; using jq filters to transform the data.\n\nversion: 1.3.5\n\nauthors:\n  - George Dietrich <dev@dietrich.pub>\n\ncrystal: ~> 1.4\n\nlicense: MIT\n\ntargets:\n  oq:\n    main: src/oq_cli.cr\n\ndevelopment_dependencies:\n  ameba:\n    github: crystal-ameba/ameba\n    version: ~> 1.5.0\n"
  },
  {
    "path": "snap/snapcraft.yaml",
    "content": "name: oq\nversion: '1.3.5'\nsummary: A performant, and portable jq wrapper to support formats other than JSON\ndescription: |\n  A performant, and portable jq wrapper that facilitates the consumption and output of formats other than JSON; using jq filters to transform the data.\n\ncontact: george@dietrich.app\nissues: https://github.com/Blacksmoke16/oq/issues\nwebsite: https://github.com/Blacksmoke16/oq\nsource-code: https://github.com/Blacksmoke16/oq.git\nlicense: MIT\n\ngrade: stable\nconfinement: strict\nbase: core20\ntype: app\n\napps:\n  oq:\n    command: bin/oq\n    plugs:\n      - home\n      - removable-media\n\nparts:\n  oq:\n    plugin: crystal\n    crystal-build-options:\n      - --release\n      - --no-debug\n      - '--link-flags=-s -Wl,-z,relro,-z,now'\n    source: ./\n    stage-packages:\n      - jq\n    override-pull: |\n      snapcraftctl pull\n      rm -rf $SNAPCRAFT_PART_SRC/lib $SNAPCRAFT_PART_SRC/bin\n"
  },
  {
    "path": "spec/assets/data1.json",
    "content": "{\"name\": \"Jim\"}\n"
  },
  {
    "path": "spec/assets/data1.yml",
    "content": "---\nname: Jim\n"
  },
  {
    "path": "spec/assets/data2.json",
    "content": "{\"name\": \"Bob\"}\n"
  },
  {
    "path": "spec/assets/data2.yml",
    "content": "age: 17\nname: Fred\n"
  },
  {
    "path": "spec/assets/raw.json",
    "content": "1\n2\n3\n"
  },
  {
    "path": "spec/assets/stream-data.json",
    "content": "{\"machine\": \"possible_victim01\", \"domain\": \"evil.com\", \"timestamp\":1435071870}\n{\"machine\": \"possible_victim01\", \"domain\": \"evil.com\", \"timestamp\":1435071875}\n{\"machine\": \"possible_victim01\", \"domain\": \"soevil.com\", \"timestamp\":1435071877}\n{\"machine\": \"possible_victim02\", \"domain\": \"bad.com\", \"timestamp\":1435071877}\n{\"machine\": \"possible_victim03\", \"domain\": \"soevil.com\", \"timestamp\":1435071879}\n"
  },
  {
    "path": "spec/assets/stream-filter",
    "content": "reduce inputs as $line\n  ({};\n   $line.machine as $machine\n   | $line.domain as $domain\n   | .[$machine].total as $total\n   | .[$machine].evildoers as $evildoers\n   | . + { ($machine): {\"total\": (1 + $total),\n                        \"evildoers\": ($evildoers | (.[$domain] += 1)) }} )\n"
  },
  {
    "path": "spec/assets/test.jq",
    "content": "def increment: . + 1;\n"
  },
  {
    "path": "spec/assets/test_filter",
    "content": ".name"
  },
  {
    "path": "spec/converters/simple_yaml_spec.cr",
    "content": "require \"../spec_helper\"\n\n# Essentially copied from the `YAML` spec, minus the `with anchors` test.\n#\n# TODO: Allow the test code to be more easily shared.\ndescribe OQ::Converters::SimpleYAML do\n  describe \".deserialize\" do\n    describe String do\n      describe \"not blank\" do\n        it \"should output correctly\" do\n          run_binary(%(--- Jim), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq %(\"Jim\"\\n)\n          end\n        end\n      end\n\n      describe \"blank\" do\n        it \"should output correctly\" do\n          run_binary(%(--- ), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq \"null\\n\"\n          end\n        end\n      end\n\n      describe \"with a tag\" do\n        it \"should output correctly\" do\n          run_binary(%(--- !!str 0.5), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq %(\"0.5\"\\n)\n          end\n        end\n      end\n\n      describe \"that is single quoted\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nhowever: 'foobar'), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"however\":\"foobar\"}\\n)\n          end\n        end\n      end\n\n      describe \"that is double quoted\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nhowever: \"foobar\"), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"however\":\"foobar\"}\\n)\n          end\n        end\n      end\n\n      describe \"literal block\" do\n        it \"should output correctly\" do\n          run_binary(LITERAL_BLOCK, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"literal_block\":\"This entire block of text will be the value of the 'literal_block' key,\\\\nwith line breaks being preserved.\\\\n\\\\nThe literal continues until de-dented, and the leading indentation is\\\\nstripped.\\\\n\\\\n    Any lines that are 'more-indented' keep the rest of their indentation -\\\\n    these lines will be indented by 4 spaces.\"}\\n)\n          end\n        end\n      end\n\n      describe \"folded block\" do\n        it \"should output correctly\" do\n          run_binary(FOLDED_BLOCK, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"folded_style\":\"This entire block of text will be the value of 'folded_style', but this time, all newlines will be replaced with a single space.\\\\nBlank lines, like above, are converted to a newline character.\\\\n\\\\n    'More-indented' lines keep their newlines, too -\\\\n    this text will appear over two lines.\"}\\n)\n          end\n        end\n      end\n    end\n\n    describe Bool do\n      it \"should output correctly\" do\n        run_binary(%(--- true), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n          output.should eq \"true\\n\"\n        end\n      end\n    end\n\n    describe Float do\n      it \"should output correctly\" do\n        run_binary(%(--- 10.50), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n          output.should eq \"10.5\\n\"\n        end\n      end\n    end\n\n    describe Nil do\n      it \"should output correctly\" do\n        run_binary(%(--- ), args: [\"-i\", \"simpleyaml\", \".\"]) do |output|\n          output.should eq \"null\\n\"\n        end\n      end\n    end\n\n    describe Object do\n      describe \"a simple object\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nname: Jim), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"name\":\"Jim\"}\\n)\n          end\n        end\n      end\n\n      describe \"with spaces in the key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nkey with spaces: value), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"key with spaces\":\"value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with a quoted key key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\n'Keys can be quoted too.': value), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"Keys can be quoted too.\":\"value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with nested object\" do\n        it \"should output correctly\" do\n          run_binary(NESTED_OBJECT, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"a_nested_map\":{\"key\":\"value\",\"another_key\":\"Another Value\",\"another_nested_map\":{\"hello\":\"hello\"}}}\\n)\n          end\n        end\n      end\n\n      describe \"with a non string key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\n0.25: a float key), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"0.25\":\"a float key\"}\\n)\n          end\n        end\n      end\n\n      describe \"with JSON syntax\" do\n        describe \"with quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: {\"key\": \"value\"}), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":{\"key\":\"value\"}}\\n)\n            end\n          end\n        end\n\n        describe \"without quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: {key: value}), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":{\"key\":\"value\"}}\\n)\n            end\n          end\n        end\n      end\n\n      describe \"with a complex mapping key\" do\n        it \"should output correctly\" do\n          run_binary(COMPLEX_MAPPING_KEY, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"This is a key\\\\nthat has multiple lines\\\\n\":\"and this is its value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with set notation\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nset:\\n  ? item1\\n  ? item2), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"set\":{\"item1\":null,\"item2\":null}}\\n)\n          end\n        end\n      end\n\n      pending \"with a complex sequence key\" do\n        it \"should output correctly\" do\n          run_binary(COMPLEX_SEQUENCE_KEY, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"[\"Manchester United\", \"Real Madrid\"]\":[\"2001-01-01T00:00:00Z\",\"2002-02-02T00:00:00Z\"]}\\n)\n          end\n        end\n      end\n    end\n\n    describe Array do\n      describe \"with mixed/nested array values\" do\n        it \"should output correctly\" do\n          run_binary(NESTED_ARRAY, args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"a_sequence\":[\"Item 1\",\"Item 2\",0.5,\"Item 4\",{\"key\":\"value\",\"another_key\":\"another_value\"},[\"This is a sequence\",\"inside another sequence\"],[[\"Nested sequence indicators\",\"can be collapsed\"]]]}\\n)\n          end\n        end\n      end\n\n      describe \"with JSON syntax\" do\n        describe \"with quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: [3, 2, 1, \"takeoff\"]), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":[3,2,1,\"takeoff\"]}\\n)\n            end\n          end\n        end\n\n        describe \"without quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: [3, 2, 1, takeoff]), args: [\"-i\", \"simpleyaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":[3,2,1,\"takeoff\"]}\\n)\n            end\n          end\n        end\n      end\n    end\n  end\n\n  describe \".serialize\" do\n    describe String do\n      describe \"not blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"Jim\"), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should start_with <<-YAML\n            --- Jim\n            YAML\n          end\n        end\n      end\n\n      describe \"blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"\"), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              --- \"\"\\n\n              YAML\n            )\n          end\n        end\n      end\n    end\n\n    describe Bool do\n      it \"should output correctly\" do\n        run_binary(%(true), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n          output.should start_with <<-YAML\n            --- true\n            YAML\n        end\n      end\n    end\n\n    describe Float do\n      it \"should output correctly\" do\n        run_binary(%(\"1.5\"), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n          output.should eq(<<-YAML\n            --- \"1.5\"\\n\n            YAML\n          )\n        end\n      end\n    end\n\n    describe Nil do\n      it \"should output correctly\" do\n        run_binary(\"null\", args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n          output.should start_with \"---\"\n        end\n      end\n    end\n\n    describe Array do\n      describe \"empty array on root\" do\n        it \"should emit a self closing root tag\" do\n          run_binary(\"[]\", args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              --- []\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"array with values on root\" do\n        it \"should emit item tags for non empty values\" do\n          run_binary(%([\"x\",{}]), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              - x\n              - {}\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object with empty array/values\" do\n        it \"should emit self closing tags for each\" do\n          run_binary(%({\"a\":[],\"b\":{},\"c\":null}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should start_with <<-YAML\n              ---\n              a: []\n              b: {}\n              c:\n              YAML\n          end\n        end\n      end\n\n      describe \"2D array object value\" do\n        it \"should emit key name tag then self closing item tag\" do\n          run_binary(%({\"a\":[[]]}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              a:\n              - []\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object value mixed/nested array values\" do\n        it \"should emit correctly\" do\n          run_binary(%({\"x\":[1,[2,[3]]]}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              x:\n              - 1\n              - - 2\n                - - 3\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object value array primitive values\" do\n        it \"should emit correctly\" do\n          run_binary(%({\"x\":[1,2,3]}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              x:\n              - 1\n              - 2\n              - 3\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"when the jq filter doesn't return data\" do\n        it \"should return an empty string\" do\n          run_binary(%([{\"name\":\"foo\"}]), args: [\"-i\", \"simpleyaml\", \"-o\", \"simpleyaml\", %<.[] | select(.name != \"foo\")>]) do |output|\n            output.should be_empty\n          end\n        end\n      end\n    end\n\n    describe Object do\n      describe \"simple key/value\" do\n        it \"should output correctly\" do\n          run_binary(%({\"name\":\"Jim\"}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              name: Jim\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"nested object\" do\n        it \"should output correctly\" do\n          run_binary(%({\"name\":\"Jim\", \"city\": {\"street\":\"forbs\"}}), args: [\"-o\", \"simpleyaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              name: Jim\n              city:\n                street: forbs\\n\n              YAML\n            )\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/converters/xml_spec.cr",
    "content": "require \"../spec_helper\"\n\nWITH_WHITESPACE = <<-XML\n<item>\n  <flagID>0</flagID>\n  <itemID>0</itemID>\n  <locationID>0</locationID>\n  <ownerID>0</ownerID>\n  <quantity>-1</quantity>\n  <typeID>0</typeID>\n</item>\nXML\n\nXML_SCALAR_ARRAY = <<-XML\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<items>\n  <number>1</number>\n  <number>2</number>\n  <number>3</number>\n</items>\nXML\n\nXML_SCALAR_ARRAY_WITH_ATTRIBUTE = <<-XML\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<items>\n  <number>1</number>\n  <number>2</number>\n  <number foo=\"bar\">3</number>\n</items>\nXML\n\nXML_CDATA = <<-XML\n<desc><![CDATA[<message>Some Description</message>]]></desc>\nXML\n\nXML_OBJECT_ARRAY = <<-XML\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<items>\n  <item>\n    <flagID>0</flagID>\n    <itemID>0</itemID>\n    <locationID>0</locationID>\n    <ownerID>0</ownerID>\n    <quantity>-1</quantity>\n    <typeID>0</typeID>\n  </item>\n  <item>\n    <flagID>0</flagID>\n    <itemID>1</itemID>\n    <locationID>0</locationID>\n    <ownerID>0</ownerID>\n    <quantity>-1</quantity>\n    <typeID>0</typeID>\n  </item>\n</items>\nXML\n\nXML_NESTED_OBJECT_ARRAY = <<-XML\n<?xml version='1.0' ?>\n<!DOCTYPE root SYSTEM \"http://www.cs.washington.edu/research/projects/xmltk/xmldata/data/auctions/ebay.dtd\">\n<root>\n <listing>\n   <seller_info>\n       <seller_name> cubsfantony</seller_name>\n       <seller_rating> 848</seller_rating>\n   </seller_info>\n   <payment_types>Visa/MasterCard, Money Order/Cashiers Checks, Personal Checks, See item description for payment methods accepted</payment_types>\n</listing>\n<listing>\n   <seller_info>\n       <seller_name> ct-inc</seller_name>\n       <seller_rating> 403</seller_rating>\n   </seller_info>\n   <payment_types>Visa/MasterCard, Discover, Money Order/Cashiers Checks, Personal Checks, See item description for payment methods accepted</payment_types>\n</listing>\n</root>\nXML\n\nXML_INLINE_ARRAY = <<-XML\n<article key=\"tr/ibm/RJ2144\">\n  <author>E. F. Codd</author>\n  <author>Robert S. Arnold</author>\n  <author>Jean-Marc Cadiou</author>\n  <author>Chin-Liang Chang</author>\n  <author>Nick Roussopoulos</author>\n  <title>RENDEZVOUS Version 1: An Experimental English Language Query Formulation System for Casual Users of Relational Data Bases.</title>\n  <journal>IBM Research Report</journal>\n  <volume>RJ2144</volume>\n  <month>January</month>\n  <year>1978</year>\n  <ee>db/labs/ibm/RJ2144.html</ee>\n  <cdrom>ibmTR/rj2144.pdf</cdrom>\n</article>\nXML\n\nXML_INLINE_ARRAY_WITHIN_ARRAY = <<-XML\n<articles>\n  <article key=\"tr/dec/SRC1997-018\">\n    <year>1997</year>\n    <ee>db/labs/dec/SRC1997-018.html</ee>\n    <ee>http://www.mcjones.org/System_R/SQL_Reunion_95/</ee>\n  </article>\n  <article key=\"tr/gte/TR-0263-08-94-165\">\n    <ee>db/labs/gte/TR-0263-08-94-165.html</ee>\n    <year>1994</year>\n  </article>\n</articles>\nXML\n\nXML_DOCTYPE = <<-XML\n<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE dblp SYSTEM \"dblp.dtd\">\n<dblp>\n  <mastersthesis key=\"ms/Brown92\">\n    <author>Kurt P. Brown</author>\n    <title>PRPL: A Database Workload Specification Language, v1.3.</title>\n    <year>1992</year>\n    <school>Univ. of Wisconsin-Madison</school>\n  </mastersthesis>\n</dblp>\nXML\n\nXML_ATTRIBUTE_IN_ARRAY = <<-XML\n<jobs>\n  <ad>\n    <salary currency=\"CAD\">80000</salary>\n    <working_hours>full-time</working_hours>\n  </ad>\n  <ad>\n    <working_hours>full-time</working_hours>\n  </ad>\n</jobs>\nXML\n\nXML_ATTRIBUTE_IN_ARRAY_ROOT_ELEMENT = <<-XML\n<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE dblp SYSTEM \"dblp.dtd\">\n<dblp>\n  <mastersthesis key=\"ms/Brown92\">\n    <author>Kurt P. Brown</author>\n  </mastersthesis>\n  <mastersthesis key=\"ms/Yurek97\">\n    <author>Tolga Yurek</author>\n  </mastersthesis>\n</dblp>\nXML\n\nXML_ALL_EMPTY = <<-XML\n<root>\n  <one> </one>\n  <two>\n  </two>\n  <three/>\n  <four></four>\n</root>\nXML\n\nXML_NAMESPACE_ARRAY = <<-XML\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<items xmlns:n=\"http://n\">\n  <n:number>1</n:number>\n  <n:number>2</n:number>\n  <number xmlns=\"http://default\">3</number>\n</items>\nXML\n\nXML_NAMESPACE_ARRAY_SCALAR_VALUE_PREFIX = <<-XML\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<items xmlns:n=\"http://n\">\n  <n:number>1</n:number>\n  <n:number>2</n:number>\n  <n:number xmlns=\"http://default\">3</n:number>\n</items>\nXML\n\nXML_NAMESPACE_PREFIXES = <<-XML\n<?xml version=\"1.0\" ?>\n<root xmlns:a=\"https://a\">\n  <foo>foo</foo>\n  <a:bar>bar</a:bar>\n</root>\nXML\n\nXML_NESTED_NAMESPACES = <<-XML\n<?xml version=\"1.0\" ?>\n<root xmlns:a=\"https://a\" xmlns=\"https://b\">\n  <a:foo>herp</a:foo>\n  <foo>\n    <bar xmlns=\"https://c\">\n      <baz xmlns=\"https://d\"/>\n    </bar>\n  </foo>\n</root>\nXML\n\ndescribe OQ::Converters::XML do\n  describe \".deserialize\" do\n    # See https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html\n    describe \"conventions\" do\n      describe \"an empty element\" do\n        it \"self closing\" do\n          run_binary(\"<e/>\", args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"e\":null}\\n)\n          end\n        end\n\n        it \"non self closing\" do\n          run_binary(\"<e></e>\", args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"e\":null}\\n)\n          end\n        end\n      end\n\n      it \"an element with pure text content\" do\n        run_binary(\"<e>text</e>\", args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":\"text\"}\\n)\n        end\n      end\n\n      it \"an empty element with attributes\" do\n        run_binary(%(<e name=\"value\" />), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":{\"@name\":\"value\"}}\\n)\n        end\n      end\n\n      it \"an element with pure text content and attributes\" do\n        run_binary(%(<e name=\"value\">text</e>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":{\"@name\":\"value\",\"#text\":\"text\"}}\\n)\n        end\n      end\n\n      it \"an element containing elements with different names\" do\n        run_binary(%(<e> <a>text</a> <b>text</b> </e>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":{\"a\":\"text\",\"b\":\"text\"}}\\n)\n        end\n      end\n\n      it \"an element containing elements with identical names\" do\n        run_binary(%(<e> <a>text</a> <a>text</a> </e>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":{\"a\":[\"text\",\"text\"]}}\\n)\n        end\n      end\n\n      it \"an element containing elements and contiguous text\" do\n        run_binary(%(<e>text<a>text</a></e>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"e\":{\"#text\":\"text\",\"a\":\"text\"}}\\n)\n        end\n      end\n    end\n\n    describe \"should raise if invalid\" do\n      it \"should output correctly\" do\n        run_binary(%(<root id=\"1<child/></root>), args: [\"-i\", \"xml\", \"-c\", \".\"], success: false) do |_, _, error|\n          error.should eq \"oq error: Couldn't find end of Start Tag root\\n\"\n        end\n      end\n    end\n\n    describe Object do\n      it \"a key/value pair\" do\n        run_binary(%(<person>Fred</person>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"person\":\"Fred\"}\\n)\n        end\n      end\n\n      describe \"that has only empty children elements\" do\n        it \"should output an object with null values\" do\n          run_binary(XML_ALL_EMPTY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"root\":{\"one\":\" \",\"two\":\"\\\\n  \",\"three\":null,\"four\":null}}\\n)\n          end\n        end\n      end\n\n      it \"with whitespace\" do\n        run_binary(WITH_WHITESPACE, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"item\":{\"flagID\":\"0\",\"itemID\":\"0\",\"locationID\":\"0\",\"ownerID\":\"0\",\"quantity\":\"-1\",\"typeID\":\"0\"}}\\n)\n        end\n      end\n\n      it \"with the prolog\" do\n        run_binary(%(<?xml version=\"1.0\" encoding=\"utf-8\"?><item><typeID>0</typeID></item>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"item\":{\"typeID\":\"0\"}}\\n)\n        end\n      end\n\n      it \"a simple object\" do\n        run_binary(%(<person><firstname>Jane</firstname><lastname>Doe</lastname></person>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"person\":{\"firstname\":\"Jane\",\"lastname\":\"Doe\"}}\\n)\n        end\n      end\n\n      it \"attributes\" do\n        run_binary(%(<person id=\"1\" foo=\"bar\"><firstname>Jane</firstname><lastname>Doe</lastname></person>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"person\":{\"@id\":\"1\",\"@foo\":\"bar\",\"firstname\":\"Jane\",\"lastname\":\"Doe\"}}\\n)\n        end\n      end\n\n      it \"nested objects\" do\n        run_binary(%(<person><firstname>Jane</firstname><lastname>Doe</lastname><location><zip>15061</zip><address>123 Foo Street</address></location></person>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"person\":{\"firstname\":\"Jane\",\"lastname\":\"Doe\",\"location\":{\"zip\":\"15061\",\"address\":\"123 Foo Street\"}}}\\n)\n        end\n      end\n\n      it \"complex object\" do\n        run_binary(%(<root><x a=\"1\"><a>2</a></x><y b=\"3\">4</y></root>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"root\":{\"x\":{\"@a\":\"1\",\"a\":\"2\"},\"y\":{\"@b\":\"3\",\"#text\":\"4\"}}}\\n)\n        end\n      end\n\n      it \"with mixed content\" do\n        run_binary(%(<root>x<y>z</y></root>), args: [\"-i\", \"xml\", \"-c\", \".root\"]) do |output|\n          output.should eq %({\"#text\":\"x\",\"y\":\"z\"}\\n)\n        end\n      end\n\n      it \"with an inline array\" do\n        run_binary(XML_INLINE_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"article\":{\"@key\":\"tr/ibm/RJ2144\",\"author\":[\"E. F. Codd\",\"Robert S. Arnold\",\"Jean-Marc Cadiou\",\"Chin-Liang Chang\",\"Nick Roussopoulos\"],\"title\":\"RENDEZVOUS Version 1: An Experimental English Language Query Formulation System for Casual Users of Relational Data Bases.\",\"journal\":\"IBM Research Report\",\"volume\":\"RJ2144\",\"month\":\"January\",\"year\":\"1978\",\"ee\":\"db/labs/ibm/RJ2144.html\",\"cdrom\":\"ibmTR/rj2144.pdf\"}}\\n)\n        end\n      end\n\n      it \"with a doctype\" do\n        run_binary(XML_DOCTYPE, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"dblp\":{\"mastersthesis\":{\"@key\":\"ms/Brown92\",\"author\":\"Kurt P. Brown\",\"title\":\"PRPL: A Database Workload Specification Language, v1.3.\",\"year\":\"1992\",\"school\":\"Univ. of Wisconsin-Madison\"}}}\\n)\n        end\n      end\n\n      it \"with CDATA\" do\n        run_binary(XML_CDATA, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"desc\":\"<message>Some Description</message>\"}\\n)\n        end\n      end\n\n      it \"with a prefixed key\" do\n        run_binary(%(<?xml version=\"1.0\"?><a:foo>bar</a:foo>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"a:foo\":\"bar\"}\\n)\n        end\n      end\n\n      describe \"with namespaces\" do\n        describe \"without --xmlns\" do\n          it \"retains prefixes but strips namespace declarations of a prefixed namespace\" do\n            run_binary(%(<?xml version=\"1.0\"?><a:foo xmlns:a=\"http://www.w3.org/1999/xhtml\">bar</a:foo>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"a:foo\":\"bar\"}\\n)\n            end\n          end\n\n          it \"does not add pefix if none was already present but strips namespace declarations\" do\n            run_binary(%(<?xml version=\"1.0\"?><foo xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:a=\"http://www.w3.org/1999/xhtml\">bar</foo>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"foo\":\"bar\"}\\n)\n            end\n          end\n\n          it \"adds namespace attribute properties only to declaring element and handles differentiating prefixed elements\" do\n            run_binary(XML_NESTED_NAMESPACES, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"root\":{\"a:foo\":\"herp\",\"foo\":{\"bar\":{\"baz\":null}}}}\\n)\n            end\n          end\n\n          it \"retains prefixes of scalar value elements\" do\n            run_binary(XML_NAMESPACE_PREFIXES, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"root\":{\"foo\":\"foo\",\"a:bar\":\"bar\"}}\\n)\n            end\n          end\n\n          describe \"with --xml-namespace-alias\" do\n            it \"should error\" do\n              run_binary(%(<?xml version=\"1.0\"?><a:foo xmlns:a=\"https://a-namespace\">bar</a:foo>), args: [\"-i\", \"xml\", \"-c\", \"--xml-namespace-alias\", \"aa=https://a-namespace\", \".\"], success: false) do |_, _, error|\n                error.should start_with \"oq error:\"\n              end\n            end\n          end\n        end\n\n        describe \"with --xmlns\" do\n          it \"creates a namespace attribute property\" do\n            run_binary(%(<?xml version=\"1.0\"?><a:foo xmlns:a=\"http://www.w3.org/1999/xhtml\">bar</a:foo>), args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"a:foo\":{\"@xmlns:a\":\"http://www.w3.org/1999/xhtml\",\"#text\":\"bar\"}}\\n)\n            end\n          end\n\n          it \"does not add pefix if none was already present and creates multiple namespace attribute properties\" do\n            run_binary(%(<?xml version=\"1.0\"?><foo xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:a=\"http://www.w3.org/1999/xhtml\">bar</foo>), args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"foo\":{\"@xmlns\":\"urn:oasis:names:tc:SAML:2.0:metadata\",\"@xmlns:a\":\"http://www.w3.org/1999/xhtml\",\"#text\":\"bar\"}}\\n)\n            end\n          end\n\n          it \"treats prefixed & unprefixed elements as unique elements\" do\n            run_binary(XML_NESTED_NAMESPACES, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"root\":{\"@xmlns:a\":\"https://a\",\"@xmlns\":\"https://b\",\"a:foo\":\"herp\",\"foo\":{\"bar\":{\"@xmlns\":\"https://c\",\"baz\":{\"@xmlns\":\"https://d\"}}}}}\\n)\n            end\n          end\n\n          it \"retains prefixes of scalar value elements and adds a namespace attribute property\" do\n            run_binary(XML_NAMESPACE_PREFIXES, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"root\":{\"@xmlns:a\":\"https://a\",\"foo\":\"foo\",\"a:bar\":\"bar\"}}\\n)\n            end\n          end\n\n          describe \"with --xml-namespace-alias\" do\n            it \"normalizes the provided namespace\" do\n              run_binary(%(<?xml version=\"1.0\"?><a:foo xmlns:a=\"https://a-namespace\">bar</a:foo>), args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \"--xml-namespace-alias\", \"aa=https://a-namespace\", \".\"]) do |output|\n                output.should eq %({\"aa:foo\":{\"@xmlns:aa\":\"https://a-namespace\",\"#text\":\"bar\"}}\\n)\n              end\n            end\n\n            it \"normalizes the default namespace\" do\n              run_binary(%(<?xml version=\"1.0\"?><foo xmlns=\"https://a-namespace\">bar</foo>), args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \"--xml-namespace-alias\", \"aa=https://a-namespace\", \".\"]) do |output|\n                output.should eq %({\"aa:foo\":{\"@xmlns:aa\":\"https://a-namespace\",\"#text\":\"bar\"}}\\n)\n              end\n            end\n\n            it \"normalizes multiple namespaces\" do\n              run_binary(XML_NESTED_NAMESPACES, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \"--xml-namespace-alias\", \"=https://a\", \"--xml-namespace-alias\", \"bb=https://b\", \".\"]) do |output|\n                output.should eq %({\"bb:root\":{\"@xmlns\":\"https://a\",\"@xmlns:bb\":\"https://b\",\"foo\":\"herp\",\"bb:foo\":{\"bar\":{\"@xmlns\":\"https://c\",\"baz\":{\"@xmlns\":\"https://d\"}}}}}\\n)\n              end\n            end\n          end\n        end\n      end\n    end\n\n    describe Array do\n      it \"of scalar values\" do\n        run_binary(XML_SCALAR_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"items\":{\"number\":[\"1\",\"2\",\"3\"]}}\\n)\n        end\n      end\n\n      it \"of scalar values with attribute\" do\n        run_binary(XML_SCALAR_ARRAY_WITH_ATTRIBUTE, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n          output.should eq %({\"items\":{\"number\":[\"1\",\"2\",{\"@foo\":\"bar\",\"#text\":\"3\"}]}}\\n)\n        end\n      end\n\n      describe \"of objects\" do\n        describe \"with no nested objects\" do\n          it \"should output correctly\" do\n            run_binary(XML_OBJECT_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"items\":{\"item\":[{\"flagID\":\"0\",\"itemID\":\"0\",\"locationID\":\"0\",\"ownerID\":\"0\",\"quantity\":\"-1\",\"typeID\":\"0\"},{\"flagID\":\"0\",\"itemID\":\"1\",\"locationID\":\"0\",\"ownerID\":\"0\",\"quantity\":\"-1\",\"typeID\":\"0\"}]}}\\n)\n            end\n          end\n        end\n\n        describe \"with an inline array\" do\n          it \"should output correctly\" do\n            run_binary(XML_INLINE_ARRAY_WITHIN_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"articles\":{\"article\":[{\"@key\":\"tr/dec/SRC1997-018\",\"year\":\"1997\",\"ee\":[\"db/labs/dec/SRC1997-018.html\",\"http://www.mcjones.org/System_R/SQL_Reunion_95/\"]},{\"@key\":\"tr/gte/TR-0263-08-94-165\",\"ee\":\"db/labs/gte/TR-0263-08-94-165.html\",\"year\":\"1994\"}]}}\\n)\n            end\n          end\n        end\n\n        describe \"with nested objects\" do\n          it \"should output correctly\" do\n            run_binary(XML_NESTED_OBJECT_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".root.listing\"]) do |output|\n              output.should eq %([{\"seller_info\":{\"seller_name\":\" cubsfantony\",\"seller_rating\":\" 848\"},\"payment_types\":\"Visa/MasterCard, Money Order/Cashiers Checks, Personal Checks, See item description for payment methods accepted\"},{\"seller_info\":{\"seller_name\":\" ct-inc\",\"seller_rating\":\" 403\"},\"payment_types\":\"Visa/MasterCard, Discover, Money Order/Cashiers Checks, Personal Checks, See item description for payment methods accepted\"}]\\n)\n            end\n          end\n        end\n      end\n\n      describe \"with object that has an attribute\" do\n        it \"should output correctly\" do\n          run_binary(XML_ATTRIBUTE_IN_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"jobs\":{\"ad\":[{\"salary\":{\"@currency\":\"CAD\",\"#text\":\"80000\"},\"working_hours\":\"full-time\"},{\"working_hours\":\"full-time\"}]}}\\n)\n          end\n        end\n      end\n\n      describe \"where array object element has an attribute\" do\n        it \"should output correctly\" do\n          run_binary(XML_ATTRIBUTE_IN_ARRAY_ROOT_ELEMENT, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"dblp\":{\"mastersthesis\":[{\"@key\":\"ms/Brown92\",\"author\":\"Kurt P. Brown\"},{\"@key\":\"ms/Yurek97\",\"author\":\"Tolga Yurek\"}]}}\\n)\n          end\n        end\n      end\n\n      describe \"with namespaces\" do\n        describe \"without --xmlns\" do\n          it \"treats prefixed & unprefixed elements as unique elements\" do\n            run_binary(XML_NAMESPACE_ARRAY, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"items\":{\"n:number\":[\"1\",\"2\"],\"number\":\"3\"}}\\n)\n            end\n          end\n\n          it \"ignores the namespace declaration\" do\n            run_binary(XML_NAMESPACE_ARRAY_SCALAR_VALUE_PREFIX, args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"items\":{\"n:number\":[\"1\",\"2\",\"3\"]}}\\n)\n            end\n          end\n        end\n\n        describe \"with --xmlns\" do\n          it \"treats prefixed & unprefixed elements as unique elements, adding namespace attribute property as needed\" do\n            run_binary(XML_NAMESPACE_ARRAY, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"items\":{\"@xmlns:n\":\"http://n\",\"n:number\":[\"1\",\"2\"],\"number\":{\"@xmlns\":\"http://default\",\"#text\":\"3\"}}}\\n)\n            end\n          end\n\n          it \"expands the scalar value to include a namespace attribute property\" do\n            run_binary(XML_NAMESPACE_ARRAY_SCALAR_VALUE_PREFIX, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \".\"]) do |output|\n              output.should eq %({\"items\":{\"@xmlns:n\":\"http://n\",\"n:number\":[\"1\",\"2\",{\"@xmlns\":\"http://default\",\"#text\":\"3\"}]}}\\n)\n            end\n          end\n\n          describe \"with --xml-namespace-alias\" do\n            it do\n              run_binary(XML_NAMESPACE_ARRAY, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \"--xml-namespace-alias\", \"num=http://n\", \".\"]) do |output|\n                output.should eq %({\"items\":{\"@xmlns:num\":\"http://n\",\"num:number\":[\"1\",\"2\"],\"number\":{\"@xmlns\":\"http://default\",\"#text\":\"3\"}}}\\n)\n              end\n            end\n\n            it do\n              run_binary(XML_NAMESPACE_ARRAY, args: [\"-i\", \"xml\", \"-c\", \"--xmlns\", \"--xml-namespace-alias\", \"=http://n\", \"--xml-namespace-alias\", \"d=http://default\", \".\"]) do |output|\n                output.should eq %({\"items\":{\"@xmlns\":\"http://n\",\"number\":[\"1\",\"2\"],\"d:number\":{\"@xmlns:d\":\"http://default\",\"#text\":\"3\"}}}\\n)\n              end\n            end\n          end\n        end\n      end\n\n      describe \"with a single element\" do\n        it \"without --xml-force-array\" do\n          run_binary(%(<foo><item/></foo>), args: [\"-i\", \"xml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"foo\":{\"item\":null}}\\n)\n          end\n        end\n\n        describe \"with --xml-force-array\" do\n          it \"force parses it as an array\" do\n            run_binary(%(<foo><item/></foo>), args: [\"-i\", \"xml\", \"--xml-force-array\", \"item\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"foo\":{\"item\":[null]}}\\n)\n            end\n          end\n\n          it \"with an attribute\" do\n            run_binary(%(<foo><item id=\"1\"/></foo>), args: [\"-i\", \"xml\", \"--xml-force-array\", \"item\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"foo\":{\"item\":[{\"@id\":\"1\"}]}}\\n)\n            end\n          end\n\n          it \"with a namespace\" do\n            run_binary(%(<foo><item xmlns=\"https://ns\"/></foo>), args: [\"-i\", \"xml\", \"--xmlns\", \"--xml-force-array\", \"item\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"foo\":{\"item\":[{\"@xmlns\":\"https://ns\"}]}}\\n)\n            end\n          end\n\n          it \"with an aliased namespace\" do\n            run_binary(%(<foo><i:item xmlns:i=\"https://ns\"/></foo>), args: [\"-i\", \"xml\", \"--xmlns\", \"--xml-force-array\", \"item:item\", \"--xml-namespace-alias\", \"item=https://ns\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"foo\":{\"item:item\":[{\"@xmlns:item\":\"https://ns\"}]}}\\n)\n            end\n          end\n        end\n      end\n    end\n  end\n\n  describe \".serialize\" do\n    it \"allows not emitting the xml prolog\" do\n      run_binary(\"1\", args: [\"-o\", \"xml\", \"--no-prolog\", \".\"]) do |output|\n        output.should eq(<<-XML\n          <root>1</root>\\n\n          XML\n        )\n      end\n    end\n\n    describe \"allows setting the root element\" do\n      describe \"to another string\" do\n        it \"should use the provided name\" do\n          run_binary(\"1\", args: [\"-o\", \"xml\", \"--xml-root\", \"foo\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <foo>1</foo>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      describe \"to an empty string\" do\n        it \"should not be emitted\" do\n          run_binary(\"1\", args: [\"-o\", \"xml\", \"--xml-root\", \"\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              1\n              XML\n            )\n          end\n        end\n      end\n    end\n\n    describe \"it allows changing the array item name\" do\n      describe \"with a single nesting level\" do\n        it \"should emit item tags for non empty values\" do\n          run_binary(%([\"x\",{}]), args: [\"-o\", \"xml\", \"--xml-item\", \"foo\", \".\"]) do |output|\n            output.should eq(<<-XML\n                <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n                <root>\n                  <foo>x</foo>\n                  <foo/>\n                </root>\\n\n                XML\n            )\n          end\n        end\n      end\n\n      describe \"with a larger nesting level\" do\n        it \"should emit item tags for non empty values\" do\n          run_binary(%({\"a\":[[]]}), args: [\"-o\", \"xml\", \"--xml-item\", \"foo\", \".\"]) do |output|\n            output.should eq(<<-XML\n                <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n                <root>\n                  <a/>\n                </root>\\n\n                XML\n            )\n          end\n        end\n      end\n    end\n\n    describe \"it allows changing the indent\" do\n      describe \"more spaces\" do\n        it \"should emit the extra spaces\" do\n          run_binary(%({\"name\": \"Jim\", \"age\": 12}), args: [\"-o\", \"xml\", \"--indent\", \"4\", \".\"]) do |output|\n            output.should eq(<<-XML\n                <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n                <root>\n                    <name>Jim</name>\n                    <age>12</age>\n                </root>\\n\n                XML\n            )\n          end\n        end\n      end\n\n      describe \"to tabs\" do\n        it \"should emit the indent as tabs\" do\n          run_binary(%({\"name\": \"Jim\", \"age\": 12}), args: [\"-o\", \"xml\", \"--indent\", \"3\", \"--tab\", \".\"]) do |output|\n            output.should eq(<<-XML\n                <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n                <root>\n                \\t\\t\\t<name>Jim</name>\n                \\t\\t\\t<age>12</age>\n                </root>\\n\n                XML\n            )\n          end\n        end\n      end\n    end\n\n    describe String do\n      describe \"not blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"Jim\"), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>Jim</root>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      describe \"blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"\"), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root></root>\\n\n            XML\n            )\n          end\n        end\n      end\n\n      describe \"with HTML content\" do\n        it \"should escape the HTMl content\" do\n          run_binary(%({\"x\":\"<p>Hello World!</p>\"}), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <x>&lt;p&gt;Hello World!&lt;/p&gt;</x>\n              </root>\\n\n              XML\n            )\n          end\n        end\n\n        it \"should be wrapped in CDATA if the json key starts with '!'\" do\n          run_binary(%({\"!x\":\"<p>Hello World!</p>\"}), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <x><![CDATA[<p>Hello World!</p>]]></x>\n              </root>\\n\n              XML\n            )\n          end\n        end\n\n        it \"should produce an empty CDATA if the json key starts with '!' and the value is null\" do\n          run_binary(%({\"!x\":null}), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <x><![CDATA[]]></x>\n              </root>\\n\n              XML\n            )\n          end\n        end\n      end\n    end\n\n    describe Bool do\n      it \"should output correctly\" do\n        run_binary(%(true), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>true</root>\\n\n            XML\n          )\n        end\n      end\n    end\n\n    describe Float do\n      it \"should output correctly\" do\n        run_binary(%(\"1.5\"), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>1.5</root>\\n\n            XML\n          )\n        end\n      end\n    end\n\n    describe Nil do\n      it \"should output correctly\" do\n        run_binary(\"null\", args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root/>\\n\n            XML\n          )\n        end\n      end\n    end\n\n    describe Array do\n      describe \"empty array on root\" do\n        it \"should emit a self closing root tag\" do\n          run_binary(\"[]\", args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root/>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      describe \"array with values on root\" do\n        it \"should emit item tags for non empty values\" do\n          run_binary(%([\"x\",{}]), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <item>x</item>\n                <item/>\n              </root>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      describe \"object with empty array/values\" do\n        it \"should emit self closing tags for each\" do\n          run_binary(%({\"a\":[],\"b\":{},\"c\":null}), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <b/>\n                <c/>\n              </root>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      describe \"2D array object value\" do\n        it \"should emit key name tag then self closing item tag\" do\n          run_binary(%({\"a\":[[]]}), args: [\"-o\", \"xml\", \".\"]) do |output|\n            output.should eq(<<-XML\n              <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n              <root>\n                <a/>\n              </root>\\n\n              XML\n            )\n          end\n        end\n      end\n\n      it \"object value mixed/nested array values\" do\n        run_binary(%({\"x\":[1,[2,[3]]]}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <x>1</x>\n              <x>\n                <item>2</item>\n                <item>\n                  <item>3</item>\n                </item>\n              </x>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"object value array primitive values\" do\n        run_binary(%({\"x\":[1,2,3]}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <x>1</x>\n              <x>2</x>\n              <x>3</x>\n            </root>\\n\n            XML\n          )\n        end\n      end\n    end\n\n    describe Object do\n      it \"simple key/value\" do\n        run_binary(%({\"name\":\"Jim\"}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"nested object\" do\n        run_binary(%({\"name\":\"Jim\", \"city\": {\"street\":\"forbs\"}}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n              <city>\n                <street>forbs</street>\n              </city>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"with an attribute\" do\n        run_binary(%({\"name\":\"Jim\", \"city\": {\"@street\":\"forbs\"}}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n              <city street=\"forbs\"/>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"with an attribute and #text\" do\n        run_binary(%({\"name\":\"Jim\", \"city\": {\"@street\":\"forbs\", \"#text\": \"Atlantic\"}}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n              <city street=\"forbs\">Atlantic</city>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"with attributes\" do\n        run_binary(%({\"name\":\"Jim\", \"city\": {\"@street\":\"forbs\", \"@post\": 123}}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n              <city street=\"forbs\" post=\"123\"/>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"with attributes and #text\" do\n        run_binary(%({\"name\":\"Jim\", \"city\": {\"@street\":\"forbs\", \"@post\": 123, \"#text\": \"Atlantic\"}}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <name>Jim</name>\n              <city street=\"forbs\" post=\"123\">Atlantic</city>\n            </root>\\n\n            XML\n          )\n        end\n      end\n\n      it \"with a prefixed key\" do\n        run_binary(%({\"foo:name\":\"Jim\"}), args: [\"-o\", \"xml\", \".\"]) do |output|\n          output.should eq(<<-XML\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <root>\n              <foo:name>Jim</foo:name>\n            </root>\\n\n            XML\n          )\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/converters/yaml_spec.cr",
    "content": "require \"../spec_helper\"\n\nLITERAL_BLOCK = <<-YAML\n---\nliteral_block: |\n    This entire block of text will be the value of the 'literal_block' key,\n    with line breaks being preserved.\n\n    The literal continues until de-dented, and the leading indentation is\n    stripped.\n\n        Any lines that are 'more-indented' keep the rest of their indentation -\n        these lines will be indented by 4 spaces.\nYAML\n\nFOLDED_BLOCK = <<-YAML\nfolded_style: >\n    This entire block of text will be the value of 'folded_style', but this\n    time, all newlines will be replaced with a single space.\n\n    Blank lines, like above, are converted to a newline character.\n\n        'More-indented' lines keep their newlines, too -\n        this text will appear over two lines.\nYAML\n\nNESTED_OBJECT = <<-YAML\na_nested_map:\n  key: value\n  another_key: Another Value\n  another_nested_map:\n    hello: hello\nYAML\n\nCOMPLEX_MAPPING_KEY = <<-YAML\n? |\n  This is a key\n  that has multiple lines\n: and this is its value\nYAML\n\nCOMPLEX_SEQUENCE_KEY = <<-YAML\n? - Manchester United\n  - Real Madrid\n: [2001-01-01, 2002-02-02]\nYAML\n\nNESTED_ARRAY = <<-YAML\na_sequence:\n  - Item 1\n  - Item 2\n  - 0.5  # sequences can contain disparate types.\n  - Item 4\n  - key: value\n    another_key: another_value\n  -\n    - This is a sequence\n    - inside another sequence\n  - - - Nested sequence indicators\n      - can be collapsed\nYAML\n\nANCHORS = <<-YAML\nbase: &base\n  name: Everyone has same name\nfoo: &foo\n  <<: *base\n  age: 10\nbar: &bar\n  <<: *base\n  age: 20\nYAML\n\ndescribe OQ::Converters::YAML do\n  describe \".deserialize\" do\n    describe String do\n      describe \"not blank\" do\n        it \"should output correctly\" do\n          run_binary(%(--- Jim), args: [\"-i\", \"yaml\", \".\"]) do |output|\n            output.should eq %(\"Jim\"\\n)\n          end\n        end\n      end\n\n      describe \"blank\" do\n        it \"should output correctly\" do\n          run_binary(%(--- ), args: [\"-i\", \"yaml\", \".\"]) do |output|\n            output.should eq \"null\\n\"\n          end\n        end\n      end\n\n      describe \"with a tag\" do\n        it \"should output correctly\" do\n          run_binary(%(--- !!str 0.5), args: [\"-i\", \"yaml\", \".\"]) do |output|\n            output.should eq %(\"0.5\"\\n)\n          end\n        end\n      end\n\n      describe \"that is single quoted\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nhowever: 'foobar'), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"however\":\"foobar\"}\\n)\n          end\n        end\n      end\n\n      describe \"that is double quoted\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nhowever: \"foobar\"), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"however\":\"foobar\"}\\n)\n          end\n        end\n      end\n\n      describe \"literal block\" do\n        it \"should output correctly\" do\n          run_binary(LITERAL_BLOCK, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"literal_block\":\"This entire block of text will be the value of the 'literal_block' key,\\\\nwith line breaks being preserved.\\\\n\\\\nThe literal continues until de-dented, and the leading indentation is\\\\nstripped.\\\\n\\\\n    Any lines that are 'more-indented' keep the rest of their indentation -\\\\n    these lines will be indented by 4 spaces.\"}\\n)\n          end\n        end\n      end\n\n      describe \"folded block\" do\n        it \"should output correctly\" do\n          run_binary(FOLDED_BLOCK, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"folded_style\":\"This entire block of text will be the value of 'folded_style', but this time, all newlines will be replaced with a single space.\\\\nBlank lines, like above, are converted to a newline character.\\\\n\\\\n    'More-indented' lines keep their newlines, too -\\\\n    this text will appear over two lines.\"}\\n)\n          end\n        end\n      end\n    end\n\n    describe Bool do\n      it \"should output correctly\" do\n        run_binary(%(--- true), args: [\"-i\", \"yaml\", \".\"]) do |output|\n          output.should eq \"true\\n\"\n        end\n      end\n    end\n\n    describe Float do\n      it \"should output correctly\" do\n        run_binary(%(--- 10.50), args: [\"-i\", \"yaml\", \".\"]) do |output|\n          output.should eq \"10.5\\n\"\n        end\n      end\n    end\n\n    describe Nil do\n      it \"should output correctly\" do\n        run_binary(%(--- ), args: [\"-i\", \"yaml\", \".\"]) do |output|\n          output.should eq \"null\\n\"\n        end\n      end\n    end\n\n    describe Object do\n      describe \"a simple object\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nname: Jim), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"name\":\"Jim\"}\\n)\n          end\n        end\n      end\n\n      describe \"with spaces in the key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nkey with spaces: value), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"key with spaces\":\"value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with a quoted key key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\n'Keys can be quoted too.': value), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"Keys can be quoted too.\":\"value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with nested object\" do\n        it \"should output correctly\" do\n          run_binary(NESTED_OBJECT, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"a_nested_map\":{\"key\":\"value\",\"another_key\":\"Another Value\",\"another_nested_map\":{\"hello\":\"hello\"}}}\\n)\n          end\n        end\n      end\n\n      describe \"with a non string key\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\n0.25: a float key), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"0.25\":\"a float key\"}\\n)\n          end\n        end\n      end\n\n      describe \"with JSON syntax\" do\n        describe \"with quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: {\"key\": \"value\"}), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":{\"key\":\"value\"}}\\n)\n            end\n          end\n        end\n\n        describe \"without quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: {key: value}), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":{\"key\":\"value\"}}\\n)\n            end\n          end\n        end\n      end\n\n      describe \"with a complex mapping key\" do\n        it \"should output correctly\" do\n          run_binary(COMPLEX_MAPPING_KEY, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"This is a key\\\\nthat has multiple lines\\\\n\":\"and this is its value\"}\\n)\n          end\n        end\n      end\n\n      describe \"with set notation\" do\n        it \"should output correctly\" do\n          run_binary(%(---\\nset:\\n  ? item1\\n  ? item2), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"set\":{\"item1\":null,\"item2\":null}}\\n)\n          end\n        end\n      end\n\n      pending \"with a complex sequence key\" do\n        it \"should output correctly\" do\n          run_binary(COMPLEX_SEQUENCE_KEY, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"[\"Manchester United\", \"Real Madrid\"]\":[\"2001-01-01T00:00:00Z\",\"2002-02-02T00:00:00Z\"]}\\n)\n          end\n        end\n      end\n\n      describe \"with anchors\" do\n        it \"should output correctly\" do\n          run_binary(ANCHORS, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"base\":{\"name\":\"Everyone has same name\"},\"foo\":{\"name\":\"Everyone has same name\",\"age\":10},\"bar\":{\"name\":\"Everyone has same name\",\"age\":20}}\\n)\n          end\n        end\n      end\n    end\n\n    describe Array do\n      describe \"with mixed/nested array values\" do\n        it \"should output correctly\" do\n          run_binary(NESTED_ARRAY, args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n            output.should eq %({\"a_sequence\":[\"Item 1\",\"Item 2\",0.5,\"Item 4\",{\"key\":\"value\",\"another_key\":\"another_value\"},[\"This is a sequence\",\"inside another sequence\"],[[\"Nested sequence indicators\",\"can be collapsed\"]]]}\\n)\n          end\n        end\n      end\n\n      describe \"with JSON syntax\" do\n        describe \"with quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: [3, 2, 1, \"takeoff\"]), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":[3,2,1,\"takeoff\"]}\\n)\n            end\n          end\n        end\n\n        describe \"without quotes\" do\n          it \"should output correctly\" do\n            run_binary(%(---\\njson_seq: [3, 2, 1, takeoff]), args: [\"-i\", \"yaml\", \"-c\", \".\"]) do |output|\n              output.should eq %({\"json_seq\":[3,2,1,\"takeoff\"]}\\n)\n            end\n          end\n        end\n      end\n    end\n  end\n\n  describe \".serialize\" do\n    describe String do\n      describe \"not blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"Jim\"), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should start_with <<-YAML\n            --- Jim\n            YAML\n          end\n        end\n      end\n\n      describe \"blank\" do\n        it \"should output correctly\" do\n          run_binary(%(\"\"), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              --- \"\"\\n\n              YAML\n            )\n          end\n        end\n      end\n    end\n\n    describe Bool do\n      it \"should output correctly\" do\n        run_binary(%(true), args: [\"-o\", \"yaml\", \".\"]) do |output|\n          output.should start_with <<-YAML\n            --- true\n            YAML\n        end\n      end\n    end\n\n    describe Float do\n      it \"should output correctly\" do\n        run_binary(%(\"1.5\"), args: [\"-o\", \"yaml\", \".\"]) do |output|\n          output.should eq(<<-YAML\n            --- \"1.5\"\\n\n            YAML\n          )\n        end\n      end\n    end\n\n    describe Nil do\n      it \"should output correctly\" do\n        run_binary(\"null\", args: [\"-o\", \"yaml\", \".\"]) do |output|\n          output.should start_with \"---\"\n        end\n      end\n    end\n\n    describe Array do\n      describe \"empty array on root\" do\n        it \"should emit a self closing root tag\" do\n          run_binary(\"[]\", args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              --- []\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"array with values on root\" do\n        it \"should emit item tags for non empty values\" do\n          run_binary(%([\"x\",{}]), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              - x\n              - {}\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object with empty array/values\" do\n        it \"should emit self closing tags for each\" do\n          run_binary(%({\"a\":[],\"b\":{},\"c\":null}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should start_with <<-YAML\n              ---\n              a: []\n              b: {}\n              c:\n              YAML\n          end\n        end\n      end\n\n      describe \"2D array object value\" do\n        it \"should emit key name tag then self closing item tag\" do\n          run_binary(%({\"a\":[[]]}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              a:\n              - []\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object value mixed/nested array values\" do\n        it \"should emit correctly\" do\n          run_binary(%({\"x\":[1,[2,[3]]]}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              x:\n              - 1\n              - - 2\n                - - 3\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"object value array primitive values\" do\n        it \"should emit correctly\" do\n          run_binary(%({\"x\":[1,2,3]}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              x:\n              - 1\n              - 2\n              - 3\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"when the jq filter doesn't return data\" do\n        it \"should return an empty string\" do\n          run_binary(%([{\"name\":\"foo\"}]), args: [\"-i\", \"yaml\", \"-o\", \"yaml\", %<.[] | select(.name != \"foo\")>]) do |output|\n            output.should be_empty\n          end\n        end\n      end\n    end\n\n    describe Object do\n      describe \"simple key/value\" do\n        it \"should output correctly\" do\n          run_binary(%({\"name\":\"Jim\"}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              name: Jim\\n\n              YAML\n            )\n          end\n        end\n      end\n\n      describe \"nested object\" do\n        it \"should output correctly\" do\n          run_binary(%({\"name\":\"Jim\", \"city\": {\"street\":\"forbs\"}}), args: [\"-o\", \"yaml\", \".\"]) do |output|\n            output.should eq(<<-YAML\n              ---\n              name: Jim\n              city:\n                street: forbs\\n\n              YAML\n            )\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/format_spec.cr",
    "content": "require \"./spec_helper\"\n\ndescribe OQ::Format do\n  describe \".to_s\" do\n    it \"returns a comma separated list of the formats\" do\n      OQ::Format.to_s.should eq \"json, simpleyaml, xml, yaml\"\n    end\n  end\nend\n"
  },
  {
    "path": "spec/oq_spec.cr",
    "content": "require \"./spec_helper\"\n\nprivate SIMPLE_JSON_OBJECT = <<-JSON\n{\n  \"name\": \"Jim\"\n}\nJSON\n\nprivate NESTED_JSON_OBJECT = <<-JSON\n{\"foo\":{\"bar\":{\"baz\":5}}}\nJSON\n\nprivate ARRAY_JSON_OBJECT = <<-JSON\n{\"names\":[1,2,3]}\nJSON\n\ndescribe OQ do\n  describe \"when given a filter file\" do\n    it \"should return the correct output\" do\n      run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-f\", \"spec/assets/test_filter\"]) do |output|\n        output.should eq %(\"Jim\"\\n)\n      end\n    end\n  end\n\n  it \"with a simple filter\" do\n    run_binary(input: SIMPLE_JSON_OBJECT, args: [\".name\"]) do |output|\n      output.should eq %(\"Jim\"\\n)\n    end\n  end\n\n  it \"with a filter to get nested values\" do\n    run_binary(input: NESTED_JSON_OBJECT, args: [\".foo.bar.baz\"]) do |output|\n      output.should eq \"5\\n\"\n    end\n  end\n\n  it \"should colorize the output with the -C option\" do\n    run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-c\", \"-C\", \".\"]) do |output|\n      output.should start_with \"\\e\"\n      output.should contain %(\"name\")\n      output.should contain %(\"Jim\")\n      output.should end_with \"\\e[0m\\n\"\n    end\n  end\n\n  describe \"with a non-JSON output format\" do\n    it \"should convert the JSON to that format\" do\n      run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-o\", \"yaml\", \".\"]) do |output|\n        output.should eq \"---\\nname: Jim\\n\"\n      end\n    end\n\n    describe \"with the -C option\" do\n      it \"should remove the -C option\" do\n        run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-o\", \"yaml\", \"-C\", \".\"]) do |output|\n          output.should eq \"---\\nname: Jim\\n\"\n        end\n      end\n    end\n  end\n\n  describe \"files\" do\n    describe \"with a file input\" do\n      it \"should return the correct output\" do\n        run_binary(args: [\".\", \"spec/assets/data1.json\"]) do |output|\n          output.should eq \"#{SIMPLE_JSON_OBJECT}\\n\"\n        end\n      end\n    end\n\n    describe \"with multiple JSON file input\" do\n      it \"raw data\" do\n        run_binary(args: [\"-c\", \".\", \"spec/assets/data1.json\", \"spec/assets/data2.json\"]) do |output|\n          output.should eq %({\"name\":\"Jim\"}\\n{\"name\":\"Bob\"}\\n)\n        end\n      end\n\n      it \"--slurp\" do\n        run_binary(args: [\"-c\", \"--slurp\", \".\", \"spec/assets/data1.json\", \"spec/assets/data2.json\"]) do |output|\n          output.should eq %([{\"name\":\"Jim\"},{\"name\":\"Bob\"}]\\n)\n        end\n      end\n    end\n\n    describe \"with multiple non JSON file input\" do\n      it \"raw data\" do\n        run_binary(args: [\"-i\", \"yaml\", \"-c\", \".\", \"spec/assets/data1.yml\", \"spec/assets/data2.yml\"]) do |output|\n          output.should eq %({\"name\":\"Jim\"}\\n{\"age\":17,\"name\":\"Fred\"}\\n)\n        end\n      end\n\n      it \"--slurp\" do\n        run_binary(args: [\"-i\", \"yaml\", \"-c\", \"--slurp\", \".\", \"spec/assets/data1.yml\", \"spec/assets/data2.yml\"]) do |output|\n          output.should eq %([{\"name\":\"Jim\"},{\"age\":17,\"name\":\"Fred\"}]\\n)\n        end\n      end\n    end\n\n    it \"with multiple --arg\" do\n      run_binary(args: [\"-c\", \"-r\", \"--arg\", \"chart\", \"stolon\", \"--arg\", \"version\", \"1.5.10\", \"$version\", \"spec/assets/data1.json\"]) do |output|\n        output.should eq %(1.5.10\\n)\n      end\n    end\n  end\n\n  it \"should minify the output with the -c option\" do\n    run_binary(input: NESTED_JSON_OBJECT, args: [\"-c\", \".\"]) do |output|\n      output.should eq %({\"foo\":{\"bar\":{\"baz\":5}}}\\n)\n    end\n  end\n\n  it \"should format the output without the -c option\" do\n    run_binary(input: NESTED_JSON_OBJECT, args: [\".\"]) do |output|\n      output.should eq(<<-JSON\n        {\n          \"foo\": {\n            \"bar\": {\n              \"baz\": 5\n            }\n          }\n        }\\n\n        JSON\n      )\n    end\n  end\n\n  describe \"with null input option\" do\n    describe \"with a scalar value\" do\n      it \"should return the correct output\" do\n        run_binary(args: [\"-n\", \"0\"]) do |output|\n          output.should eq \"0\\n\"\n        end\n      end\n\n      it \"should return the correct output\" do\n        run_binary(args: [\"--null-input\", \"0\"]) do |output|\n          output.should eq \"0\\n\"\n        end\n      end\n    end\n\n    describe \"with a JSON object string\" do\n      it \"should return the correct output\" do\n        run_binary(args: [\"-cn\", %([{\"foo\":\"bar\"},{\"foo\":\"baz\"}])]) do |output|\n          output.should eq %([{\"foo\":\"bar\"},{\"foo\":\"baz\"}]\\n)\n        end\n      end\n    end\n\n    describe \"with input from STDIN\" do\n      it \"should return the correct output\" do\n        run_binary(input: \"foo\", args: [\"-n\", \".\"]) do |output|\n          output.should eq \"null\\n\"\n        end\n      end\n    end\n\n    it \"should not block waiting for input\" do\n      run_binary(input: Process::Redirect::Inherit, args: [\"-n\", \".\"]) do |output|\n        output.should eq \"null\\n\"\n      end\n    end\n  end\n\n  describe \"with a custom indent value with JSON\" do\n    it \"should return the correct output\" do\n      run_binary(input: SIMPLE_JSON_OBJECT, args: [\"--indent\", \"1\", \".\"]) do |output|\n        output.should eq %({\\n \"name\": \"Jim\"\\n}\\n)\n      end\n    end\n  end\n\n  describe \"when streaming input\" do\n    it \"should return the correct output\" do\n      run_binary(input: %({\"a\": [1, 2.2, true, \"abc\", null]}), args: [\"-nc\", \"--stream\", \"fromstream( 1|truncate_stream(inputs) |  select(length>1) | .[0] |= .[1:] )\"]) do |output|\n        output.should eq %(1\\n2.2\\ntrue\\n\"abc\"\\nnull\\n)\n      end\n    end\n  end\n\n  describe \"when using 'input'\" do\n    it \"should return the correct output\" do\n      run_binary(args: [\"-cn\", \"-f\", \"spec/assets/stream-filter\", \"spec/assets/stream-data.json\"]) do |output|\n        output.should eq %({\"possible_victim01\":{\"total\":3,\"evildoers\":{\"evil.com\":2,\"soevil.com\":1}},\"possible_victim02\":{\"total\":1,\"evildoers\":{\"bad.com\":1}},\"possible_victim03\":{\"total\":1,\"evildoers\":{\"soevil.com\":1}}}\\n)\n      end\n    end\n  end\n\n  describe \"with the -L option\" do\n    it \"should be passed correctly without a space\" do\n      run_binary(args: [\"-n\", \"-L#{__DIR__}/assets\", %(import \"test\" as test; 9 | test::increment)]) do |output|\n        output.should eq %(10\\n)\n      end\n    end\n\n    it \"should be passed correctly with a space\" do\n      run_binary(args: [\"-n\", \"-L\", \"#{__DIR__}/assets\", %(import \"test\" as test; 9 | test::increment)]) do |output|\n        output.should eq %(10\\n)\n      end\n    end\n  end\n\n  describe \"--arg\" do\n    it \"single arg\" do\n      run_binary(args: [\"-cn\", \"--arg\", \"foo\", \"bar\", %({\"name\":$foo})]) do |output|\n        output.should eq %({\"name\":\"bar\"}\\n)\n      end\n    end\n\n    it \"multiple arg\" do\n      run_binary(args: [\"-rcn\", \"-r\", \"--arg\", \"chart\", \"stolon\", \"--arg\", \"version\", \"1.5.10\", \"$version\"]) do |output|\n        output.should eq %(1.5.10\\n)\n      end\n    end\n\n    it \"different option in between args\" do\n      run_binary(args: [\"-rcn\", \"--arg\", \"chart\", \"stolon\", \"--arg\", \"version\", \"1.5.10\", \"$version\"]) do |output|\n        output.should eq %(1.5.10\\n)\n      end\n    end\n\n    it \"when the arg name matches a directory name\" do\n      run_binary(args: [\"-rcn\", \"--arg\", \"spec\", \"dir\", \"$spec\"]) do |output|\n        output.should eq %(dir\\n)\n      end\n    end\n  end\n\n  describe \"with the --argjson option\" do\n    it \"should be passed correctly\" do\n      run_binary(args: [\"-rcn\", \"--argjson\", \"foo\", \"123\", %({\"id\":$foo})]) do |output|\n        output.should eq %({\"id\":123}\\n)\n      end\n    end\n\n    it \"when the arg name matches a directory name\" do\n      run_binary(args: [\"-rcn\", \"--argjson\", \"spec\", \"123\", \"$spec\"]) do |output|\n        output.should eq %(123\\n)\n      end\n    end\n  end\n\n  describe \"with the --slurpfile option\" do\n    it \"should be passed correctly\" do\n      run_binary(args: [\"-rcn\", \"--slurpfile\", \"ids\", \"spec/assets/raw.json\", %({\"ids\":$ids})]) do |output|\n        output.should eq %({\"ids\":[1,2,3]}\\n)\n      end\n    end\n  end\n\n  describe \"with the --rawfile option\" do\n    it \"should be passed correctly\" do\n      run_binary(args: [\"-rcn\", \"--rawfile\", \"ids\", \"spec/assets/raw.json\", %({\"ids\":$ids})]) do |output|\n        output.should eq %({\"ids\":\"1\\\\n2\\\\n3\\\\n\"}\\n)\n      end\n    end\n  end\n\n  describe \"with the --args option\" do\n    it \"should be passed correctly\" do\n      run_binary(args: [\"-rcn\", %({\"ids\":$ARGS.positional}), \"--args\", \"1\", \"2\", \"3\"]) do |output|\n        output.should eq %({\"ids\":[\"1\",\"2\",\"3\"]}\\n)\n      end\n    end\n  end\n\n  describe \"with the --jsonargs option\" do\n    it \"should be passed correctly\" do\n      run_binary(args: [\"-rcn\", %({\"ids\":$ARGS.positional}), \"--jsonargs\", \"1\", \"2\", \"3\"]) do |output|\n        output.should eq %({\"ids\":[1,2,3]}\\n)\n      end\n    end\n  end\n\n  describe \"when there is a jq error\" do\n    it \"should return the error and correct exit code\" do\n      run_binary(input: ARRAY_JSON_OBJECT, args: [\".names | .[] | .name\"], success: false) do |_, _, error|\n        error.should eq %(jq: error (at <stdin>:0): Cannot index number with string \"name\"\\n)\n      end\n    end\n  end\n\n  describe \"with an invalid input format\" do\n    it \"should return the error and correct exit code\" do\n      run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-i\", \"foo\"], success: false) do |_, _, error|\n        error.should eq %(Invalid input format: 'foo'\\n)\n      end\n    end\n  end\n\n  describe \"with an invalid output format\" do\n    it \"should return the error and correct exit code\" do\n      run_binary(input: SIMPLE_JSON_OBJECT, args: [\"-o\", \"foo\"], success: false) do |_, _, error|\n        error.should eq %(Invalid output format: 'foo'\\n)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/processor_spec.cr",
    "content": "require \"./spec_helper\"\n\ndescribe OQ::Processor do\n  describe \"custom IOs\" do\n    it \"works with \\\"STDIN\\\" input\" do\n      input_io = IO::Memory.new %({\"name\":\"Jim\"})\n      output_io = IO::Memory.new\n\n      OQ::Processor.new.process input_args: [\".name\"], input: input_io, output: output_io\n\n      output_io.to_s.should eq %(\"Jim\"\\n)\n    end\n\n    it \"works with custom error output\" do\n      input_io = IO::Memory.new %({\"name:\"Jim\"})\n      output_io = IO::Memory.new\n      error_io = IO::Memory.new\n\n      expect_raises RuntimeError do\n        OQ::Processor.new.process input_args: [\".name\"], input: input_io, output: output_io, error: error_io\n      end\n\n      output_io.to_s.should be_empty\n      error_io.to_s.should contain \"parse error: Invalid numeric literal at line 1, column 12\\n\"\n    end\n\n    describe \"file input\" do\n      it \"single file\" do\n        output_io = IO::Memory.new\n\n        OQ::Processor.new.process input_args: [\".\", \"-c\", \"spec/assets/data1.json\"], output: output_io\n\n        output_io.to_s.should eq %({\"name\":\"Jim\"}\\n)\n      end\n\n      it \"single file, standard input IO\" do\n        input_io = IO::Memory.new\n        output_io = IO::Memory.new\n\n        OQ::Processor.new.process input_args: [\".\", \"-c\", \"spec/assets/data1.json\"], input: input_io, output: output_io\n\n        output_io.to_s.should eq %({\"name\":\"Jim\"}\\n)\n      end\n\n      it \"multiple file\" do\n        output_io = IO::Memory.new\n\n        OQ::Processor.new.process input_args: [\".\", \"-c\", \"spec/assets/data1.json\", \"spec/assets/data2.json\"], output: output_io\n\n        output_io.to_s.should eq %({\"name\":\"Jim\"}\\n{\"name\":\"Bob\"}\\n)\n      end\n\n      it \"multiple files and --slurp\" do\n        output_io = IO::Memory.new\n\n        OQ::Processor.new.process input_args: [\".\", \"-c\", \"-s\", \"spec/assets/data1.json\", \"spec/assets/data2.json\"], output: output_io\n\n        output_io.to_s.should eq %([{\"name\":\"Jim\"},{\"name\":\"Bob\"}]\\n)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/spec_helper.cr",
    "content": "require \"spec\"\nrequire \"../src/oq\"\n\n# Runs the binary with the given *name* and *args*.\ndef run_binary(input : String | Process::Redirect | Nil = nil, name : String = \"bin/oq\", args : Array(String) = [] of String, *, success : Bool = true, file = __FILE__, line = __LINE__, & : String, Process::Status, String -> Nil)\n  buffer_io = IO::Memory.new\n  error_io = IO::Memory.new\n  input_io = IO::Memory.new\n\n  if input.is_a? Process::Redirect\n    input_io = input\n  else\n    input_io << input if input\n    input_io = input_io.rewind\n  end\n\n  status = Process.run(name, args, output: buffer_io, input: input_io, error: error_io)\n\n  if success\n    status.success?.should be_true, file: file, line: line, failure_message: error_io.to_s\n  else\n    status.success?.should_not be_true, file: file, line: line, failure_message: error_io.to_s\n  end\n\n  yield buffer_io.to_s, status, error_io.to_s\nend\n"
  },
  {
    "path": "src/converters/json.cr",
    "content": "# Converter for the `OQ::Format::JSON` format.\nmodule OQ::Converters::JSON\n  def self.deserialize(input : IO, output : IO) : Nil\n    IO.copy input, output\n  end\n\n  def self.serialize(input : IO, output : IO) : Nil\n    IO.copy input, output\n  end\nend\n"
  },
  {
    "path": "src/converters/processor_aware.cr",
    "content": "# :nodoc:\n#\n# Denotes a converter exposes the related `OQ::Processor`\n# instance in order to read configuration options off of it.\nmodule OQ::Converters::ProcessorAware\n  macro extended\n    class_property! processor : OQ::Processor\n  end\nend\n"
  },
  {
    "path": "src/converters/simple_yaml.cr",
    "content": "require \"./yaml\"\n\n# Converter for the `OQ::Format::SimpleYAML` format.\nmodule OQ::Converters::SimpleYAML\n  extend OQ::Converters::YAML\n  extend self\n\n  # ameba:disable Metrics/CyclomaticComplexity\n  def deserialize(input : IO, output : IO) : Nil\n    yaml = ::YAML::PullParser.new(input)\n    json = ::JSON::Builder.new(output)\n\n    yaml.read_stream do\n      loop do\n        case yaml.kind\n        when .document_start?\n          json.start_document\n        when .document_end?\n          json.end_document\n          yaml.read_next\n          break\n        when .scalar?\n          string = yaml.value\n\n          if json.next_is_object_key?\n            json.scalar(string)\n          else\n            scalar = ::YAML::Schema::Core.parse_scalar(yaml)\n            case scalar\n            when Nil\n              json.scalar(scalar)\n            when Bool\n              json.scalar(scalar)\n            when Int64\n              json.scalar(scalar)\n            when Float64\n              json.scalar(scalar)\n            else\n              json.scalar(string)\n            end\n          end\n        when .sequence_start?\n          json.start_array\n        when .sequence_end?\n          json.end_array\n        when .mapping_start?\n          json.start_object\n        when .mapping_end?\n          json.end_object\n        end\n        yaml.read_next\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "src/converters/xml.cr",
    "content": "# Converter for the `OQ::Format::XML` format.\nmodule OQ::Converters::XML\n  extend OQ::Converters::ProcessorAware\n\n  def self.deserialize(input : IO, output : IO) : Nil\n    builder = ::JSON::Builder.new output\n    xml = ::XML::Reader.new input\n\n    # Set reader to first element\n    xml.read\n\n    # Raise an error if the document is invalid and could not be read\n    raise ::XML::Error.new LibXML.xmlGetLastError if xml.node_type.none?\n\n    builder.document do\n      builder.object do\n        # Skip non element nodes, i.e. the prolog or DOCTYPE, etc.\n        until xml.node_type.element?\n          xml.read\n        end\n\n        process_element_node xml.expand, builder\n      end\n    end\n  end\n\n  private def self.process_element_node(node : ::XML::Node, builder : ::JSON::Builder) : Nil\n    # If the node doesn't have nested elements nor attributes nor a namespace (with --xmlns); just emit a scalar value\n    if self.scalar_node? node\n      return builder.field self.normalize_node_name(node), get_node_value node\n    end\n\n    # Otherwise process the node as a key/value pair\n    builder.field self.normalize_node_name node do\n      builder.object do\n        process_children node, builder\n      end\n    end\n  end\n\n  private def self.process_array_node(name : String, children : Array(::XML::Node), builder : ::JSON::Builder) : Nil\n    builder.field name do\n      builder.array do\n        children.each do |node|\n          # If the node doesn't have nested elements nor attributes nor a namespace (with --xmlns); just emit a scalar value\n          if self.scalar_node? node\n            builder.scalar get_node_value node\n          else\n            # Otherwise process the node within an object\n            builder.object do\n              process_children node, builder\n            end\n          end\n        end\n      end\n    end\n  end\n\n  private def self.process_children(node : ::XML::Node, builder : ::JSON::Builder) : Nil\n    # Process node attributes\n    node.attributes.each do |attr|\n      builder.field \"@#{attr.name}\", attr.content\n    end\n\n    # Include attributes for namespaces defined on this node\n    # TODO: Make this the default behavior in oq 2.x\n    if self.processor.xmlns?\n      node.namespace_definitions.each do |ns|\n        builder.field \"@#{self.normalize_namespace_prefix ns}\", ns.href\n      end\n    end\n\n    # Determine how to process a node's children\n    node.children.group_by(&->normalize_node_name(::XML::Node)).each do |name, children|\n      # Skip non significant whitespace; Skip mixed character input\n      if children.first.text? && has_nested_elements?(node)\n        # Only emit text content if there is only one child\n        if children.size == 1\n          builder.field \"#text\", children.first.content\n        end\n\n        next\n      end\n\n      # Array\n      if children.size > 1 || self.processor.xml_forced_arrays.includes? name\n        process_array_node name, children, builder\n      else\n        if children.first.text?\n          # node content in attribute object\n          builder.field \"#text\", children.first.content\n        else\n          # Element\n          process_element_node children.first, builder\n        end\n      end\n    end\n  end\n\n  private def self.has_nested_elements?(node : ::XML::Node) : Bool\n    node.children.any? { |child| !child.text? && !child.cdata? }\n  end\n\n  # TODO: Make checking for namespaces the default behavior in oq 2.x\n  private def self.scalar_node?(node : ::XML::Node) : Bool\n    !self.has_nested_elements?(node) && node.attributes.empty? && ((self.processor.xmlns? && node.namespace_definitions.empty?) || !self.processor.xmlns?)\n  end\n\n  private def self.get_node_value(node : ::XML::Node) : String?\n    node.children.empty? ? nil : node.children.first.content\n  end\n\n  private def self.normalize_node_name(node : ::XML::Node) : String\n    return node.name unless namespace = node.namespace\n    (prefix = (self.processor.xml_namespaces[namespace.href]? || namespace.prefix).presence) ? \"#{prefix}:#{node.name}\" : node.name\n  end\n\n  private def self.normalize_namespace_prefix(namespace : ::XML::Namespace) : String\n    (prefix = (self.processor.xml_namespaces[namespace.href]? || namespace.prefix).presence) ? \"xmlns:#{prefix}\" : \"xmlns\"\n  end\n\n  def self.serialize(input : IO, output : IO) : Nil\n    json = ::JSON::PullParser.new input\n    builder = ::XML::Builder.new output\n\n    builder.indent = ((self.processor.tab? ? \"\\t\" : \" \")*self.processor.indent)\n\n    builder.start_document \"1.0\", \"UTF-8\" if self.processor.xml_prolog?\n\n    if root = self.processor.xml_root.presence\n      builder.start_element root\n    end\n\n    loop do\n      emit builder, json\n      break if json.kind.eof?\n    end\n\n    if self.processor.xml_root.presence\n      builder.end_element\n    end\n\n    builder.end_document if self.processor.xml_prolog?\n    builder.flush unless self.processor.xml_prolog?\n  end\n\n  private def self.emit(builder : ::XML::Builder, json : ::JSON::PullParser, key : String? = nil, array_key : String? = nil) : Nil\n    case json.kind\n    when .null?                           then json.read_null\n    when .string?, .int?, .float?, .bool? then builder.text get_value json\n    when .begin_object?                   then handle_object builder, json, key, array_key\n    when .begin_array?                    then handle_array builder, json, key, array_key\n    else\n      nil\n    end\n  end\n\n  private def self.handle_object(builder : ::XML::Builder, json : ::JSON::PullParser, key : String? = nil, array_key : String? = nil) : Nil\n    json.read_object do |k|\n      if k.starts_with?('@')\n        builder.attribute k.lchop('@'), get_value json\n      elsif k.starts_with?('!')\n        builder.element k.lchop('!') do\n          builder.cdata get_value json\n        end\n      elsif json.kind.begin_array? || k == \"#text\"\n        emit builder, json, k, k\n      else\n        builder.element k do\n          emit builder, json, k\n        end\n      end\n    end\n  end\n\n  private def self.handle_array(builder : ::XML::Builder, json : ::JSON::PullParser, key : String? = nil, array_key : String? = nil) : Nil\n    json.read_begin_array\n    array_key = array_key || self.processor.xml_item\n\n    if json.kind.end_array?\n      # If the array is empty don't emit anything\n    else\n      until json.kind.end_array?\n        builder.element array_key do\n          emit builder, json, key\n        end\n      end\n    end\n\n    json.read_end_array\n  end\n\n  private def self.get_value(json : ::JSON::PullParser) : String\n    case json.kind\n    when .string? then json.read_string\n    when .int?    then json.read_int\n    when .float?  then json.read_float\n    when .bool?   then json.read_bool\n    when .null?   then json.read_null\n    else\n      \"\"\n    end.to_s\n  end\nend\n"
  },
  {
    "path": "src/converters/yaml.cr",
    "content": "# Converter for the `OQ::Format::YAML` format.\nmodule OQ::Converters::YAML\n  extend self\n\n  def deserialize(input : IO, output : IO) : Nil\n    ::YAML.parse(input).to_json output\n  end\n\n  # ameba:disable Metrics/CyclomaticComplexity\n  def serialize(input : IO, output : IO) : Nil\n    json = ::JSON::PullParser.new input\n    yaml = ::YAML::Builder.new output\n\n    # Return early is there is no JSON to be read.\n    return if json.kind.eof?\n\n    yaml.stream do\n      yaml.document do\n        loop do\n          case json.kind\n          when .null?\n            yaml.scalar nil\n          when .bool?\n            yaml.scalar json.bool_value\n          when .int?\n            yaml.scalar json.int_value\n          when .float?\n            yaml.scalar json.float_value\n          when .string?\n            if ::YAML::Schema::Core.reserved_string? json.string_value\n              yaml.scalar json.string_value, style: :double_quoted\n            else\n              yaml.scalar json.string_value\n            end\n          when .begin_array?\n            yaml.start_sequence\n          when .end_array?\n            yaml.end_sequence\n          when .begin_object?\n            yaml.start_mapping\n          when .end_object?\n            yaml.end_mapping\n          when .eof?\n            break\n          end\n          json.read_next\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "src/oq.cr",
    "content": "require \"json\"\nrequire \"xml\"\nrequire \"yaml\"\n\nrequire \"./converters/*\"\n\n# A performant, and portable jq wrapper that facilitates the consumption and output of formats other than JSON; using jq filters to transform the data.\nmodule OQ\n  VERSION = \"1.3.5\"\n\n  # The support formats that can be converted to/from.\n  enum Format\n    # The [JSON](https://www.json.org/) format.\n    JSON\n\n    # Same as `YAML`, but does not support [anchors or aliases](https://yaml.org/spec/1.2/spec.html#id2765878);\n    # thus allowing for the input conversion to be streamed, reducing the memory usage for large inputs.\n    SimpleYAML\n\n    # The [XML](https://en.wikipedia.org/wiki/XML) format.\n    #\n    # NOTE: Conversion to and from `JSON` uses [this](https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html) spec.\n    XML\n\n    # The [YAML](https://yaml.org/) format.\n    YAML\n\n    # Returns the list of supported formats.\n    def self.to_s(io : IO) : Nil\n      self.names.join(io, \", \") { |str, join_io| str.downcase join_io }\n    end\n\n    # Maps a given format to its converter.\n    def converter(processor : OQ::Processor)\n      case self\n      in .json?        then OQ::Converters::JSON\n      in .simple_yaml? then OQ::Converters::SimpleYAML\n      in .xml?         then OQ::Converters::XML\n      in .yaml?        then OQ::Converters::YAML\n      end.tap { |converter| converter.processor = processor if converter.is_a? OQ::Converters::ProcessorAware }\n    end\n  end\n\n  # Handles the logic of converting the input format (if needed),\n  # processing it via [jq](https://stedolan.github.io/jq/),\n  # and converting the output format (if needed).\n  #\n  # ```\n  # require \"oq\"\n  #\n  # # This could be any `IO`, e.g. an `HTTP` request body, etc.\n  # input_io = IO::Memory.new %({\"name\":\"Jim\"})\n  #\n  # # Create a processor, specifying that we want the output format to be `YAML`.\n  # processor = OQ::Processor.new output_format: :yaml\n  #\n  # File.open(\"./out.yml\", \"w\") do |file|\n  #   # Process the data using our custom input and output IOs.\n  #   # The first argument represents the input arguments;\n  #   # i.e. the filter and/or any other arguments that should be passed to `jq`.\n  #   processor.process [\".\"], input: input_io, output: file\n  # end\n  # ```\n  class Processor\n    # The format that the input data is in.\n    property input_format : Format\n\n    # The format that the output should be transcoded into.\n    property output_format : Format\n\n    # The root of the XML document when transcoding to XML.\n    property xml_root : String\n\n    # If the XML prolog should be emitted.\n    property? xml_prolog : Bool\n\n    # The name for XML array elements without keys.\n    property xml_item : String\n\n    # The number of spaces to use for indentation.\n    property indent : Int32\n\n    # If a tab for each indentation level instead of spaces.\n    property? tab : Bool\n\n    # Do not read any input, using `null` as the singular input value.\n    property? null : Bool\n\n    # If XML namespaces should be parsed as well.\n    # TODO: Remove this in oq 2.0 as it'll becomethe default.\n    property? xmlns : Bool\n\n    # Mapping to namespace aliases to their related namespace.\n    protected getter xml_namespaces = Hash(String, String).new\n\n    # Set of elements who should be force expanded to an array.\n    protected getter xml_forced_arrays = Set(String).new\n\n    # The args that'll be passed to `jq`.\n    @args : Array(String) = [] of String\n\n    # Keep a reference to the created temp files in order to delete them later.\n    @tmp_files = Set(File).new\n\n    def initialize(\n      @input_format : Format = Format::JSON,\n      @output_format : Format = Format::JSON,\n      @xml_root : String = \"root\",\n      @xml_prolog : Bool = true,\n      @xml_item : String = \"item\",\n      @indent : Int32 = 2,\n      @tab : Bool = false,\n      @null : Bool = false,\n      @xmlns : Bool = false,\n    )\n    end\n\n    @[Deprecated(\"Use `Processor#tab?` instead.\")]\n    def tab : Bool\n      self.tab?\n    end\n\n    @[Deprecated(\"Use `Processor#xml_prolog?` instead.\")]\n    def xml_prolog : Bool\n      self.xml_prolog?\n    end\n\n    # Adds the provided *value* to the internal args array.\n    def add_arg(value : String) : Nil\n      @args << value\n    end\n\n    def add_xml_namespace(prefix : String, href : String) : Nil\n      @xml_namespaces[href] = prefix\n    end\n\n    def add_forced_array(name : String) : Nil\n      xml_forced_arrays << name\n    end\n\n    # Consumes `#input_format` data from the provided *input* `IO`, along with any *input_args*.\n    # The data is then converted to `JSON`, passed to `jq`, and then converted to `#output_format` while being written to the *output* `IO`.\n    # Any errors are written to the *error* `IO`.\n    def process(input_args : Array(String) = ARGV, input : IO = ARGF, output : IO = STDOUT, error : IO = STDERR) : Nil\n      # Register an at_exit handler to cleanup temp files.\n      at_exit { @tmp_files.each &.delete }\n\n      # Parse out --rawfile, --argfile, --slurpfile,-f/--from-file, and -L before processing additional args\n      # since these options use a file that should not be used as input.\n      self.consume_file_args input_args, \"--rawfile\", \"--argfile\", \"--slurpfile\"\n      self.consume_file_args input_args, \"-f\", \"--from-file\", \"-L\", count: 1\n\n      # Also parse out --arg, and --argjson as they may include identifiers that also exist as a directory/file\n      # which would result in incorrect arg extraction.\n      self.consume_file_args input_args, \"--arg\", \"--argjson\"\n\n      # Extract `jq` arguments from `ARGV`.\n      self.extract_args input_args, output\n\n      # The --xml-namespace-alias option must be used with the --xmlns option.\n      # TODO: Remove this in oq 2.x\n      raise ArgumentError.new \"The `--xml-namespace-alias` option must be used with the `--xmlns` option.\" if !@xmlns && !@xml_namespaces.empty?\n\n      # Replace the *input* with a fake `ARGF` `IO` to handle both file and `IO` inputs in case `ARGV` is not being used for the input arguments.\n      #\n      # If using `null` input, set the input to an empty memory `IO` to essentially consume nothing.\n      input = @null ? IO::Memory.new : IO::ARGF.new input_args, input\n\n      input_read, input_write = IO.pipe\n      output_read, output_write = IO.pipe\n\n      channel = Channel(Bool | Exception).new\n\n      # If the input format is not JSON and there is more than 1 file in ARGV,\n      # convert each file to JSON from the `#input_format` and save it to a temp file.\n      # Then replace ARGV with the temp files.\n      if !@input_format.json? && input_args.size > 1\n        input_args.replace(input_args.map do |file_name|\n          File.tempfile \".#{File.basename file_name}\" do |tmp_file|\n            File.open file_name do |file|\n              @input_format.converter(self).deserialize file, tmp_file\n            end\n          end\n            .tap { |tf| @tmp_files << tf }\n            .path\n        end)\n\n        # Conversion has already been completed by this point, so reset input format back to JSON.\n        @input_format = :json\n      end\n\n      spawn do\n        @input_format.converter(self).deserialize input, input_write\n        input_write.close\n        channel.send true\n      rescue ex\n        input_write.close\n        channel.send ex\n      end\n\n      spawn do\n        output_write.close\n        @output_format.converter(self).serialize output_read, output\n        channel.send true\n      rescue ex\n        channel.send ex\n      end\n\n      run = Process.run(\n        \"jq\",\n        @args,\n        input: input_read,\n        output: output_write,\n        error: error\n      )\n\n      unless run.success?\n        # Raise this to represent a jq error.\n        # jq writes its errors directly to the *error* IO so no need to include a message.\n        raise RuntimeError.new\n      end\n\n      2.times do\n        case v = channel.receive\n        when Exception then raise v\n        end\n      end\n    end\n\n    # Parses the *input_args*, extracting `jq` arguments while leaving files\n    private def extract_args(input_args : Array(String), output : IO) : Nil\n      # Add color option if *output* is a tty\n      # and the output format is JSON\n      # (Since it will go straight to *output* and not converted)\n      input_args.unshift \"-C\" if output.tty? && @output_format.json? && !input_args.includes? \"-C\"\n\n      # If the -C option was explicitly included\n      # and the output format is not JSON;\n      # remove it from *input_args* to prevent\n      # conversion errors\n      input_args.delete(\"-C\") if !@output_format.json?\n\n      # If there are any files within the *input_args*, ignore \".\" as it's both a valid file and filter\n      idx = if first_file_idx = input_args.index { |a| a != \".\" && File.exists? a }\n              # extract everything else\n              first_file_idx - 1\n            else\n              # otherwise just take it all\n              -1\n            end\n\n      @args.concat input_args.delete_at 0..idx\n    end\n\n    # Extracts *arg_name* from the provided *input_args* if it exists;\n    # concatenating the result to the internal arg array.\n    private def consume_file_arg(input_args : Array(String), arg_name : String, count : Int32 = 2) : Nil\n      input_args.index(arg_name).try { |idx| @args.concat input_args.delete_at idx..(idx + count) }\n    end\n\n    private def consume_file_args(input_args : Array(String), *arg_names : String, count : Int32 = 2) : Nil\n      arg_names.each { |name| consume_file_arg input_args, name, count }\n    end\n  end\nend\n"
  },
  {
    "path": "src/oq_cli.cr",
    "content": "require \"option_parser\"\n\nrequire \"./oq\"\n\nprocessor = OQ::Processor.new\n\nOptionParser.parse do |parser|\n  parser.banner = \"Usage: oq [--help] [oq-arguments] [jq-arguments] jq_filter [file [files...]]\"\n  parser.on(\"-h\", \"--help\", \"Show this help message.\") do\n    output = IO::Memory.new\n    version = IO::Memory.new\n\n    Process.run(\"jq\", [\"-h\"], output: output)\n    Process.run(\"jq\", [\"--version\"], output: version)\n\n    puts \"oq version: #{OQ::VERSION}, jq version: #{version}\", parser, output.to_s.lines.map(&.gsub('\\t', \"    \")).tap(&.delete_at(0..1)).join('\\n')\n    exit\n  end\n  parser.on(\"-V\", \"--version\", \"Returns the current versions of oq and jq.\") do\n    output = IO::Memory.new\n\n    Process.run(\"jq\", [\"--version\"], output: output)\n\n    puts \"jq: #{output}\", \"oq: #{OQ::VERSION}\"\n    exit\n  end\n  parser.on(\"-i FORMAT\", \"--input FORMAT\", \"Format of the input data. Supported formats: #{OQ::Format}\") { |format| (f = OQ::Format.parse?(format)) ? processor.input_format = f : abort \"Invalid input format: '#{format}'\" }\n  parser.on(\"-o FORMAT\", \"--output FORMAT\", \"Format of the output data. Supported formats: #{OQ::Format}\") { |format| (f = OQ::Format.parse?(format)) ? processor.output_format = f : abort \"Invalid output format: '#{format}'\" }\n  parser.on(\"--indent NUMBER\", \"Use the given number of spaces for indentation (JSON/XML only).\") { |n| processor.indent = n.to_i; processor.add_arg \"--indent\"; processor.add_arg n }\n  parser.on(\"--tab\", \"Use a tab for each indentation level instead of two spaces.\") { processor.tab = true; processor.add_arg \"--tab\" }\n  parser.on(\"-n\", \"--null-input\", \"Don't read any input at all, running the filter once using `null` as the input.\") { processor.null = true; processor.add_arg \"--null-input\" }\n  parser.on(\"--no-prolog\", \"Whether the XML prolog should be emitted if converting to XML.\") { processor.xml_prolog = false }\n  parser.on(\"--xml-item NAME\", \"The name for XML array elements without keys.\") { |i| processor.xml_item = i }\n  parser.on(\"--xmlns\", \"If XML namespaces should be parsed.  NOTE: This will become the default in oq 2.x.\") { processor.xmlns = true }\n  parser.on(\"--xml-force-array NAME\", \"Forces an element with the provided name to be parsed as an array even if it only contains one item.\") { |n| processor.add_forced_array n }\n  parser.on(\"--xml-namespace-alias ALIAS\", \"Value should be in the form of: `key=namespace`. Elements within the provided namespace are normalized to the provided key.  NOTE: Requires the `--xmlns` option to be passed as well.\") { |a| k, v = a.split('=', 2); processor.add_xml_namespace k, v }\n  parser.on(\"--xml-root ROOT\", \"Name of the root XML element if converting to XML.\") { |r| processor.xml_root = r }\n  parser.invalid_option { }\nend\n\nbegin\n  processor.process\nrescue ex : RuntimeError\n  # ignore jq errors as it writes directly to error output.\n  exit 1\nrescue ex\n  abort \"oq error: #{ex.message}\"\nend\n"
  }
]